Mercurial > projects > ldc
comparison gen/statements.cpp @ 86:fd32135dca3e trunk
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
Lots of bugfixes.
Added support for special foreach on strings.
Added std.array, std.utf, std.ctype and std.uni to phobos.
Changed all the .c files in the gen dir to .cpp (it *is* C++ after all)
author | lindquist |
---|---|
date | Sat, 03 Nov 2007 14:44:58 +0100 |
parents | gen/statements.c@d8dd47ef3973 |
children | 61615fa85940 |
comparison
equal
deleted
inserted
replaced
85:f869c636a113 | 86:fd32135dca3e |
---|---|
1 // Statements: D -> LLVM glue | |
2 | |
3 #include <stdio.h> | |
4 #include <math.h> | |
5 #include <sstream> | |
6 #include <fstream> | |
7 #include <iostream> | |
8 | |
9 #include "gen/llvm.h" | |
10 #include "llvm/Transforms/Utils/Cloning.h" | |
11 | |
12 #include "total.h" | |
13 #include "init.h" | |
14 #include "symbol.h" | |
15 #include "mtype.h" | |
16 #include "hdrgen.h" | |
17 #include "port.h" | |
18 | |
19 #include "gen/irstate.h" | |
20 #include "gen/elem.h" | |
21 #include "gen/logger.h" | |
22 #include "gen/tollvm.h" | |
23 #include "gen/runtime.h" | |
24 #include "gen/arrays.h" | |
25 #include "gen/todebug.h" | |
26 #include "gen/dvalue.h" | |
27 | |
28 ////////////////////////////////////////////////////////////////////////////// | |
29 | |
30 void CompoundStatement::toIR(IRState* p) | |
31 { | |
32 static int csi = 0; | |
33 Logger::println("CompoundStatement::toIR(%d):\n<<<\n%s>>>", csi++, toChars()); | |
34 LOG_SCOPE; | |
35 | |
36 for (int i=0; i<statements->dim; i++) | |
37 { | |
38 Statement* s = (Statement*)statements->data[i]; | |
39 if (s) | |
40 s->toIR(p); | |
41 else { | |
42 Logger::println("*** ATTENTION: null statement found in CompoundStatement"); | |
43 //assert(0); | |
44 } | |
45 } | |
46 } | |
47 | |
48 ////////////////////////////////////////////////////////////////////////////// | |
49 | |
50 void ReturnStatement::toIR(IRState* p) | |
51 { | |
52 static int rsi = 0; | |
53 Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars()); | |
54 LOG_SCOPE; | |
55 | |
56 if (exp) | |
57 { | |
58 Logger::println("return type is: %s", exp->type->toChars()); | |
59 | |
60 Type* exptype = DtoDType(exp->type); | |
61 TY expty = exptype->ty; | |
62 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { | |
63 assert(DtoIsPassedByRef(exptype)); | |
64 | |
65 TypeFunction* f = p->topfunctype(); | |
66 assert(f->llvmRetInPtr && f->llvmRetArg); | |
67 | |
68 if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum); | |
69 | |
70 DValue* rvar = new DVarValue(f->next, f->llvmRetArg, true); | |
71 | |
72 p->exps.push_back(IRExp(NULL,exp,rvar)); | |
73 DValue* e = exp->toElem(p); | |
74 p->exps.pop_back(); | |
75 | |
76 if (!e->inPlace()) | |
77 DtoAssign(rvar, e); | |
78 | |
79 IRFunction::FinallyVec& fin = p->func().finallys; | |
80 if (fin.empty()) { | |
81 if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl); | |
82 new llvm::ReturnInst(p->scopebb()); | |
83 } | |
84 else { | |
85 new llvm::BranchInst(fin.back().retbb, p->scopebb()); | |
86 } | |
87 } | |
88 else { | |
89 if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum); | |
90 DValue* e = exp->toElem(p); | |
91 llvm::Value* v = e->getRVal(); | |
92 delete e; | |
93 Logger::cout() << "return value is '" <<*v << "'\n"; | |
94 | |
95 IRFunction::FinallyVec& fin = p->func().finallys; | |
96 if (fin.empty()) { | |
97 if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl); | |
98 new llvm::ReturnInst(v, p->scopebb()); | |
99 } | |
100 else { | |
101 if (!p->func().finallyretval) | |
102 p->func().finallyretval = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint()); | |
103 llvm::Value* rettmp = p->func().finallyretval; | |
104 new llvm::StoreInst(v,rettmp,p->scopebb()); | |
105 new llvm::BranchInst(fin.back().retbb, p->scopebb()); | |
106 } | |
107 } | |
108 } | |
109 else | |
110 { | |
111 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { | |
112 IRFunction::FinallyVec& fin = p->func().finallys; | |
113 if (fin.empty()) { | |
114 if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl); | |
115 new llvm::ReturnInst(p->scopebb()); | |
116 } | |
117 else { | |
118 new llvm::BranchInst(fin.back().retbb, p->scopebb()); | |
119 } | |
120 } | |
121 else { | |
122 assert(0); // why should this ever happen? | |
123 new llvm::UnreachableInst(p->scopebb()); | |
124 } | |
125 } | |
126 } | |
127 | |
128 ////////////////////////////////////////////////////////////////////////////// | |
129 | |
130 void ExpStatement::toIR(IRState* p) | |
131 { | |
132 static int esi = 0; | |
133 Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars()); | |
134 LOG_SCOPE; | |
135 | |
136 if (global.params.symdebug) | |
137 DtoDwarfStopPoint(loc.linnum); | |
138 | |
139 if (exp != 0) { | |
140 elem* e = exp->toElem(p); | |
141 delete e; | |
142 } | |
143 /*elem* e = exp->toElem(p); | |
144 p->buf.printf("%s", e->toChars()); | |
145 delete e; | |
146 p->buf.writenl();*/ | |
147 } | |
148 | |
149 ////////////////////////////////////////////////////////////////////////////// | |
150 | |
151 void IfStatement::toIR(IRState* p) | |
152 { | |
153 static int wsi = 0; | |
154 Logger::println("IfStatement::toIR(%d): %s", wsi++, toChars()); | |
155 LOG_SCOPE; | |
156 | |
157 DValue* cond_e = condition->toElem(p); | |
158 llvm::Value* cond_val = cond_e->getRVal(); | |
159 delete cond_e; | |
160 | |
161 llvm::BasicBlock* oldend = gIR->scopeend(); | |
162 | |
163 llvm::BasicBlock* ifbb = new llvm::BasicBlock("if", gIR->topfunc(), oldend); | |
164 llvm::BasicBlock* endbb = new llvm::BasicBlock("endif", gIR->topfunc(), oldend); | |
165 llvm::BasicBlock* elsebb = elsebody ? new llvm::BasicBlock("else", gIR->topfunc(), endbb) : endbb; | |
166 | |
167 if (cond_val->getType() != llvm::Type::Int1Ty) { | |
168 Logger::cout() << "if conditional: " << *cond_val << '\n'; | |
169 cond_val = DtoBoolean(cond_val); | |
170 } | |
171 llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebegin()); | |
172 | |
173 // replace current scope | |
174 gIR->scope() = IRScope(ifbb,elsebb); | |
175 | |
176 // do scoped statements | |
177 ifbody->toIR(p); | |
178 if (!gIR->scopereturned()) { | |
179 new llvm::BranchInst(endbb,gIR->scopebegin()); | |
180 } | |
181 | |
182 if (elsebody) { | |
183 //assert(0); | |
184 gIR->scope() = IRScope(elsebb,endbb); | |
185 elsebody->toIR(p); | |
186 if (!gIR->scopereturned()) { | |
187 new llvm::BranchInst(endbb,gIR->scopebegin()); | |
188 } | |
189 } | |
190 | |
191 // rewrite the scope | |
192 gIR->scope() = IRScope(endbb,oldend); | |
193 } | |
194 | |
195 ////////////////////////////////////////////////////////////////////////////// | |
196 | |
197 void ScopeStatement::toIR(IRState* p) | |
198 { | |
199 Logger::println("ScopeStatement::toIR(): %s", toChars()); | |
200 LOG_SCOPE; | |
201 | |
202 llvm::BasicBlock* oldend = p->scopeend(); | |
203 | |
204 llvm::BasicBlock* beginbb = 0; | |
205 | |
206 // remove useless branches by clearing and reusing the current basicblock | |
207 llvm::BasicBlock* bb = p->scopebegin(); | |
208 if (bb->empty()) { | |
209 beginbb = bb; | |
210 } | |
211 else { | |
212 assert(!p->scopereturned()); | |
213 beginbb = new llvm::BasicBlock("scope", p->topfunc(), oldend); | |
214 new llvm::BranchInst(beginbb, p->scopebegin()); | |
215 } | |
216 llvm::BasicBlock* endbb = new llvm::BasicBlock("endscope", p->topfunc(), oldend); | |
217 | |
218 gIR->scope() = IRScope(beginbb, endbb); | |
219 | |
220 statement->toIR(p); | |
221 | |
222 p->scope() = IRScope(p->scopebb(),oldend); | |
223 endbb->eraseFromParent(); | |
224 } | |
225 | |
226 ////////////////////////////////////////////////////////////////////////////// | |
227 | |
228 void WhileStatement::toIR(IRState* p) | |
229 { | |
230 static int wsi = 0; | |
231 Logger::println("WhileStatement::toIR(%d): %s", wsi++, toChars()); | |
232 LOG_SCOPE; | |
233 | |
234 // create while blocks | |
235 llvm::BasicBlock* oldend = gIR->scopeend(); | |
236 llvm::BasicBlock* whilebb = new llvm::BasicBlock("whilecond", gIR->topfunc(), oldend); | |
237 llvm::BasicBlock* whilebodybb = new llvm::BasicBlock("whilebody", gIR->topfunc(), oldend); | |
238 llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend); | |
239 | |
240 // move into the while block | |
241 p->ir->CreateBr(whilebb); | |
242 //new llvm::BranchInst(whilebb, gIR->scopebegin()); | |
243 | |
244 // replace current scope | |
245 gIR->scope() = IRScope(whilebb,endbb); | |
246 | |
247 // create the condition | |
248 DValue* cond_e = condition->toElem(p); | |
249 llvm::Value* cond_val = DtoBoolean(cond_e->getRVal()); | |
250 delete cond_e; | |
251 | |
252 // conditional branch | |
253 llvm::Value* ifbreak = new llvm::BranchInst(whilebodybb, endbb, cond_val, p->scopebb()); | |
254 | |
255 // rewrite scope | |
256 gIR->scope() = IRScope(whilebodybb,endbb); | |
257 | |
258 // do while body code | |
259 body->toIR(p); | |
260 | |
261 // loop | |
262 new llvm::BranchInst(whilebb, gIR->scopebegin()); | |
263 | |
264 // rewrite the scope | |
265 gIR->scope() = IRScope(endbb,oldend); | |
266 } | |
267 | |
268 ////////////////////////////////////////////////////////////////////////////// | |
269 | |
270 void DoStatement::toIR(IRState* p) | |
271 { | |
272 static int wsi = 0; | |
273 Logger::println("DoStatement::toIR(%d): %s", wsi++, toChars()); | |
274 LOG_SCOPE; | |
275 | |
276 // create while blocks | |
277 llvm::BasicBlock* oldend = gIR->scopeend(); | |
278 llvm::BasicBlock* dowhilebb = new llvm::BasicBlock("dowhile", gIR->topfunc(), oldend); | |
279 llvm::BasicBlock* endbb = new llvm::BasicBlock("enddowhile", gIR->topfunc(), oldend); | |
280 | |
281 // move into the while block | |
282 new llvm::BranchInst(dowhilebb, gIR->scopebegin()); | |
283 | |
284 // replace current scope | |
285 gIR->scope() = IRScope(dowhilebb,endbb); | |
286 | |
287 // do do-while body code | |
288 body->toIR(p); | |
289 | |
290 // create the condition | |
291 DValue* cond_e = condition->toElem(p); | |
292 llvm::Value* cond_val = DtoBoolean(cond_e->getRVal()); | |
293 delete cond_e; | |
294 | |
295 // conditional branch | |
296 llvm::Value* ifbreak = new llvm::BranchInst(dowhilebb, endbb, cond_val, gIR->scopebegin()); | |
297 | |
298 // rewrite the scope | |
299 gIR->scope() = IRScope(endbb,oldend); | |
300 } | |
301 | |
302 ////////////////////////////////////////////////////////////////////////////// | |
303 | |
304 void ForStatement::toIR(IRState* p) | |
305 { | |
306 static int wsi = 0; | |
307 Logger::println("ForStatement::toIR(%d): %s", wsi++, toChars()); | |
308 LOG_SCOPE; | |
309 | |
310 // create for blocks | |
311 llvm::BasicBlock* oldend = gIR->scopeend(); | |
312 llvm::BasicBlock* forbb = new llvm::BasicBlock("forcond", gIR->topfunc(), oldend); | |
313 llvm::BasicBlock* forbodybb = new llvm::BasicBlock("forbody", gIR->topfunc(), oldend); | |
314 llvm::BasicBlock* forincbb = new llvm::BasicBlock("forinc", gIR->topfunc(), oldend); | |
315 llvm::BasicBlock* endbb = new llvm::BasicBlock("endfor", gIR->topfunc(), oldend); | |
316 | |
317 // init | |
318 if (init != 0) | |
319 init->toIR(p); | |
320 | |
321 // move into the for condition block, ie. start the loop | |
322 new llvm::BranchInst(forbb, gIR->scopebegin()); | |
323 | |
324 p->loopbbs.push_back(IRScope(forincbb,endbb)); | |
325 | |
326 // replace current scope | |
327 gIR->scope() = IRScope(forbb,forbodybb); | |
328 | |
329 // create the condition | |
330 DValue* cond_e = condition->toElem(p); | |
331 llvm::Value* cond_val = DtoBoolean(cond_e->getRVal()); | |
332 delete cond_e; | |
333 | |
334 // conditional branch | |
335 llvm::Value* ifbreak = new llvm::BranchInst(forbodybb, endbb, cond_val, forbb); | |
336 | |
337 // rewrite scope | |
338 gIR->scope() = IRScope(forbodybb,forincbb); | |
339 | |
340 // do for body code | |
341 body->toIR(p); | |
342 | |
343 // move into the for increment block | |
344 new llvm::BranchInst(forincbb, gIR->scopebegin()); | |
345 gIR->scope() = IRScope(forincbb, endbb); | |
346 | |
347 // increment | |
348 if (increment) { | |
349 DValue* inc = increment->toElem(p); | |
350 delete inc; | |
351 } | |
352 | |
353 // loop | |
354 new llvm::BranchInst(forbb, gIR->scopebegin()); | |
355 | |
356 p->loopbbs.pop_back(); | |
357 | |
358 // rewrite the scope | |
359 gIR->scope() = IRScope(endbb,oldend); | |
360 } | |
361 | |
362 ////////////////////////////////////////////////////////////////////////////// | |
363 | |
364 void BreakStatement::toIR(IRState* p) | |
365 { | |
366 static int wsi = 0; | |
367 Logger::println("BreakStatement::toIR(%d): %s", wsi++, toChars()); | |
368 LOG_SCOPE; | |
369 | |
370 if (ident != 0) { | |
371 Logger::println("ident = %s", ident->toChars()); | |
372 assert(0); | |
373 } | |
374 else { | |
375 new llvm::BranchInst(gIR->loopbbs.back().end, gIR->scopebegin()); | |
376 } | |
377 } | |
378 | |
379 ////////////////////////////////////////////////////////////////////////////// | |
380 | |
381 void ContinueStatement::toIR(IRState* p) | |
382 { | |
383 static int wsi = 0; | |
384 Logger::println("ContinueStatement::toIR(%d): %s", wsi++, toChars()); | |
385 LOG_SCOPE; | |
386 | |
387 if (ident != 0) { | |
388 Logger::println("ident = %s", ident->toChars()); | |
389 assert(0); | |
390 } | |
391 else { | |
392 new llvm::BranchInst(gIR->loopbbs.back().begin, gIR->scopebegin()); | |
393 } | |
394 } | |
395 | |
396 ////////////////////////////////////////////////////////////////////////////// | |
397 | |
398 void OnScopeStatement::toIR(IRState* p) | |
399 { | |
400 static int wsi = 0; | |
401 Logger::println("OnScopeStatement::toIR(%d): %s", wsi++, toChars()); | |
402 LOG_SCOPE; | |
403 | |
404 assert(statement); | |
405 //statement->toIR(p); // this seems to be redundant | |
406 } | |
407 | |
408 ////////////////////////////////////////////////////////////////////////////// | |
409 | |
410 static void replaceFinallyBBs(std::vector<llvm::BasicBlock*>& a, std::vector<llvm::BasicBlock*>& b) | |
411 { | |
412 } | |
413 | |
414 void TryFinallyStatement::toIR(IRState* p) | |
415 { | |
416 Logger::println("TryFinallyStatement::toIR(): %s", toChars()); | |
417 LOG_SCOPE; | |
418 | |
419 // create basic blocks | |
420 llvm::BasicBlock* oldend = p->scopeend(); | |
421 | |
422 llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend); | |
423 llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend); | |
424 llvm::BasicBlock* finallyretbb = new llvm::BasicBlock("finallyreturn", p->topfunc(), oldend); | |
425 llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend); | |
426 | |
427 // pass the previous BB into this | |
428 assert(!gIR->scopereturned()); | |
429 new llvm::BranchInst(trybb, p->scopebb()); | |
430 | |
431 // do the try block | |
432 p->scope() = IRScope(trybb,finallybb); | |
433 gIR->func().finallys.push_back(IRFinally(finallybb,finallyretbb)); | |
434 IRFinally& fin = p->func().finallys.back(); | |
435 | |
436 assert(body); | |
437 body->toIR(p); | |
438 | |
439 // terminate try BB | |
440 if (!p->scopereturned()) | |
441 new llvm::BranchInst(finallybb, p->scopebb()); | |
442 | |
443 // do finally block | |
444 p->scope() = IRScope(finallybb,finallyretbb); | |
445 assert(finalbody); | |
446 finalbody->toIR(p); | |
447 | |
448 // terminate finally | |
449 if (!gIR->scopereturned()) { | |
450 new llvm::BranchInst(endbb, p->scopebb()); | |
451 } | |
452 | |
453 // do finally block (return path) | |
454 p->scope() = IRScope(finallyretbb,endbb); | |
455 assert(finalbody); | |
456 finalbody->toIR(p); // hope this will work, otherwise it's time it gets fixed | |
457 | |
458 // terminate finally (return path) | |
459 size_t nfin = p->func().finallys.size(); | |
460 if (nfin > 1) { | |
461 IRFinally& ofin = p->func().finallys[nfin-2]; | |
462 p->ir->CreateBr(ofin.retbb); | |
463 } | |
464 // no outer | |
465 else | |
466 { | |
467 if (global.params.symdebug) DtoDwarfFuncEnd(p->func().decl); | |
468 llvm::Value* retval = p->func().finallyretval; | |
469 if (retval) { | |
470 retval = p->ir->CreateLoad(retval,"tmp"); | |
471 p->ir->CreateRet(retval); | |
472 } | |
473 else { | |
474 FuncDeclaration* fd = p->func().decl; | |
475 if (fd->isMain()) { | |
476 assert(fd->type->next->ty == Tvoid); | |
477 p->ir->CreateRet(DtoConstInt(0)); | |
478 } | |
479 else { | |
480 p->ir->CreateRetVoid(); | |
481 } | |
482 } | |
483 } | |
484 | |
485 // rewrite the scope | |
486 p->func().finallys.pop_back(); | |
487 p->scope() = IRScope(endbb,oldend); | |
488 } | |
489 | |
490 ////////////////////////////////////////////////////////////////////////////// | |
491 | |
492 void TryCatchStatement::toIR(IRState* p) | |
493 { | |
494 static int wsi = 0; | |
495 Logger::println("TryCatchStatement::toIR(%d): %s", wsi++, toChars()); | |
496 LOG_SCOPE; | |
497 | |
498 Logger::println("*** ATTENTION: try-catch is not yet fully implemented, only the try block will be emitted."); | |
499 | |
500 assert(body); | |
501 body->toIR(p); | |
502 | |
503 /*assert(catches); | |
504 for(size_t i=0; i<catches->dim; ++i) | |
505 { | |
506 Catch* c = (Catch*)catches->data[i]; | |
507 c->handler->toIR(p); | |
508 }*/ | |
509 } | |
510 | |
511 ////////////////////////////////////////////////////////////////////////////// | |
512 | |
513 void ThrowStatement::toIR(IRState* p) | |
514 { | |
515 static int wsi = 0; | |
516 Logger::println("ThrowStatement::toIR(%d): %s", wsi++, toChars()); | |
517 LOG_SCOPE; | |
518 | |
519 Logger::println("*** ATTENTION: throw is not yet implemented, replacing expression with assert(0);"); | |
520 | |
521 llvm::Value* line = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false); | |
522 DtoAssert(NULL, line, NULL); | |
523 | |
524 /* | |
525 assert(exp); | |
526 DValue* e = exp->toElem(p); | |
527 delete e; | |
528 */ | |
529 } | |
530 | |
531 ////////////////////////////////////////////////////////////////////////////// | |
532 | |
533 void SwitchStatement::toIR(IRState* p) | |
534 { | |
535 Logger::println("SwitchStatement::toIR(): %s", toChars()); | |
536 LOG_SCOPE; | |
537 | |
538 llvm::BasicBlock* oldend = gIR->scopeend(); | |
539 | |
540 // collect the needed cases | |
541 typedef std::pair<llvm::BasicBlock*, llvm::ConstantInt*> CasePair; | |
542 std::vector<CasePair> vcases; | |
543 for (int i=0; i<cases->dim; ++i) | |
544 { | |
545 CaseStatement* cs = (CaseStatement*)cases->data[i]; | |
546 | |
547 // get the case value | |
548 DValue* e = cs->exp->toElem(p); | |
549 DConstValue* ce = e->isConst(); | |
550 assert(ce && llvm::isa<llvm::ConstantInt>(ce->c)); | |
551 llvm::ConstantInt* ec = llvm::cast<llvm::ConstantInt>(ce->c); | |
552 delete e; | |
553 | |
554 // create the case bb with a nice label | |
555 std::string lblname("case"+std::string(cs->exp->toChars())); | |
556 llvm::BasicBlock* bb = new llvm::BasicBlock(lblname, p->topfunc(), oldend); | |
557 | |
558 vcases.push_back(CasePair(bb,ec)); | |
559 } | |
560 | |
561 // default | |
562 llvm::BasicBlock* defbb = 0; | |
563 if (!hasNoDefault) { | |
564 defbb = new llvm::BasicBlock("default", p->topfunc(), oldend); | |
565 } | |
566 | |
567 // end (break point) | |
568 llvm::BasicBlock* endbb = new llvm::BasicBlock("switchend", p->topfunc(), oldend); | |
569 | |
570 // condition var | |
571 DValue* cond = condition->toElem(p); | |
572 llvm::SwitchInst* si = new llvm::SwitchInst(cond->getRVal(), defbb ? defbb : endbb, cases->dim, p->scopebb()); | |
573 delete cond; | |
574 | |
575 // add the cases | |
576 size_t n = vcases.size(); | |
577 for (size_t i=0; i<n; ++i) | |
578 { | |
579 si->addCase(vcases[i].second, vcases[i].first); | |
580 } | |
581 | |
582 // insert case statements | |
583 for (size_t i=0; i<n; ++i) | |
584 { | |
585 llvm::BasicBlock* nextbb = (i == n-1) ? (defbb ? defbb : endbb) : vcases[i+1].first; | |
586 p->scope() = IRScope(vcases[i].first,nextbb); | |
587 | |
588 p->loopbbs.push_back(IRScope(p->scopebb(),endbb)); | |
589 static_cast<CaseStatement*>(cases->data[i])->statement->toIR(p); | |
590 p->loopbbs.pop_back(); | |
591 | |
592 llvm::BasicBlock* curbb = p->scopebb(); | |
593 if (curbb->empty() || !curbb->back().isTerminator()) | |
594 { | |
595 new llvm::BranchInst(nextbb, curbb); | |
596 } | |
597 } | |
598 | |
599 // default statement | |
600 if (defbb) | |
601 { | |
602 p->scope() = IRScope(defbb,endbb); | |
603 p->loopbbs.push_back(IRScope(defbb,endbb)); | |
604 Logger::println("doing default statement"); | |
605 sdefault->statement->toIR(p); | |
606 p->loopbbs.pop_back(); | |
607 | |
608 llvm::BasicBlock* curbb = p->scopebb(); | |
609 if (curbb->empty() || !curbb->back().isTerminator()) | |
610 { | |
611 new llvm::BranchInst(endbb, curbb); | |
612 } | |
613 } | |
614 | |
615 gIR->scope() = IRScope(endbb,oldend); | |
616 } | |
617 | |
618 ////////////////////////////////////////////////////////////////////////////// | |
619 | |
620 void UnrolledLoopStatement::toIR(IRState* p) | |
621 { | |
622 Logger::println("UnrolledLoopStatement::toIR(): %s", toChars()); | |
623 LOG_SCOPE; | |
624 | |
625 llvm::BasicBlock* oldend = gIR->scopeend(); | |
626 llvm::BasicBlock* endbb = new llvm::BasicBlock("unrolledend", p->topfunc(), oldend); | |
627 | |
628 p->scope() = IRScope(p->scopebb(),endbb); | |
629 p->loopbbs.push_back(IRScope(p->scopebb(),endbb)); | |
630 | |
631 for (int i=0; i<statements->dim; ++i) | |
632 { | |
633 Statement* s = (Statement*)statements->data[i]; | |
634 s->toIR(p); | |
635 } | |
636 | |
637 p->loopbbs.pop_back(); | |
638 | |
639 new llvm::BranchInst(endbb, p->scopebb()); | |
640 p->scope() = IRScope(endbb,oldend); | |
641 } | |
642 | |
643 ////////////////////////////////////////////////////////////////////////////// | |
644 | |
645 void ForeachStatement::toIR(IRState* p) | |
646 { | |
647 Logger::println("ForeachStatement::toIR(): %s", toChars()); | |
648 LOG_SCOPE; | |
649 | |
650 //assert(arguments->dim == 1); | |
651 assert(value != 0); | |
652 assert(body != 0); | |
653 assert(aggr != 0); | |
654 assert(func != 0); | |
655 | |
656 //Argument* arg = (Argument*)arguments->data[0]; | |
657 //Logger::println("Argument is %s", arg->toChars()); | |
658 | |
659 Logger::println("aggr = %s", aggr->toChars()); | |
660 Logger::println("func = %s", func->toChars()); | |
661 | |
662 DValue* arr = aggr->toElem(p); | |
663 llvm::Value* val = 0; | |
664 if (!arr->isSlice()) { | |
665 val = arr->getRVal(); | |
666 Logger::cout() << "aggr2llvm = " << *val << '\n'; | |
667 } | |
668 | |
669 llvm::Value* numiters = 0; | |
670 | |
671 const llvm::Type* keytype = key ? DtoType(key->type) : DtoSize_t(); | |
672 llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint()); | |
673 if (key) key->llvmValue = keyvar; | |
674 | |
675 const llvm::Type* valtype = DtoType(value->type); | |
676 llvm::Value* valvar = !(value->isRef() || value->isOut()) ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL; | |
677 | |
678 Type* aggrtype = DtoDType(aggr->type); | |
679 if (aggrtype->ty == Tsarray) | |
680 { | |
681 assert(llvm::isa<llvm::PointerType>(val->getType())); | |
682 assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0))); | |
683 size_t n = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements(); | |
684 assert(n > 0); | |
685 numiters = llvm::ConstantInt::get(keytype,n,false); | |
686 } | |
687 else if (aggrtype->ty == Tarray) | |
688 { | |
689 if (DSliceValue* slice = arr->isSlice()) { | |
690 numiters = slice->len; | |
691 val = slice->ptr; | |
692 } | |
693 else { | |
694 numiters = p->ir->CreateLoad(DtoGEPi(val,0,0,"tmp",p->scopebb())); | |
695 val = p->ir->CreateLoad(DtoGEPi(val,0,1,"tmp",p->scopebb())); | |
696 } | |
697 } | |
698 else | |
699 { | |
700 assert(0 && "aggregate type is not Tarray or Tsarray"); | |
701 } | |
702 | |
703 if (op == TOKforeach) { | |
704 new llvm::StoreInst(llvm::ConstantInt::get(keytype,0,false), keyvar, p->scopebb()); | |
705 } | |
706 else if (op == TOKforeach_reverse) { | |
707 llvm::Value* v = llvm::BinaryOperator::createSub(numiters, llvm::ConstantInt::get(keytype,1,false),"tmp",p->scopebb()); | |
708 new llvm::StoreInst(v, keyvar, p->scopebb()); | |
709 } | |
710 | |
711 delete arr; | |
712 | |
713 llvm::BasicBlock* oldend = gIR->scopeend(); | |
714 llvm::BasicBlock* nexbb = new llvm::BasicBlock("foreachnext", p->topfunc(), oldend); | |
715 llvm::BasicBlock* begbb = new llvm::BasicBlock("foreachbegin", p->topfunc(), oldend); | |
716 llvm::BasicBlock* endbb = new llvm::BasicBlock("foreachend", p->topfunc(), oldend); | |
717 | |
718 new llvm::BranchInst(begbb, p->scopebb()); | |
719 | |
720 // next | |
721 p->scope() = IRScope(nexbb,begbb); | |
722 llvm::Value* done = 0; | |
723 llvm::Value* load = new llvm::LoadInst(keyvar, "tmp", p->scopebb()); | |
724 if (op == TOKforeach) { | |
725 load = llvm::BinaryOperator::createAdd(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb()); | |
726 new llvm::StoreInst(load, keyvar, p->scopebb()); | |
727 done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_ULT, load, numiters, "tmp", p->scopebb()); | |
728 } | |
729 else if (op == TOKforeach_reverse) { | |
730 done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_UGT, load, llvm::ConstantInt::get(keytype, 0, false), "tmp", p->scopebb()); | |
731 load = llvm::BinaryOperator::createSub(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb()); | |
732 new llvm::StoreInst(load, keyvar, p->scopebb()); | |
733 } | |
734 new llvm::BranchInst(begbb, endbb, done, p->scopebb()); | |
735 | |
736 // begin | |
737 p->scope() = IRScope(begbb,nexbb); | |
738 | |
739 // get value for this iteration | |
740 llvm::Constant* zero = llvm::ConstantInt::get(keytype,0,false); | |
741 llvm::Value* loadedKey = p->ir->CreateLoad(keyvar,"tmp"); | |
742 if (aggrtype->ty == Tsarray) | |
743 value->llvmValue = DtoGEP(val,zero,loadedKey,"tmp"); | |
744 else if (aggrtype->ty == Tarray) | |
745 value->llvmValue = new llvm::GetElementPtrInst(val,loadedKey,"tmp",p->scopebb()); | |
746 | |
747 if (!value->isRef() && !value->isOut()) { | |
748 DValue* dst = new DVarValue(value->type, valvar, true); | |
749 DValue* src = new DVarValue(value->type, value->llvmValue, true); | |
750 DtoAssign(dst, src); | |
751 delete dst; | |
752 delete src; | |
753 value->llvmValue = valvar; | |
754 } | |
755 | |
756 // body | |
757 p->scope() = IRScope(p->scopebb(),endbb); | |
758 p->loopbbs.push_back(IRScope(nexbb,endbb)); | |
759 body->toIR(p); | |
760 p->loopbbs.pop_back(); | |
761 | |
762 if (!p->scopereturned()) | |
763 new llvm::BranchInst(nexbb, p->scopebb()); | |
764 | |
765 // end | |
766 p->scope() = IRScope(endbb,oldend); | |
767 } | |
768 | |
769 ////////////////////////////////////////////////////////////////////////////// | |
770 | |
771 void LabelStatement::toIR(IRState* p) | |
772 { | |
773 Logger::println("LabelStatement::toIR(): %s", toChars()); | |
774 LOG_SCOPE; | |
775 | |
776 assert(tf == NULL); | |
777 assert(!isReturnLabel); | |
778 | |
779 llvm::BasicBlock* oldend = gIR->scopeend(); | |
780 if (llvmBB) | |
781 llvmBB->moveBefore(oldend); | |
782 else | |
783 llvmBB = new llvm::BasicBlock("label", p->topfunc(), oldend); | |
784 | |
785 if (!p->scopereturned()) | |
786 new llvm::BranchInst(llvmBB, p->scopebb()); | |
787 | |
788 p->scope() = IRScope(llvmBB,oldend); | |
789 if (statement) | |
790 statement->toIR(p); | |
791 } | |
792 | |
793 ////////////////////////////////////////////////////////////////////////////// | |
794 | |
795 void GotoStatement::toIR(IRState* p) | |
796 { | |
797 Logger::println("GotoStatement::toIR(): %s", toChars()); | |
798 LOG_SCOPE; | |
799 | |
800 assert(tf == NULL); | |
801 | |
802 llvm::BasicBlock* oldend = gIR->scopeend(); | |
803 llvm::BasicBlock* bb = new llvm::BasicBlock("aftergoto", p->topfunc(), oldend); | |
804 | |
805 if (label->statement->llvmBB == NULL) | |
806 label->statement->llvmBB = new llvm::BasicBlock("label", p->topfunc()); | |
807 assert(!p->scopereturned()); | |
808 new llvm::BranchInst(label->statement->llvmBB, p->scopebb()); | |
809 p->scope() = IRScope(bb,oldend); | |
810 } | |
811 | |
812 ////////////////////////////////////////////////////////////////////////////// | |
813 | |
814 void WithStatement::toIR(IRState* p) | |
815 { | |
816 Logger::println("WithStatement::toIR(): %s", toChars()); | |
817 LOG_SCOPE; | |
818 | |
819 assert(exp); | |
820 assert(body); | |
821 | |
822 DValue* e = exp->toElem(p); | |
823 wthis->llvmValue = e->getRVal(); | |
824 delete e; | |
825 | |
826 body->toIR(p); | |
827 } | |
828 | |
829 ////////////////////////////////////////////////////////////////////////////// | |
830 | |
831 ////////////////////////////////////////////////////////////////////////////// | |
832 | |
833 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();} | |
834 //STUBST(BreakStatement); | |
835 //STUBST(ForStatement); | |
836 //STUBST(WithStatement); | |
837 STUBST(SynchronizedStatement); | |
838 //STUBST(ReturnStatement); | |
839 //STUBST(ContinueStatement); | |
840 STUBST(DefaultStatement); | |
841 STUBST(CaseStatement); | |
842 //STUBST(SwitchStatement); | |
843 STUBST(SwitchErrorStatement); | |
844 STUBST(Statement); | |
845 //STUBST(IfStatement); | |
846 //STUBST(ForeachStatement); | |
847 //STUBST(DoStatement); | |
848 //STUBST(WhileStatement); | |
849 //STUBST(ExpStatement); | |
850 //STUBST(CompoundStatement); | |
851 //STUBST(ScopeStatement); | |
852 STUBST(AsmStatement); | |
853 //STUBST(TryCatchStatement); | |
854 //STUBST(TryFinallyStatement); | |
855 STUBST(VolatileStatement); | |
856 //STUBST(LabelStatement); | |
857 //STUBST(ThrowStatement); | |
858 STUBST(GotoCaseStatement); | |
859 STUBST(GotoDefaultStatement); | |
860 //STUBST(GotoStatement); | |
861 //STUBST(UnrolledLoopStatement); | |
862 //STUBST(OnScopeStatement); |