Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

root/gen/statements.cpp

Revision 1650:40bd4a0d4870, 47.6 kB (checked in by Tomas Lindquist Olsen, 2 years ago)

Update to work with LLVM 2.7.

Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).

Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.

Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.

Line 
1 // Statements: D -> LLVM glue
2
3 #include <stdio.h>
4 #include <math.h>
5 #include <fstream>
6
7 #include "gen/llvm.h"
8 #include "llvm/InlineAsm.h"
9 #include "llvm/Support/CFG.h"
10
11 #include "mars.h"
12 #include "init.h"
13 #include "mtype.h"
14 #include "hdrgen.h"
15 #include "port.h"
16 #include "module.h"
17
18 #include "gen/irstate.h"
19 #include "gen/logger.h"
20 #include "gen/tollvm.h"
21 #include "gen/llvmhelpers.h"
22 #include "gen/runtime.h"
23 #include "gen/arrays.h"
24 #include "gen/todebug.h"
25 #include "gen/dvalue.h"
26 #include "gen/abi.h"
27
28 #include "ir/irfunction.h"
29 #include "ir/irmodule.h"
30 #include "ir/irlandingpad.h"
31
32 //////////////////////////////////////////////////////////////////////////////
33
34 void CompoundStatement::toIR(IRState* p)
35 {
36     Logger::println("CompoundStatement::toIR(): %s", loc.toChars());
37     LOG_SCOPE;
38
39     for (int i=0; i<statements->dim; i++)
40     {
41         Statement* s = (Statement*)statements->data[i];
42         if (s) {
43             s->toIR(p);
44         }
45     }
46 }
47
48
49 //////////////////////////////////////////////////////////////////////////////
50
51 void ReturnStatement::toIR(IRState* p)
52 {
53     Logger::println("ReturnStatement::toIR(): %s", loc.toChars());
54     LOG_SCOPE;
55
56     #ifndef DISABLE_DEBUG_INFO
57     if (global.params.symdebug)
58         DtoDwarfStopPoint(loc.linnum);
59     #endif
60
61     // is there a return value expression?
62     if (exp || (!exp && (p->topfunc() == p->mainFunc)) )
63     {
64         // if the functions return type is void this means that
65         // we are returning through a pointer argument
66         if (p->topfunc()->getReturnType() == LLType::getVoidTy(gIR->context()))
67         {
68             // sanity check
69             IrFunction* f = p->func();
70             assert(f->decl->ir.irFunc->retArg);
71
72             // FIXME: is there ever a case where a sret return needs to be rewritten for the ABI?
73
74             // get return pointer
75             DValue* rvar = new DVarValue(f->type->next, f->decl->ir.irFunc->retArg);
76             DValue* e = exp->toElem(p);
77             // store return value
78             DtoAssign(loc, rvar, e);
79
80             // emit scopes
81             DtoEnclosingHandlers(loc, NULL);
82
83             #ifndef DISABLE_DEBUG_INFO
84             // emit dbg end function
85             if (global.params.symdebug) DtoDwarfFuncEnd(f->decl);
86             #endif
87
88             // emit ret
89             llvm::ReturnInst::Create(gIR->context(), p->scopebb());
90
91         }
92         // the return type is not void, so this is a normal "register" return
93         else
94         {
95             LLValue* v;
96             if (!exp && (p->topfunc() == p->mainFunc))
97                 v = LLConstant::getNullValue(p->mainFunc->getReturnType());
98             else
99                 // do abi specific transformations on the return value
100                 v = p->func()->type->fty.putRet(exp->type, exp->toElem(p));
101
102             if (Logger::enabled())
103                 Logger::cout() << "return value is '" <<*v << "'\n";
104
105             IrFunction* f = p->func();
106             // Hack around LDC assuming structs are in memory:
107             // If the function returns a struct, and the return value is a
108             // pointer to a struct, load from it before returning.
109             if (f->type->next->ty == Tstruct && isaPointer(v->getType())) {
110                 Logger::println("Loading struct type for return");
111                 v = DtoLoad(v);
112             }
113
114             // can happen for classes and void main
115             if (v->getType() != p->topfunc()->getReturnType())
116             {
117                 // for the main function this only happens if it is declared as void
118                 // and then contains a return (exp); statement. Since the actual
119                 // return type remains i32, we just throw away the exp value
120                 // and return 0 instead
121                 // if we're not in main, just bitcast
122                 if (p->topfunc() == p->mainFunc)
123                     v = LLConstant::getNullValue(p->mainFunc->getReturnType());
124                 else
125                     v = gIR->ir->CreateBitCast(v, p->topfunc()->getReturnType(), "tmp");
126
127                 if (Logger::enabled())
128                     Logger::cout() << "return value after cast: " << *v << '\n';
129             }
130
131             DtoEnclosingHandlers(loc, NULL);
132
133             #ifndef DISABLE_DEBUG_INFO
134             if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
135             #endif
136             llvm::ReturnInst::Create(gIR->context(), v, p->scopebb());
137         }
138     }
139     // no return value expression means it's a void function
140     else
141     {
142         assert(p->topfunc()->getReturnType() == LLType::getVoidTy(gIR->context()));
143         DtoEnclosingHandlers(loc, NULL);
144
145         #ifndef DISABLE_DEBUG_INFO
146         if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
147         #endif
148         llvm::ReturnInst::Create(gIR->context(), p->scopebb());
149     }
150
151     // the return terminated this basicblock, start a new one
152     llvm::BasicBlock* oldend = gIR->scopeend();
153     llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "afterreturn", p->topfunc(), oldend);
154     p->scope() = IRScope(bb,oldend);
155 }
156
157 //////////////////////////////////////////////////////////////////////////////
158
159 void ExpStatement::toIR(IRState* p)
160 {
161     Logger::println("ExpStatement::toIR(): %s", loc.toChars());
162     LOG_SCOPE;
163
164     #ifndef DISABLE_DEBUG_INFO
165     if (global.params.symdebug)
166         DtoDwarfStopPoint(loc.linnum);
167     #endif
168
169     if (exp) {
170         if (global.params.llvmAnnotate)
171             DtoAnnotation(exp->toChars());
172         elem* e;
173         // a cast(void) around the expression is allowed, but doesn't require any code
174         if(exp->op == TOKcast && exp->type == Type::tvoid) {
175             CastExp* cexp = (CastExp*)exp;
176             e = cexp->e1->toElem(p);
177         }
178         else
179             e = exp->toElem(p);
180         delete e;
181     }
182     /*elem* e = exp->toElem(p);
183     p->buf.printf("%s", e->toChars());
184     delete e;
185     p->buf.writenl();*/
186 }
187
188 //////////////////////////////////////////////////////////////////////////////
189
190 void IfStatement::toIR(IRState* p)
191 {
192     Logger::println("IfStatement::toIR(): %s", loc.toChars());
193     LOG_SCOPE;
194
195     #ifndef DISABLE_DEBUG_INFO
196     if (global.params.symdebug)
197         DtoDwarfStopPoint(loc.linnum);
198     #endif
199
200     if (match)
201         DtoRawVarDeclaration(match);
202
203     DValue* cond_e = condition->toElem(p);
204     LLValue* cond_val = cond_e->getRVal();
205
206     llvm::BasicBlock* oldend = gIR->scopeend();
207
208     llvm::BasicBlock* ifbb = llvm::BasicBlock::Create(gIR->context(), "if", gIR->topfunc(), oldend);
209     llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "endif", gIR->topfunc(), oldend);
210     llvm::BasicBlock* elsebb = elsebody ? llvm::BasicBlock::Create(gIR->context(), "else", gIR->topfunc(), endbb) : endbb;
211
212     if (cond_val->getType() != LLType::getInt1Ty(gIR->context())) {
213         if (Logger::enabled())
214             Logger::cout() << "if conditional: " << *cond_val << '\n';
215         cond_val = DtoCast(loc, cond_e, Type::tbool)->getRVal();
216     }
217     LLValue* ifgoback = llvm::BranchInst::Create(ifbb, elsebb, cond_val, gIR->scopebb());
218
219     // replace current scope
220     gIR->scope() = IRScope(ifbb,elsebb);
221
222     // do scoped statements
223     if (ifbody)
224         ifbody->toIR(p);
225     if (!gIR->scopereturned()) {
226         llvm::BranchInst::Create(endbb,gIR->scopebb());
227     }
228
229     if (elsebody) {
230         //assert(0);
231         gIR->scope() = IRScope(elsebb,endbb);
232         elsebody->toIR(p);
233         if (!gIR->scopereturned()) {
234             llvm::BranchInst::Create(endbb,gIR->scopebb());
235         }
236     }
237
238     // rewrite the scope
239     gIR->scope() = IRScope(endbb,oldend);
240 }
241
242 //////////////////////////////////////////////////////////////////////////////
243
244 void ScopeStatement::toIR(IRState* p)
245 {
246     Logger::println("ScopeStatement::toIR(): %s", loc.toChars());
247     LOG_SCOPE;
248
249     /*llvm::BasicBlock* oldend = p->scopeend();
250
251     llvm::BasicBlock* beginbb = 0;
252
253     // remove useless branches by clearing and reusing the current basicblock
254     llvm::BasicBlock* bb = p->scopebb();
255     if (bb->empty()) {
256         beginbb = bb;
257     }
258     else {
259         beginbb = llvm::BasicBlock::Create(gIR->context(), "scope", p->topfunc(), oldend);
260         if (!p->scopereturned())
261             llvm::BranchInst::Create(beginbb, bb);
262     }
263
264     llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "endscope", p->topfunc(), oldend);
265     if (beginbb != bb)
266         p->scope() = IRScope(beginbb, endbb);
267     else
268         p->scope().end = endbb;*/
269
270     if (statement)
271         statement->toIR(p);
272
273     /*p->scope().end = oldend;
274     Logger::println("Erasing scope endbb");
275     endbb->eraseFromParent();*/
276 }
277
278 //////////////////////////////////////////////////////////////////////////////
279
280 void WhileStatement::toIR(IRState* p)
281 {
282     Logger::println("WhileStatement::toIR(): %s", loc.toChars());
283     LOG_SCOPE;
284
285     #ifndef DISABLE_DEBUG_INFO
286     if (global.params.symdebug)
287         DtoDwarfStopPoint(loc.linnum);
288     #endif
289
290     // create while blocks
291     llvm::BasicBlock* oldend = gIR->scopeend();
292     llvm::BasicBlock* whilebb = llvm::BasicBlock::Create(gIR->context(), "whilecond", gIR->topfunc(), oldend);
293     llvm::BasicBlock* whilebodybb = llvm::BasicBlock::Create(gIR->context(), "whilebody", gIR->topfunc(), oldend);
294     llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "endwhile", gIR->topfunc(), oldend);
295
296     // move into the while block
297     p->ir->CreateBr(whilebb);
298     //llvm::BranchInst::Create(whilebb, gIR->scopebb());
299
300     // replace current scope
301     gIR->scope() = IRScope(whilebb,endbb);
302
303     // create the condition
304     DValue* cond_e = condition->toElem(p);
305     LLValue* cond_val = DtoCast(loc, cond_e, Type::tbool)->getRVal();
306     delete cond_e;
307
308     // conditional branch
309     LLValue* ifbreak = llvm::BranchInst::Create(whilebodybb, endbb, cond_val, p->scopebb());
310
311     // rewrite scope
312     gIR->scope() = IRScope(whilebodybb,endbb);
313
314     // while body code
315     p->func()->gen->targetScopes.push_back(IRTargetScope(this,NULL,whilebb,endbb));
316     if (body)
317         body->toIR(p);
318     p->func()->gen->targetScopes.pop_back();
319
320     // loop
321     if (!gIR->scopereturned())
322         llvm::BranchInst::Create(whilebb, gIR->scopebb());
323
324     // rewrite the scope
325     gIR->scope() = IRScope(endbb,oldend);
326 }
327
328 //////////////////////////////////////////////////////////////////////////////
329
330 void DoStatement::toIR(IRState* p)
331 {
332     Logger::println("DoStatement::toIR(): %s", loc.toChars());
333     LOG_SCOPE;
334
335     #ifndef DISABLE_DEBUG_INFO
336     if (global.params.symdebug)
337         DtoDwarfStopPoint(loc.linnum);
338     #endif
339
340     // create while blocks
341     llvm::BasicBlock* oldend = gIR->scopeend();
342     llvm::BasicBlock* dowhilebb = llvm::BasicBlock::Create(gIR->context(), "dowhile", gIR->topfunc(), oldend);
343     llvm::BasicBlock* condbb = llvm::BasicBlock::Create(gIR->context(), "dowhilecond", gIR->topfunc(), oldend);
344     llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "enddowhile", gIR->topfunc(), oldend);
345
346     // move into the while block
347     assert(!gIR->scopereturned());
348     llvm::BranchInst::Create(dowhilebb, gIR->scopebb());
349
350     // replace current scope
351     gIR->scope() = IRScope(dowhilebb,condbb);
352
353     // do-while body code
354     p->func()->gen->targetScopes.push_back(IRTargetScope(this,NULL,condbb,endbb));
355     if (body)
356         body->toIR(p);
357     p->func()->gen->targetScopes.pop_back();
358
359     // branch to condition block
360     llvm::BranchInst::Create(condbb, gIR->scopebb());
361     gIR->scope() = IRScope(condbb,endbb);
362
363     // create the condition
364     DValue* cond_e = condition->toElem(p);
365     LLValue* cond_val = DtoCast(loc, cond_e, Type::tbool)->getRVal();
366     delete cond_e;
367
368     // conditional branch
369     LLValue* ifbreak = llvm::BranchInst::Create(dowhilebb, endbb, cond_val, gIR->scopebb());
370
371     // rewrite the scope
372     gIR->scope() = IRScope(endbb,oldend);
373 }
374
375 //////////////////////////////////////////////////////////////////////////////
376
377 void ForStatement::toIR(IRState* p)
378 {
379     Logger::println("ForStatement::toIR(): %s", loc.toChars());
380     LOG_SCOPE;
381
382     #ifndef DISABLE_DEBUG_INFO
383     if (global.params.symdebug)
384         DtoDwarfStopPoint(loc.linnum);
385     #endif
386
387     // create for blocks
388     llvm::BasicBlock* oldend = gIR->scopeend();
389     llvm::BasicBlock* forbb = llvm::BasicBlock::Create(gIR->context(), "forcond", gIR->topfunc(), oldend);
390     llvm::BasicBlock* forbodybb = llvm::BasicBlock::Create(gIR->context(), "forbody", gIR->topfunc(), oldend);
391     llvm::BasicBlock* forincbb = llvm::BasicBlock::Create(gIR->context(), "forinc", gIR->topfunc(), oldend);
392     llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "endfor", gIR->topfunc(), oldend);
393
394     // init
395     if (init != 0)
396     init->toIR(p);
397
398     // move into the for condition block, ie. start the loop
399     assert(!gIR->scopereturned());
400     llvm::BranchInst::Create(forbb, gIR->scopebb());
401
402     p->func()->gen->targetScopes.push_back(IRTargetScope(this,NULL,forincbb,endbb));
403
404     // replace current scope
405     gIR->scope() = IRScope(forbb,forbodybb);
406
407     // create the condition
408     LLValue* cond_val;
409     if (condition)
410     {
411         DValue* cond_e = condition->toElem(p);
412         cond_val = DtoCast(loc, cond_e, Type::tbool)->getRVal();
413         delete cond_e;
414     }
415     else
416     {
417         cond_val = DtoConstBool(true);
418     }
419
420     // conditional branch
421     assert(!gIR->scopereturned());
422     llvm::BranchInst::Create(forbodybb, endbb, cond_val, gIR->scopebb());
423
424     // rewrite scope
425     gIR->scope() = IRScope(forbodybb,forincbb);
426
427     // do for body code
428     if (body)
429         body->toIR(p);
430
431     // move into the for increment block
432     if (!gIR->scopereturned())
433         llvm::BranchInst::Create(forincbb, gIR->scopebb());
434     gIR->scope() = IRScope(forincbb, endbb);
435
436     // increment
437     if (increment) {
438         DValue* inc = increment->toElem(p);
439         delete inc;
440     }
441
442     // loop
443     if (!gIR->scopereturned())
444         llvm::BranchInst::Create(forbb, gIR->scopebb());
445
446     p->func()->gen->targetScopes.pop_back();
447
448     // rewrite the scope
449     gIR->scope() = IRScope(endbb,oldend);
450 }
451
452 //////////////////////////////////////////////////////////////////////////////
453
454 void BreakStatement::toIR(IRState* p)
455 {
456     Logger::println("BreakStatement::toIR(): %s", loc.toChars());
457     LOG_SCOPE;
458
459     // don't emit two terminators in a row
460     // happens just before DMD generated default statements if the last case terminates
461     if (p->scopereturned())
462         return;
463
464     #ifndef DISABLE_DEBUG_INFO
465     if (global.params.symdebug)
466         DtoDwarfStopPoint(loc.linnum);
467     #endif
468
469     if (ident != 0) {
470         Logger::println("ident = %s", ident->toChars());
471
472         DtoEnclosingHandlers(loc, target);
473
474         // get the loop statement the label refers to
475         Statement* targetLoopStatement = target->statement;
476         ScopeStatement* tmp;
477         while(tmp = targetLoopStatement->isScopeStatement())
478             targetLoopStatement = tmp->statement;
479
480         // find the right break block and jump there
481         bool found = false;
482         FuncGen::TargetScopeVec::reverse_iterator it = p->func()->gen->targetScopes.rbegin();
483         FuncGen::TargetScopeVec::reverse_iterator it_end = p->func()->gen->targetScopes.rend();
484         while(it != it_end) {
485             if(it->s == targetLoopStatement) {
486                 llvm::BranchInst::Create(it->breakTarget, p->scopebb());
487                 found = true;
488                 break;
489             }
490             ++it;
491         }
492         assert(found);
493     }
494     else {
495         // find closest scope with a break target
496         FuncGen::TargetScopeVec::reverse_iterator it = p->func()->gen->targetScopes.rbegin();
497         FuncGen::TargetScopeVec::reverse_iterator it_end = p->func()->gen->targetScopes.rend();
498         while(it != it_end) {
499             if(it->breakTarget) {
500                 break;
501             }
502             ++it;
503         }
504         DtoEnclosingHandlers(loc, it->s);
505         llvm::BranchInst::Create(it->breakTarget, gIR->scopebb());
506     }
507
508     // the break terminated this basicblock, start a new one
509     llvm::BasicBlock* oldend = gIR->scopeend();
510     llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "afterbreak", p->topfunc(), oldend);
511     p->scope() = IRScope(bb,oldend);
512 }
513
514 //////////////////////////////////////////////////////////////////////////////
515
516 void ContinueStatement::toIR(IRState* p)
517 {
518     Logger::println("ContinueStatement::toIR(): %s", loc.toChars());
519     LOG_SCOPE;
520
521     #ifndef DISABLE_DEBUG_INFO
522     if (global.params.symdebug)
523         DtoDwarfStopPoint(loc.linnum);
524     #endif
525
526     if (ident != 0) {
527         Logger::println("ident = %s", ident->toChars());
528
529         DtoEnclosingHandlers(loc, target);
530
531         // get the loop statement the label refers to
532         Statement* targetLoopStatement = target->statement;
533         ScopeStatement* tmp;
534         while(tmp = targetLoopStatement->isScopeStatement())
535             targetLoopStatement = tmp->statement;
536
537         // find the right continue block and jump there
538         bool found = false;
539         FuncGen::TargetScopeVec::reverse_iterator it = p->func()->gen->targetScopes.rbegin();
540         FuncGen::TargetScopeVec::reverse_iterator it_end = p->func()->gen->targetScopes.rend();
541         while(it != it_end) {
542             if(it->s == targetLoopStatement) {
543                 llvm::BranchInst::Create(it->continueTarget, gIR->scopebb());
544                 found = true;
545                 break;
546             }
547             ++it;
548         }
549         assert(found);
550     }
551     else {
552         // find closest scope with a continue target
553         FuncGen::TargetScopeVec::reverse_iterator it = p->func()->gen->targetScopes.rbegin();
554         FuncGen::TargetScopeVec::reverse_iterator it_end = p->func()->gen->targetScopes.rend();
555         while(it != it_end) {
556             if(it->continueTarget) {
557                 break;
558             }
559             ++it;
560         }
561         DtoEnclosingHandlers(loc, it->s);
562         llvm::BranchInst::Create(it->continueTarget, gIR->scopebb());
563     }
564
565     // the continue terminated this basicblock, start a new one
566     llvm::BasicBlock* oldend = gIR->scopeend();
567     llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftercontinue", p->topfunc(), oldend);
568     p->scope() = IRScope(bb,oldend);
569 }
570
571 //////////////////////////////////////////////////////////////////////////////
572
573 void OnScopeStatement::toIR(IRState* p)
574 {
575     Logger::println("OnScopeStatement::toIR(): %s", loc.toChars());
576     LOG_SCOPE;
577
578     assert(statement);
579     //statement->toIR(p); // this seems to be redundant
580 }
581
582 //////////////////////////////////////////////////////////////////////////////
583
584 void TryFinallyStatement::toIR(IRState* p)
585 {
586     Logger::println("TryFinallyStatement::toIR(): %s", loc.toChars());
587     LOG_SCOPE;
588
589     #ifndef DISABLE_DEBUG_INFO
590     if (global.params.symdebug)
591         DtoDwarfStopPoint(loc.linnum);
592     #endif
593
594     // if there's no finalbody or no body, things are simple
595     if (!finalbody) {
596         if (body)
597             body->toIR(p);
598         return;
599     }
600     if (!body) {
601         finalbody->toIR(p);
602         return;
603     }
604
605     // create basic blocks
606     llvm::BasicBlock* oldend = p->scopeend();
607
608     llvm::BasicBlock* trybb = llvm::BasicBlock::Create(gIR->context(), "try", p->topfunc(), oldend);
609     llvm::BasicBlock* finallybb = llvm::BasicBlock::Create(gIR->context(), "finally", p->topfunc(), oldend);
610     // the landing pad for statements in the try block
611     llvm::BasicBlock* landingpadbb = llvm::BasicBlock::Create(gIR->context(), "landingpad", p->topfunc(), oldend);
612     llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "endtryfinally", p->topfunc(), oldend);
613
614     // pass the previous BB into this
615     assert(!gIR->scopereturned());
616     llvm::BranchInst::Create(trybb, p->scopebb());
617
618     //
619     // set up the landing pad
620     //
621     p->scope() = IRScope(landingpadbb, endbb);
622
623     assert(finalbody);
624     IRLandingPad& pad = gIR->func()->gen->landingPadInfo;
625     pad.addFinally(finalbody);
626     pad.push(landingpadbb);
627     gIR->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingTryFinally(this,gIR->func()->gen->landingPad),NULL,NULL));
628     gIR->func()->gen->landingPad = pad.get();
629
630     //
631     // do the try block
632     //
633     p->scope() = IRScope(trybb,finallybb);
634
635     assert(body);
636     body->toIR(p);
637
638     // terminate try BB
639     if (!p->scopereturned())
640         llvm::BranchInst::Create(finallybb, p->scopebb());
641
642     pad.pop();
643     gIR->func()->gen->landingPad = pad.get();
644     gIR->func()->gen->targetScopes.pop_back();
645
646     //
647     // do finally block
648     //
649     p->scope() = IRScope(finallybb,landingpadbb);
650     finalbody->toIR(p);
651
652     // terminate finally
653     //TODO: isn't it an error to have a 'returned' finally block?
654     if (!gIR->scopereturned()) {
655         llvm::BranchInst::Create(endbb, p->scopebb());
656     }
657
658     // rewrite the scope
659     p->scope() = IRScope(endbb,oldend);
660 }
661
662 //////////////////////////////////////////////////////////////////////////////
663
664 void TryCatchStatement::toIR(IRState* p)
665 {
666     Logger::println("TryCatchStatement::toIR(): %s", loc.toChars());
667     LOG_SCOPE;
668
669     #ifndef DISABLE_DEBUG_INFO
670     if (global.params.symdebug)
671         DtoDwarfStopPoint(loc.linnum);
672     #endif
673
674     // create basic blocks
675     llvm::BasicBlock* oldend = p->scopeend();
676
677     llvm::BasicBlock* trybb = llvm::BasicBlock::Create(gIR->context(), "try", p->topfunc(), oldend);
678     // the landing pad will be responsible for branching to the correct catch block
679     llvm::BasicBlock* landingpadbb = llvm::BasicBlock::Create(gIR->context(), "landingpad", p->topfunc(), oldend);
680     llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "endtrycatch", p->topfunc(), oldend);
681
682     // pass the previous BB into this
683     assert(!gIR->scopereturned());
684     llvm::BranchInst::Create(trybb, p->scopebb());
685
686     //
687     // do catches and the landing pad
688     //
689     assert(catches);
690     gIR->scope() = IRScope(landingpadbb, endbb);
691
692     IRLandingPad& pad = gIR->func()->gen->landingPadInfo;
693     for (int i = 0; i < catches->dim; i++)
694     {
695         Catch *c = (Catch *)catches->data[i];
696         pad.addCatch(c, endbb);
697     }
698
699     pad.push(landingpadbb);
700     gIR->func()->gen->landingPad = pad.get();
701
702     //
703     // do the try block
704     //
705     p->scope() = IRScope(trybb,landingpadbb);
706
707     assert(body);
708     body->toIR(p);
709
710     if (!gIR->scopereturned())
711         llvm::BranchInst::Create(endbb, p->scopebb());
712
713     pad.pop();
714     gIR->func()->gen->landingPad = pad.get();
715
716     // rewrite the scope
717     p->scope() = IRScope(endbb,oldend);
718 }
719
720 //////////////////////////////////////////////////////////////////////////////
721
722 void ThrowStatement::toIR(IRState* p)
723 {
724     Logger::println("ThrowStatement::toIR(): %s", loc.toChars());
725     LOG_SCOPE;
726
727     #ifndef DISABLE_DEBUG_INFO
728     if (global.params.symdebug)
729         DtoDwarfStopPoint(loc.linnum);
730     #endif
731
732     assert(exp);
733     DValue* e = exp->toElem(p);
734
735     #ifndef DISABLE_DEBUG_INFO
736     if (global.params.symdebug) DtoDwarfFuncEnd(gIR->func()->decl);
737     #endif
738
739     llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_throw_exception");
740     //Logger::cout() << "calling: " << *fn << '\n';
741     LLValue* arg = DtoBitCast(e->getRVal(), fn->getFunctionType()->getParamType(0));
742     //Logger::cout() << "arg: " << *arg << '\n';
743     gIR->CreateCallOrInvoke(fn, arg);
744     gIR->ir->CreateUnreachable();
745
746     // need a block after the throw for now
747     llvm::BasicBlock* oldend = gIR->scopeend();
748     llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "afterthrow", p->topfunc(), oldend);
749     p->scope() = IRScope(bb,oldend);
750 }
751
752 //////////////////////////////////////////////////////////////////////////////
753
754 // used to build the sorted list of cases
755 struct Case : Object
756 {
757     StringExp* str;
758     size_t index;
759
760     Case(StringExp* s, size_t i) {
761         str = s;
762         index = i;
763     }
764
765     int compare(Object *obj) {
766         Case* c2 = (Case*)obj;
767         return str->compare(c2->str);
768     }
769 };
770
771 static LLValue* call_string_switch_runtime(llvm::Value* table, Expression* e)
772 {
773     Type* dt = e->type->toBasetype();
774     Type* dtnext = dt->nextOf()->toBasetype();
775     TY ty = dtnext->ty;
776     const char* fname;
777     if (ty == Tchar) {
778         fname = "_d_switch_string";
779     }
780     else if (ty == Twchar) {
781         fname = "_d_switch_ustring";
782     }
783     else if (ty == Tdchar) {
784         fname = "_d_switch_dstring";
785     }
786     else {
787         assert(0 && "not char/wchar/dchar");
788     }
789
790     llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
791
792     if (Logger::enabled())
793     {
794         Logger::cout() << *table->getType() << '\n';
795         Logger::cout() << *fn->getFunctionType()->getParamType(0) << '\n';
796     }
797     assert(table->getType() == fn->getFunctionType()->getParamType(0));
798
799     DValue* val = e->toElem(gIR);
800     LLValue* llval = val->getRVal();
801     assert(llval->getType() == fn->getFunctionType()->getParamType(1));
802
803     LLCallSite call = gIR->CreateCallOrInvoke2(fn, table, llval, "tmp");
804
805     return call.getInstruction();
806 }
807
808 void SwitchStatement::toIR(IRState* p)
809 {
810     Logger::println("SwitchStatement::toIR(): %s", loc.toChars());
811     LOG_SCOPE;
812
813     #ifndef DISABLE_DEBUG_INFO
814     if (global.params.symdebug)
815         DtoDwarfStopPoint(loc.linnum);
816     #endif
817
818     llvm::BasicBlock* oldend = gIR->scopeend();
819
820     // clear data from previous passes... :/
821     for (int i=0; i<cases->dim; ++i)
822     {
823         CaseStatement* cs = (CaseStatement*)cases->data[i];
824         cs->bodyBB = NULL;
825         cs->llvmIdx = NULL;
826     }
827
828     // string switch?
829     llvm::Value* switchTable = 0;
830     Array caseArray;
831     if (!condition->type->isintegral())
832     {
833         Logger::println("is string switch");
834         // build array of the stringexpS
835         caseArray.reserve(cases->dim);
836         for (int i=0; i<cases->dim; ++i)
837         {
838             CaseStatement* cs = (CaseStatement*)cases->data[i];
839
840             assert(cs->exp->op == TOKstring);
841             caseArray.push(new Case((StringExp*)cs->exp, i));
842         }
843         // first sort it
844         caseArray.sort();
845         // iterate and add indices to cases
846         std::vector<LLConstant*> inits(caseArray.dim);
847         for (size_t i=0; i<caseArray.dim; ++i)
848         {
849             Case* c = (Case*)caseArray.data[i];
850             CaseStatement* cs = (CaseStatement*)cases->data[c->index];
851             cs->llvmIdx = DtoConstUint(i);
852             inits[i] = c->str->toConstElem(p);
853         }
854         // build static array for ptr or final array
855         const LLType* elemTy = DtoType(condition->type);
856         const llvm::ArrayType* arrTy = llvm::ArrayType::get(elemTy, inits.size());
857         LLConstant* arrInit = LLConstantArray::get(arrTy, inits);
858         llvm::GlobalVariable* arr = new llvm::GlobalVariable(*gIR->module, arrTy, true, llvm::GlobalValue::InternalLinkage, arrInit, ".string_switch_table_data");
859
860         const LLType* elemPtrTy = getPtrToType(elemTy);
861         LLConstant* arrPtr = llvm::ConstantExpr::getBitCast(arr, elemPtrTy);
862
863         // build the static table
864         std::vector<const LLType*> types;
865         types.push_back(DtoSize_t());
866         types.push_back(elemPtrTy);
867         const llvm::StructType* sTy = llvm::StructType::get(gIR->context(), types);
868         std::vector<LLConstant*> sinits;
869         sinits.push_back(DtoConstSize_t(inits.size()));
870         sinits.push_back(arrPtr);
871         switchTable = llvm::ConstantStruct::get(sTy, sinits);
872     }
873
874     // body block
875     llvm::BasicBlock* bodybb = llvm::BasicBlock::Create(gIR->context(), "switchbody", p->topfunc(), oldend);
876
877     // default
878     llvm::BasicBlock* defbb = 0;
879     if (sdefault) {
880         Logger::println("has default");
881         defbb = llvm::BasicBlock::Create(gIR->context(), "default", p->topfunc(), oldend);
882         sdefault->bodyBB = defbb;
883     }
884
885     // end (break point)
886     llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "switchend", p->topfunc(), oldend);
887
888     // condition var
889     LLValue* condVal;
890     // integral switch
891     if (condition->type->isintegral()) {
892         DValue* cond = condition->toElem(p);
893         condVal = cond->getRVal();
894     }
895     // string switch
896     else {
897         condVal = call_string_switch_runtime(switchTable, condition);
898     }
899     llvm::SwitchInst* si = llvm::SwitchInst::Create(condVal, defbb ? defbb : endbb, cases->dim, p->scopebb());
900
901     // do switch body
902     assert(body);
903
904     p->scope() = IRScope(bodybb, endbb);
905     p->func()->gen->targetScopes.push_back(IRTargetScope(this,NULL,NULL,endbb));
906     body->toIR(p);
907     p->func()->gen->targetScopes.pop_back();
908
909     if (!p->scopereturned())
910         llvm::BranchInst::Create(endbb, p->scopebb());
911
912     // add the cases
913     for (int i=0; i<cases->dim; ++i)
914     {
915         CaseStatement* cs = (CaseStatement*)cases->data[i];
916         si->addCase(cs->llvmIdx, cs->bodyBB);
917     }
918
919     gIR->scope() = IRScope(endbb,oldend);
920 }
921
922 //////////////////////////////////////////////////////////////////////////////
923 void CaseStatement::toIR(IRState* p)
924 {
925     Logger::println("CaseStatement::toIR(): %s", loc.toChars());
926     LOG_SCOPE;
927
928     llvm::BasicBlock* nbb = llvm::BasicBlock::Create(gIR->context(), "case", p->topfunc(), p->scopeend());
929
930     if (bodyBB && !bodyBB->getTerminator())
931     {
932         llvm::BranchInst::Create(nbb, bodyBB);
933     }
934     bodyBB = nbb;
935
936     if (llvmIdx == NULL) {
937         LLConstant* c = exp->toConstElem(p);
938         llvmIdx = isaConstantInt(c);
939     }
940
941     if (!p->scopereturned())
942         llvm::BranchInst::Create(bodyBB, p->scopebb());
943
944     p->scope() = IRScope(bodyBB, p->scopeend());
945
946     assert(statement);
947     statement->toIR(p);
948 }
949
950 //////////////////////////////////////////////////////////////////////////////
951 void DefaultStatement::toIR(IRState* p)
952 {
953     Logger::println("DefaultStatement::toIR(): %s", loc.toChars());
954     LOG_SCOPE;
955
956     assert(bodyBB);
957
958     llvm::BasicBlock* nbb = llvm::BasicBlock::Create(gIR->context(), "default", p->topfunc(), p->scopeend());
959
960     if (!bodyBB->getTerminator())
961     {
962         llvm::BranchInst::Create(nbb, bodyBB);
963     }
964     bodyBB = nbb;
965
966     if (!p->scopereturned())
967         llvm::BranchInst::Create(bodyBB, p->scopebb());
968
969     p->scope() = IRScope(bodyBB, p->scopeend());
970
971     assert(statement);
972     statement->toIR(p);
973 }
974
975 //////////////////////////////////////////////////////////////////////////////
976
977 void UnrolledLoopStatement::toIR(IRState* p)
978 {
979     Logger::println("UnrolledLoopStatement::toIR(): %s", loc.toChars());
980     LOG_SCOPE;
981
982     // if no statements, there's nothing to do
983     if (!statements || !statements->dim)
984         return;
985
986     #ifndef DISABLE_DEBUG_INFO
987     if (global.params.symdebug)
988         DtoDwarfStopPoint(loc.linnum);
989     #endif
990
991     // DMD doesn't fold stuff like continue/break, and since this isn't really a loop
992     // we have to keep track of each statement and jump to the next/end on continue/break
993
994     llvm::BasicBlock* oldend = gIR->scopeend();
995
996     // create a block for each statement
997     size_t nstmt = statements->dim;
998     LLSmallVector<llvm::BasicBlock*, 4> blocks(nstmt, NULL);
999
1000     for (size_t i=0; i<nstmt; i++)
1001     {
1002         blocks[i] = llvm::BasicBlock::Create(gIR->context(), "unrolledstmt", p->topfunc(), oldend);
1003     }
1004
1005     // create end block
1006     llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "unrolledend", p->topfunc(), oldend);
1007
1008     // enter first stmt
1009     if (!p->scopereturned())
1010         p->ir->CreateBr(blocks[0]);
1011
1012     // do statements
1013     Statement** stmts = (Statement**)statements->data;
1014
1015     for (int i=0; i<nstmt; i++)
1016     {
1017         Statement* s = stmts[i];
1018
1019         // get blocks
1020         llvm::BasicBlock* thisbb = blocks[i];
1021         llvm::BasicBlock* nextbb = (i+1 == nstmt) ? endbb : blocks[i+1];
1022
1023         // update scope
1024         p->scope() = IRScope(thisbb,nextbb);
1025
1026         // push loop scope
1027         // continue goes to next statement, break goes to end
1028         p->func()->gen->targetScopes.push_back(IRTargetScope(this,NULL,nextbb,endbb));
1029
1030         // do statement
1031         s->toIR(p);
1032
1033         // pop loop scope
1034         p->func()->gen->targetScopes.pop_back();
1035
1036         // next stmt
1037         if (!p->scopereturned())
1038             p->ir->CreateBr(nextbb);
1039     }
1040
1041     // finish scope
1042     if (!p->scopereturned())
1043         p->ir->CreateBr(endbb);
1044     p->scope() = IRScope(endbb,oldend);
1045 }
1046
1047 //////////////////////////////////////////////////////////////////////////////
1048
1049 void ForeachStatement::toIR(IRState* p)
1050 {
1051     Logger::println("ForeachStatement::toIR(): %s", loc.toChars());
1052     LOG_SCOPE;
1053
1054     #ifndef DISABLE_DEBUG_INFO
1055     if (global.params.symdebug)
1056         DtoDwarfStopPoint(loc.linnum);
1057     #endif
1058
1059     //assert(arguments->dim == 1);
1060     assert(value != 0);
1061     assert(aggr != 0);
1062     assert(func != 0);
1063
1064     //Argument* arg = (Argument*)arguments->data[0];
1065     //Logger::println("Argument is %s", arg->toChars());
1066
1067     Logger::println("aggr = %s", aggr->toChars());
1068
1069     // key
1070     const LLType* keytype = key ? DtoType(key->type) : DtoSize_t();
1071     LLValue* keyvar;
1072     if (key)
1073         keyvar = DtoRawVarDeclaration(key);
1074     else
1075         keyvar = DtoRawAlloca(keytype, 0, "foreachkey"); // FIXME: align?
1076     LLValue* zerokey = LLConstantInt::get(keytype,0,false);
1077
1078     // value
1079     Logger::println("value = %s", value->toPrettyChars());
1080     LLValue* valvar = NULL;
1081     if (!value->isRef() && !value->isOut()) {
1082         // Create a local variable to serve as the value.
1083         DtoRawVarDeclaration(value);
1084         valvar = value->ir.irLocal->value;
1085     }
1086
1087     // what to iterate
1088     DValue* aggrval = aggr->toElem(p);
1089     Type* aggrtype = aggr->type->toBasetype();
1090
1091     // get length and pointer
1092     LLValue* niters = DtoArrayLen(aggrval);
1093     LLValue* val = DtoArrayPtr(aggrval);
1094
1095     if (niters->getType() != keytype)
1096     {
1097         size_t sz1 = getTypeBitSize(niters->getType());
1098         size_t sz2 = getTypeBitSize(keytype);
1099         if (sz1 < sz2)
1100             niters = gIR->ir->CreateZExt(niters, keytype, "foreachtrunckey");
1101         else if (sz1 > sz2)
1102             niters = gIR->ir->CreateTrunc(niters, keytype, "foreachtrunckey");
1103         else
1104             niters = gIR->ir->CreateBitCast(niters, keytype, "foreachtrunckey");
1105     }
1106
1107     LLConstant* delta = 0;
1108     if (op == TOKforeach) {
1109         new llvm::StoreInst(zerokey, keyvar, p->scopebb());
1110     }
1111     else {
1112         new llvm::StoreInst(niters, keyvar, p->scopebb());
1113     }
1114
1115     llvm::BasicBlock* oldend = gIR->scopeend();
1116     llvm::BasicBlock* condbb = llvm::BasicBlock::Create(gIR->context(), "foreachcond", p->topfunc(), oldend);
1117     llvm::BasicBlock* bodybb = llvm::BasicBlock::Create(gIR->context(), "foreachbody", p->topfunc(), oldend);
1118     llvm::BasicBlock* nextbb = llvm::BasicBlock::Create(gIR->context(), "foreachnext", p->topfunc(), oldend);
1119     llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "foreachend", p->topfunc(), oldend);
1120
1121     llvm::BranchInst::Create(condbb, p->scopebb());
1122
1123     // condition
1124     p->scope() = IRScope(condbb,bodybb);
1125
1126     LLValue* done = 0;
1127     LLValue* load = DtoLoad(keyvar);
1128     if (op == TOKforeach) {
1129         done = p->ir->CreateICmpULT(load, niters, "tmp");
1130     }
1131     else if (op == TOKforeach_reverse) {
1132         done = p->ir->CreateICmpUGT(load, zerokey, "tmp");
1133         load = p->ir->CreateSub(load, LLConstantInt::get(keytype, 1, false), "tmp");
1134         DtoStore(load, keyvar);
1135     }
1136     llvm::BranchInst::Create(bodybb, endbb, done, p->scopebb());
1137
1138     // init body
1139     p->scope() = IRScope(bodybb,nextbb);
1140
1141     // get value for this iteration
1142     LLConstant* zero = LLConstantInt::get(keytype,0,false);
1143     LLValue* loadedKey = p->ir->CreateLoad(keyvar,"tmp");
1144     LLValue* gep = DtoGEP1(val,loadedKey);
1145
1146     if (!value->isRef() && !value->isOut()) {
1147         // Copy value to local variable, and use it as the value variable.
1148         DVarValue dst(value->type, valvar);
1149         DVarValue src(value->type, gep);
1150         DtoAssign(loc, &dst, &src);
1151         value->ir.irLocal->value = valvar;
1152     } else {
1153         // Use the GEP as the address of the value variable.
1154         DtoRawVarDeclaration(value, gep);
1155     }
1156
1157     // emit body
1158     p->func()->gen->targetScopes.push_back(IRTargetScope(this,NULL,nextbb,endbb));
1159     if(body)
1160         body->toIR(p);
1161     p->func()->gen->targetScopes.pop_back();
1162
1163     if (!p->scopereturned())
1164         llvm::BranchInst::Create(nextbb, p->scopebb());
1165
1166     // next
1167     p->scope() = IRScope(nextbb,endbb);
1168     if (op == TOKforeach) {
1169         LLValue* load = DtoLoad(keyvar);
1170         load = p->ir->CreateAdd(load, LLConstantInt::get(keytype, 1, false), "tmp");
1171         DtoStore(load, keyvar);
1172     }
1173     llvm::BranchInst::Create(condbb, p->scopebb());
1174
1175     // end
1176     p->scope() = IRScope(endbb,oldend);
1177 }
1178
1179 //////////////////////////////////////////////////////////////////////////////
1180
1181 #if DMDV2
1182
1183 void ForeachRangeStatement::toIR(IRState* p)
1184 {
1185     Logger::println("ForeachRangeStatement::toIR(): %s", loc.toChars());
1186     LOG_SCOPE;
1187
1188     #ifndef DISABLE_DEBUG_INFO
1189     if (global.params.symdebug)
1190         DtoDwarfStopPoint(loc.linnum);
1191     #endif
1192
1193     // evaluate lwr/upr
1194     assert(lwr->type->isintegral());
1195     LLValue* lower = lwr->toElem(p)->getRVal();
1196     assert(upr->type->isintegral());
1197     LLValue* upper = upr->toElem(p)->getRVal();
1198
1199     // handle key
1200     assert(key->type->isintegral());
1201     LLValue* keyval = DtoRawVarDeclaration(key);
1202
1203     // store initial value in key
1204     if (op == TOKforeach)
1205         DtoStore(lower, keyval);
1206     else
1207         DtoStore(upper, keyval);
1208
1209     // set up the block we'll need
1210     llvm::BasicBlock* oldend = gIR->scopeend();
1211     llvm::BasicBlock* condbb = llvm::BasicBlock::Create(gIR->context(), "foreachrange_cond", p->topfunc(), oldend);
1212     llvm::BasicBlock* bodybb = llvm::BasicBlock::Create(gIR->context(), "foreachrange_body", p->topfunc(), oldend);
1213     llvm::BasicBlock* nextbb = llvm::BasicBlock::Create(gIR->context(), "foreachrange_next", p->topfunc(), oldend);
1214     llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "foreachrange_end", p->topfunc(), oldend);
1215
1216     // jump to condition
1217     llvm::BranchInst::Create(condbb, p->scopebb());
1218
1219     // CONDITION
1220     p->scope() = IRScope(condbb,bodybb);
1221
1222     // first we test that lwr < upr
1223     lower = DtoLoad(keyval);
1224     assert(lower->getType() == upper->getType());
1225     llvm::ICmpInst::Predicate cmpop;
1226     if (key->type->isunsigned())
1227     {
1228         cmpop = (op == TOKforeach)
1229         ? llvm::ICmpInst::ICMP_ULT
1230         : llvm::ICmpInst::ICMP_UGT;
1231     }
1232     else
1233     {
1234         cmpop = (op == TOKforeach)
1235         ? llvm::ICmpInst::ICMP_SLT
1236         : llvm::ICmpInst::ICMP_SGT;
1237     }
1238     LLValue* cond = p->ir->CreateICmp(cmpop, lower, upper);
1239
1240     // jump to the body if range is ok, to the end if not
1241     llvm::BranchInst::Create(bodybb, endbb, cond, p->scopebb());
1242
1243     // BODY
1244     p->scope() = IRScope(bodybb,nextbb);
1245
1246     // reverse foreach decrements here
1247     if (op == TOKforeach_reverse)
1248     {
1249         LLValue* v = DtoLoad(keyval);
1250         LLValue* one = LLConstantInt::get(v->getType(), 1, false);
1251         v = p->ir->CreateSub(v, one);
1252         DtoStore(v, keyval);
1253     }
1254
1255     // emit body
1256     p->func()->gen->targetScopes.push_back(IRTargetScope(this,NULL,nextbb,endbb));
1257     if (body)
1258         body->toIR(p);
1259     p->func()->gen->targetScopes.pop_back();
1260
1261     // jump to next iteration
1262     if (!p->scopereturned())
1263         llvm::BranchInst::Create(nextbb, p->scopebb());
1264
1265     // NEXT
1266     p->scope() = IRScope(nextbb,endbb);
1267
1268     // forward foreach increments here
1269     if (op == TOKforeach)
1270     {
1271         LLValue* v = DtoLoad(keyval);
1272         LLValue* one = LLConstantInt::get(v->getType(), 1, false);
1273         v = p->ir->CreateAdd(v, one);
1274         DtoStore(v, keyval);
1275     }
1276
1277     // jump to condition
1278     llvm::BranchInst::Create(condbb, p->scopebb());
1279
1280     // END
1281     p->scope() = IRScope(endbb,oldend);
1282 }
1283
1284 #endif // D2
1285
1286 //////////////////////////////////////////////////////////////////////////////
1287
1288 void LabelStatement::toIR(IRState* p)
1289 {
1290     Logger::println("LabelStatement::toIR(): %s", loc.toChars());
1291     LOG_SCOPE;
1292
1293     // if it's an inline asm label, we don't create a basicblock, just emit it in the asm
1294     if (p->asmBlock)
1295     {
1296         IRAsmStmt* a = new IRAsmStmt;
1297         a->code += p->func()->decl->mangle();
1298         a->code += "_";
1299         a->code += ident->toChars();
1300         a->code += ":";
1301         p->asmBlock->s.push_back(a);
1302         p->asmBlock->internalLabels.push_back(ident);
1303
1304         // disable inlining
1305         gIR->func()->setNeverInline();
1306     }
1307     else
1308     {
1309         std::string labelname = p->func()->gen->getScopedLabelName(ident->toChars());
1310         llvm::BasicBlock*& labelBB = p->func()->gen->labelToBB[labelname];
1311
1312         llvm::BasicBlock* oldend = gIR->scopeend();
1313         if (labelBB != NULL) {
1314             labelBB->moveBefore(oldend);
1315         } else {
1316             labelBB = llvm::BasicBlock::Create(gIR->context(), "label_" + labelname, p->topfunc(), oldend);
1317         }
1318
1319         if (!p->scopereturned())
1320             llvm::BranchInst::Create(labelBB, p->scopebb());
1321
1322         p->scope() = IRScope(labelBB,oldend);
1323     }
1324
1325     if (statement) {
1326         p->func()->gen->targetScopes.push_back(IRTargetScope(this,NULL,NULL,NULL));
1327         statement->toIR(p);
1328         p->func()->gen->targetScopes.pop_back();
1329     }
1330 }
1331
1332 //////////////////////////////////////////////////////////////////////////////
1333
1334 void GotoStatement::toIR(IRState* p)
1335 {
1336     Logger::println("GotoStatement::toIR(): %s", loc.toChars());
1337     LOG_SCOPE;
1338
1339     #ifndef DISABLE_DEBUG_INFO
1340     if (global.params.symdebug)
1341         DtoDwarfStopPoint(loc.linnum);
1342     #endif
1343
1344     llvm::BasicBlock* oldend = gIR->scopeend();
1345     llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergoto", p->topfunc(), oldend);
1346
1347     DtoGoto(loc, label->ident, enclosingFinally);
1348
1349     p->scope() = IRScope(bb,oldend);
1350 }
1351
1352 //////////////////////////////////////////////////////////////////////////////
1353
1354 void GotoDefaultStatement::toIR(IRState* p)
1355 {
1356     Logger::println("GotoDefaultStatement::toIR(): %s", loc.toChars());
1357     LOG_SCOPE;
1358
1359     #ifndef DISABLE_DEBUG_INFO
1360     if (global.params.symdebug)
1361         DtoDwarfStopPoint(loc.linnum);
1362     #endif
1363
1364     llvm::BasicBlock* oldend = gIR->scopeend();
1365     llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergotodefault", p->topfunc(), oldend);
1366
1367     assert(!p->scopereturned());
1368     assert(sw->sdefault->bodyBB);
1369
1370     DtoEnclosingHandlers(loc, sw);
1371
1372     llvm::BranchInst::Create(sw->sdefault->bodyBB, p->scopebb());
1373     p->scope() = IRScope(bb,oldend);
1374 }
1375
1376 //////////////////////////////////////////////////////////////////////////////
1377
1378 void GotoCaseStatement::toIR(IRState* p)
1379 {
1380     Logger::println("GotoCaseStatement::toIR(): %s", loc.toChars());
1381     LOG_SCOPE;
1382
1383     #ifndef DISABLE_DEBUG_INFO
1384     if (global.params.symdebug)
1385         DtoDwarfStopPoint(loc.linnum);
1386     #endif
1387
1388     llvm::BasicBlock* oldend = gIR->scopeend();
1389     llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergotocase", p->topfunc(), oldend);
1390
1391     assert(!p->scopereturned());
1392     if (!cs->bodyBB)
1393     {
1394         cs->bodyBB = llvm::BasicBlock::Create(gIR->context(), "goto_case", p->topfunc(), p->scopeend());
1395     }
1396
1397     DtoEnclosingHandlers(loc, sw);
1398
1399     llvm::BranchInst::Create(cs->bodyBB, p->scopebb());
1400     p->scope() = IRScope(bb,oldend);
1401 }
1402
1403 //////////////////////////////////////////////////////////////////////////////
1404
1405 void WithStatement::toIR(IRState* p)
1406 {
1407     Logger::println("WithStatement::toIR(): %s", loc.toChars());
1408     LOG_SCOPE;
1409
1410     #ifndef DISABLE_DEBUG_INFO
1411     if (global.params.symdebug)
1412         DtoDwarfStopPoint(loc.linnum);
1413     #endif
1414
1415     assert(exp);
1416     assert(body);
1417
1418     // with(..) can either be used with expressions or with symbols
1419     // wthis == null indicates the symbol form
1420     if (wthis) {
1421         DValue* e = exp->toElem(p);
1422         LLValue* mem = DtoRawVarDeclaration(wthis);
1423         DtoStore(e->getRVal(), mem);
1424     }
1425
1426     body->toIR(p);
1427 }
1428
1429 //////////////////////////////////////////////////////////////////////////////
1430
1431 static LLConstant* generate_unique_critical_section()
1432 {
1433     const LLType* Mty = DtoMutexType();
1434     return new llvm::GlobalVariable(*gIR->module, Mty, false, llvm::GlobalValue::InternalLinkage, LLConstant::getNullValue(Mty), ".uniqueCS");
1435 }
1436
1437 void SynchronizedStatement::toIR(IRState* p)
1438 {
1439     Logger::println("SynchronizedStatement::toIR(): %s", loc.toChars());
1440     LOG_SCOPE;
1441
1442     #ifndef DISABLE_DEBUG_INFO
1443     if (global.params.symdebug)
1444         DtoDwarfStopPoint(loc.linnum);
1445     #endif
1446
1447     // enter lock
1448     if (exp)
1449     {
1450         llsync = exp->toElem(p)->getRVal();
1451         DtoEnterMonitor(llsync);
1452     }
1453     else
1454     {
1455         llsync = generate_unique_critical_section();
1456         DtoEnterCritical(llsync);
1457     }
1458
1459     // emit body
1460     p->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingSynchro(this),NULL,NULL));
1461     body->toIR(p);
1462     p->func()->gen->targetScopes.pop_back();
1463
1464     // exit lock
1465     // no point in a unreachable unlock, terminating statements must insert this themselves.
1466     if (p->scopereturned())
1467         return;
1468     else if (exp)
1469         DtoLeaveMonitor(llsync);
1470     else
1471         DtoLeaveCritical(llsync);
1472 }
1473
1474 //////////////////////////////////////////////////////////////////////////////
1475
1476 void VolatileStatement::toIR(IRState* p)
1477 {
1478     Logger::println("VolatileStatement::toIR(): %s", loc.toChars());
1479     LOG_SCOPE;
1480
1481     #ifndef DISABLE_DEBUG_INFO
1482     if (global.params.symdebug)
1483         DtoDwarfStopPoint(loc.linnum);
1484     #endif
1485
1486     // mark in-volatile
1487     // FIXME
1488
1489     // has statement
1490     if (statement != NULL)
1491     {
1492         // load-store
1493         DtoMemoryBarrier(false, true, false, false);
1494
1495         // do statement
1496     p->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingVolatile(this),NULL,NULL));
1497         statement->toIR(p);
1498     p->func()->gen->targetScopes.pop_back();
1499
1500         // no point in a unreachable barrier, terminating statements must insert this themselves.
1501         if (statement->blockExit() & BEfallthru)
1502         {
1503             // store-load
1504             DtoMemoryBarrier(false, false, true, false);
1505         }
1506     }
1507     // barrier only
1508     else
1509     {
1510         // load-store & store-load
1511         DtoMemoryBarrier(false, true, true, false);
1512     }
1513
1514     // restore volatile state
1515     // FIXME
1516 }
1517
1518 //////////////////////////////////////////////////////////////////////////////
1519
1520 void SwitchErrorStatement::toIR(IRState* p)
1521 {
1522     Logger::println("SwitchErrorStatement::toIR(): %s", loc.toChars());
1523     LOG_SCOPE;
1524
1525     llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_switch_error");
1526
1527     std::vector<LLValue*> args;
1528
1529     // file param
1530     IrModule* irmod = getIrModule(NULL);
1531     args.push_back(DtoLoad(irmod->fileName));
1532
1533     // line param
1534     LLConstant* c = DtoConstUint(loc.linnum);
1535     args.push_back(c);
1536
1537     // call
1538     gIR->CreateCallOrInvoke(fn, args.begin(), args.end());
1539
1540     gIR->ir->CreateUnreachable();
1541 }
1542
1543 //////////////////////////////////////////////////////////////////////////////
1544
1545 //////////////////////////////////////////////////////////////////////////////
1546
1547 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();}
1548 //STUBST(BreakStatement);
1549 //STUBST(ForStatement);
1550 //STUBST(WithStatement);
1551 //STUBST(SynchronizedStatement);
1552 //STUBST(ReturnStatement);
1553 //STUBST(ContinueStatement);
1554 //STUBST(DefaultStatement);
1555 //STUBST(CaseStatement);
1556 //STUBST(SwitchStatement);
1557 //STUBST(SwitchErrorStatement);
1558 STUBST(Statement);
1559 //STUBST(IfStatement);
1560 //STUBST(ForeachStatement);
1561 //STUBST(DoStatement);
1562 //STUBST(WhileStatement);
1563 //STUBST(ExpStatement);
1564 //STUBST(CompoundStatement);
1565 //STUBST(ScopeStatement);
1566 //STUBST(AsmStatement);
1567 //STUBST(TryCatchStatement);
1568 //STUBST(TryFinallyStatement);
1569 //STUBST(VolatileStatement);
1570 //STUBST(LabelStatement);
1571 //STUBST(ThrowStatement);
1572 //STUBST(GotoCaseStatement);
1573 //STUBST(GotoDefaultStatement);
1574 //STUBST(GotoStatement);
1575 //STUBST(UnrolledLoopStatement);
1576 //STUBST(OnScopeStatement);
1577
1578 #if DMDV2
1579 STUBST(PragmaStatement);
1580 #endif
1581
1582 //////////////////////////////////////////////////////////////////////////////
1583
1584 //////////////////////////////////////////////////////////////////////////////
1585
1586 AsmBlockStatement* Statement::endsWithAsm()
1587 {
1588     // does not end with inline asm
1589     return NULL;
1590 }
1591
1592 AsmBlockStatement* CompoundStatement::endsWithAsm()
1593 {
1594     // make the last inner statement decide
1595     if (statements && statements->dim)
1596     {
1597         unsigned last = statements->dim - 1;
1598         Statement* s = (Statement*)statements->data[last];
1599         if (s) return s->endsWithAsm();
1600     }
1601     return NULL;
1602 }
1603
1604 AsmBlockStatement* AsmBlockStatement::endsWithAsm()
1605 {
1606     // yes this is inline asm
1607     return this;
1608 }
Note: See TracBrowser for help on using the browser.
Copyright © 2008, LDC Development Team.