Mercurial > projects > ldc
comparison gen/statements.cpp @ 302:bef811104734 trunk
[svn r323] Branching out of inline asm works.
Renamed emit_finallyblocks to DtoFinallyBlocks and moved to llvmhelpers.
Added enclosingtryfinally to AsmBlockStatement, so branches out of asm blocks respect finallys.
Refactored some GotoStatement code into DtoGoto.
author | ChristianK |
---|---|
date | Wed, 25 Jun 2008 20:39:09 +0200 |
parents | df8a7b8d5929 |
children | 3ebc136702dd |
comparison
equal
deleted
inserted
replaced
301:f42a1090e895 | 302:bef811104734 |
---|---|
42 s->toIR(p); | 42 s->toIR(p); |
43 } | 43 } |
44 } | 44 } |
45 } | 45 } |
46 | 46 |
47 ////////////////////////////////////////////////////////////////////////////// | |
48 | |
49 // generates IR for finally blocks between the 'start' and 'end' statements | |
50 // will begin with the finally block belonging to 'start' and does not include | |
51 // the finally block of 'end' | |
52 void emit_finallyblocks(IRState* p, TryFinallyStatement* start, TryFinallyStatement* end) | |
53 { | |
54 // verify that end encloses start | |
55 TryFinallyStatement* endfinally = start; | |
56 while(endfinally != NULL && endfinally != end) { | |
57 endfinally = endfinally->enclosingtryfinally; | |
58 } | |
59 assert(endfinally == end); | |
60 | |
61 // emit code for finallys between start and end | |
62 TryFinallyStatement* tf = start; | |
63 while(tf != end) { | |
64 tf->finalbody->toIR(p); | |
65 tf = tf->enclosingtryfinally; | |
66 } | |
67 } | |
68 | 47 |
69 ////////////////////////////////////////////////////////////////////////////// | 48 ////////////////////////////////////////////////////////////////////////////// |
70 | 49 |
71 void ReturnStatement::toIR(IRState* p) | 50 void ReturnStatement::toIR(IRState* p) |
72 { | 51 { |
89 p->exps.pop_back(); | 68 p->exps.pop_back(); |
90 | 69 |
91 if (!e->inPlace()) | 70 if (!e->inPlace()) |
92 DtoAssign(rvar, e); | 71 DtoAssign(rvar, e); |
93 | 72 |
94 emit_finallyblocks(p, enclosingtryfinally, NULL); | 73 DtoFinallyBlocks(enclosingtryfinally, NULL); |
95 | 74 |
96 if (f->inVolatile) { | 75 if (f->inVolatile) { |
97 // store-load barrier | 76 // store-load barrier |
98 DtoMemoryBarrier(false, false, true, false); | 77 DtoMemoryBarrier(false, false, true, false); |
99 } | 78 } |
114 { | 93 { |
115 v = gIR->ir->CreateBitCast(v, p->topfunc()->getReturnType(), "tmp"); | 94 v = gIR->ir->CreateBitCast(v, p->topfunc()->getReturnType(), "tmp"); |
116 Logger::cout() << "return value after cast: " << *v << '\n'; | 95 Logger::cout() << "return value after cast: " << *v << '\n'; |
117 } | 96 } |
118 | 97 |
119 emit_finallyblocks(p, enclosingtryfinally, NULL); | 98 DtoFinallyBlocks(enclosingtryfinally, NULL); |
120 | 99 |
121 if (gIR->func()->inVolatile) { | 100 if (gIR->func()->inVolatile) { |
122 // store-load barrier | 101 // store-load barrier |
123 DtoMemoryBarrier(false, false, true, false); | 102 DtoMemoryBarrier(false, false, true, false); |
124 } | 103 } |
128 } | 107 } |
129 } | 108 } |
130 else | 109 else |
131 { | 110 { |
132 assert(p->topfunc()->getReturnType() == LLType::VoidTy); | 111 assert(p->topfunc()->getReturnType() == LLType::VoidTy); |
133 emit_finallyblocks(p, enclosingtryfinally, NULL); | 112 DtoFinallyBlocks(enclosingtryfinally, NULL); |
134 | 113 |
135 if (gIR->func()->inVolatile) { | 114 if (gIR->func()->inVolatile) { |
136 // store-load barrier | 115 // store-load barrier |
137 DtoMemoryBarrier(false, false, true, false); | 116 DtoMemoryBarrier(false, false, true, false); |
138 } | 117 } |
429 DtoDwarfStopPoint(loc.linnum); | 408 DtoDwarfStopPoint(loc.linnum); |
430 | 409 |
431 if (ident != 0) { | 410 if (ident != 0) { |
432 Logger::println("ident = %s", ident->toChars()); | 411 Logger::println("ident = %s", ident->toChars()); |
433 | 412 |
434 emit_finallyblocks(p, enclosingtryfinally, target->enclosingtryfinally); | 413 DtoFinallyBlocks(enclosingtryfinally, target->enclosingtryfinally); |
435 | 414 |
436 // get the loop statement the label refers to | 415 // get the loop statement the label refers to |
437 Statement* targetLoopStatement = target->statement; | 416 Statement* targetLoopStatement = target->statement; |
438 ScopeStatement* tmp; | 417 ScopeStatement* tmp; |
439 while(tmp = targetLoopStatement->isScopeStatement()) | 418 while(tmp = targetLoopStatement->isScopeStatement()) |
450 } | 429 } |
451 } | 430 } |
452 assert(found); | 431 assert(found); |
453 } | 432 } |
454 else { | 433 else { |
455 emit_finallyblocks(p, enclosingtryfinally, p->loopbbs.back().enclosingtryfinally); | 434 DtoFinallyBlocks(enclosingtryfinally, p->loopbbs.back().enclosingtryfinally); |
456 llvm::BranchInst::Create(p->loopbbs.back().end, p->scopebb()); | 435 llvm::BranchInst::Create(p->loopbbs.back().end, p->scopebb()); |
457 } | 436 } |
458 | 437 |
459 // the break terminated this basicblock, start a new one | 438 // the break terminated this basicblock, start a new one |
460 llvm::BasicBlock* oldend = gIR->scopeend(); | 439 llvm::BasicBlock* oldend = gIR->scopeend(); |
473 DtoDwarfStopPoint(loc.linnum); | 452 DtoDwarfStopPoint(loc.linnum); |
474 | 453 |
475 if (ident != 0) { | 454 if (ident != 0) { |
476 Logger::println("ident = %s", ident->toChars()); | 455 Logger::println("ident = %s", ident->toChars()); |
477 | 456 |
478 emit_finallyblocks(p, enclosingtryfinally, target->enclosingtryfinally); | 457 DtoFinallyBlocks(enclosingtryfinally, target->enclosingtryfinally); |
479 | 458 |
480 // get the loop statement the label refers to | 459 // get the loop statement the label refers to |
481 Statement* targetLoopStatement = target->statement; | 460 Statement* targetLoopStatement = target->statement; |
482 ScopeStatement* tmp; | 461 ScopeStatement* tmp; |
483 while(tmp = targetLoopStatement->isScopeStatement()) | 462 while(tmp = targetLoopStatement->isScopeStatement()) |
492 } | 471 } |
493 } | 472 } |
494 assert(0); | 473 assert(0); |
495 } | 474 } |
496 else { | 475 else { |
497 emit_finallyblocks(p, enclosingtryfinally, gIR->loopbbs.back().enclosingtryfinally); | 476 DtoFinallyBlocks(enclosingtryfinally, gIR->loopbbs.back().enclosingtryfinally); |
498 llvm::BranchInst::Create(gIR->loopbbs.back().begin, gIR->scopebb()); | 477 llvm::BranchInst::Create(gIR->loopbbs.back().begin, gIR->scopebb()); |
499 } | 478 } |
500 } | 479 } |
501 | 480 |
502 ////////////////////////////////////////////////////////////////////////////// | 481 ////////////////////////////////////////////////////////////////////////////// |
1106 assert(tf == NULL); | 1085 assert(tf == NULL); |
1107 | 1086 |
1108 llvm::BasicBlock* oldend = gIR->scopeend(); | 1087 llvm::BasicBlock* oldend = gIR->scopeend(); |
1109 llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergoto", p->topfunc(), oldend); | 1088 llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergoto", p->topfunc(), oldend); |
1110 | 1089 |
1111 if (label->statement->llvmBB == NULL) | 1090 DtoGoto(&loc, label, enclosingtryfinally); |
1112 label->statement->llvmBB = llvm::BasicBlock::Create("label", p->topfunc()); | 1091 |
1113 assert(!p->scopereturned()); | |
1114 | |
1115 // find finallys between goto and label | |
1116 TryFinallyStatement* endfinally = enclosingtryfinally; | |
1117 while(endfinally != NULL && endfinally != label->statement->enclosingtryfinally) { | |
1118 endfinally = endfinally->enclosingtryfinally; | |
1119 } | |
1120 | |
1121 // error if didn't find tf statement of label | |
1122 if(endfinally != label->statement->enclosingtryfinally) | |
1123 error("cannot goto into try block", loc.toChars()); | |
1124 | |
1125 // emit code for finallys between goto and label | |
1126 emit_finallyblocks(p, enclosingtryfinally, endfinally); | |
1127 | |
1128 llvm::BranchInst::Create(label->statement->llvmBB, p->scopebb()); | |
1129 p->scope() = IRScope(bb,oldend); | 1092 p->scope() = IRScope(bb,oldend); |
1130 } | 1093 } |
1131 | 1094 |
1132 ////////////////////////////////////////////////////////////////////////////// | 1095 ////////////////////////////////////////////////////////////////////////////// |
1133 | 1096 |
1143 llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergotodefault", p->topfunc(), oldend); | 1106 llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergotodefault", p->topfunc(), oldend); |
1144 | 1107 |
1145 assert(!p->scopereturned()); | 1108 assert(!p->scopereturned()); |
1146 assert(sw->sdefault->bodyBB); | 1109 assert(sw->sdefault->bodyBB); |
1147 | 1110 |
1148 emit_finallyblocks(p, enclosingtryfinally, sw->enclosingtryfinally); | 1111 DtoFinallyBlocks(enclosingtryfinally, sw->enclosingtryfinally); |
1149 | 1112 |
1150 llvm::BranchInst::Create(sw->sdefault->bodyBB, p->scopebb()); | 1113 llvm::BranchInst::Create(sw->sdefault->bodyBB, p->scopebb()); |
1151 p->scope() = IRScope(bb,oldend); | 1114 p->scope() = IRScope(bb,oldend); |
1152 } | 1115 } |
1153 | 1116 |
1168 if (!cs->bodyBB) | 1131 if (!cs->bodyBB) |
1169 { | 1132 { |
1170 cs->bodyBB = llvm::BasicBlock::Create("goto_case", p->topfunc(), p->scopeend()); | 1133 cs->bodyBB = llvm::BasicBlock::Create("goto_case", p->topfunc(), p->scopeend()); |
1171 } | 1134 } |
1172 | 1135 |
1173 emit_finallyblocks(p, enclosingtryfinally, sw->enclosingtryfinally); | 1136 DtoFinallyBlocks(enclosingtryfinally, sw->enclosingtryfinally); |
1174 | 1137 |
1175 llvm::BranchInst::Create(cs->bodyBB, p->scopebb()); | 1138 llvm::BranchInst::Create(cs->bodyBB, p->scopebb()); |
1176 p->scope() = IRScope(bb,oldend); | 1139 p->scope() = IRScope(bb,oldend); |
1177 } | 1140 } |
1178 | 1141 |