Mercurial > projects > ldc
comparison gen/statements.cpp @ 309:d59c363fccad trunk
[svn r330] Implemented synchronized statements.
Changed the tryfinally handlers to a more generalized EnclosingHandler.
Changed ClassInfoS to be mutable so they can be used as locks.
Added new BB after throw ala return/break etc.
author | lindquist |
---|---|
date | Sat, 28 Jun 2008 11:37:53 +0200 |
parents | 6b62e8cdf970 |
children | 9967a3270837 |
comparison
equal
deleted
inserted
replaced
308:6b62e8cdf970 | 309:d59c363fccad |
---|---|
68 p->exps.pop_back(); | 68 p->exps.pop_back(); |
69 | 69 |
70 if (!e->inPlace()) | 70 if (!e->inPlace()) |
71 DtoAssign(rvar, e); | 71 DtoAssign(rvar, e); |
72 | 72 |
73 DtoFinallyBlocks(enclosingtryfinally, NULL); | 73 DtoEnclosingHandlers(enclosinghandler, NULL); |
74 | |
75 if (f->inVolatile) { | |
76 // store-load barrier | |
77 DtoMemoryBarrier(false, false, true, false); | |
78 } | |
79 | 74 |
80 if (global.params.symdebug) DtoDwarfFuncEnd(f->decl); | 75 if (global.params.symdebug) DtoDwarfFuncEnd(f->decl); |
81 llvm::ReturnInst::Create(p->scopebb()); | 76 llvm::ReturnInst::Create(p->scopebb()); |
82 | 77 |
83 } | 78 } |
93 { | 88 { |
94 v = gIR->ir->CreateBitCast(v, p->topfunc()->getReturnType(), "tmp"); | 89 v = gIR->ir->CreateBitCast(v, p->topfunc()->getReturnType(), "tmp"); |
95 Logger::cout() << "return value after cast: " << *v << '\n'; | 90 Logger::cout() << "return value after cast: " << *v << '\n'; |
96 } | 91 } |
97 | 92 |
98 DtoFinallyBlocks(enclosingtryfinally, NULL); | 93 DtoEnclosingHandlers(enclosinghandler, NULL); |
99 | |
100 if (gIR->func()->inVolatile) { | |
101 // store-load barrier | |
102 DtoMemoryBarrier(false, false, true, false); | |
103 } | |
104 | 94 |
105 if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl); | 95 if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl); |
106 llvm::ReturnInst::Create(v, p->scopebb()); | 96 llvm::ReturnInst::Create(v, p->scopebb()); |
107 } | 97 } |
108 } | 98 } |
109 else | 99 else |
110 { | 100 { |
111 assert(p->topfunc()->getReturnType() == LLType::VoidTy); | 101 assert(p->topfunc()->getReturnType() == LLType::VoidTy); |
112 DtoFinallyBlocks(enclosingtryfinally, NULL); | 102 DtoEnclosingHandlers(enclosinghandler, NULL); |
113 | |
114 if (gIR->func()->inVolatile) { | |
115 // store-load barrier | |
116 DtoMemoryBarrier(false, false, true, false); | |
117 } | |
118 | 103 |
119 if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl); | 104 if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl); |
120 llvm::ReturnInst::Create(p->scopebb()); | 105 llvm::ReturnInst::Create(p->scopebb()); |
121 } | 106 } |
122 | 107 |
273 | 258 |
274 // rewrite scope | 259 // rewrite scope |
275 gIR->scope() = IRScope(whilebodybb,endbb); | 260 gIR->scope() = IRScope(whilebodybb,endbb); |
276 | 261 |
277 // while body code | 262 // while body code |
278 p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,whilebb,endbb)); | 263 p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,whilebb,endbb)); |
279 body->toIR(p); | 264 body->toIR(p); |
280 p->loopbbs.pop_back(); | 265 p->loopbbs.pop_back(); |
281 | 266 |
282 // loop | 267 // loop |
283 if (!gIR->scopereturned()) | 268 if (!gIR->scopereturned()) |
308 | 293 |
309 // replace current scope | 294 // replace current scope |
310 gIR->scope() = IRScope(dowhilebb,endbb); | 295 gIR->scope() = IRScope(dowhilebb,endbb); |
311 | 296 |
312 // do-while body code | 297 // do-while body code |
313 p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,dowhilebb,endbb)); | 298 p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,dowhilebb,endbb)); |
314 body->toIR(p); | 299 body->toIR(p); |
315 p->loopbbs.pop_back(); | 300 p->loopbbs.pop_back(); |
316 | 301 |
317 // create the condition | 302 // create the condition |
318 DValue* cond_e = condition->toElem(p); | 303 DValue* cond_e = condition->toElem(p); |
349 | 334 |
350 // move into the for condition block, ie. start the loop | 335 // move into the for condition block, ie. start the loop |
351 assert(!gIR->scopereturned()); | 336 assert(!gIR->scopereturned()); |
352 llvm::BranchInst::Create(forbb, gIR->scopebb()); | 337 llvm::BranchInst::Create(forbb, gIR->scopebb()); |
353 | 338 |
354 p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,forincbb,endbb)); | 339 p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,forincbb,endbb)); |
355 | 340 |
356 // replace current scope | 341 // replace current scope |
357 gIR->scope() = IRScope(forbb,forbodybb); | 342 gIR->scope() = IRScope(forbb,forbodybb); |
358 | 343 |
359 // create the condition | 344 // create the condition |
408 DtoDwarfStopPoint(loc.linnum); | 393 DtoDwarfStopPoint(loc.linnum); |
409 | 394 |
410 if (ident != 0) { | 395 if (ident != 0) { |
411 Logger::println("ident = %s", ident->toChars()); | 396 Logger::println("ident = %s", ident->toChars()); |
412 | 397 |
413 DtoFinallyBlocks(enclosingtryfinally, target->enclosingtryfinally); | 398 DtoEnclosingHandlers(enclosinghandler, target->enclosinghandler); |
414 | 399 |
415 // get the loop statement the label refers to | 400 // get the loop statement the label refers to |
416 Statement* targetLoopStatement = target->statement; | 401 Statement* targetLoopStatement = target->statement; |
417 ScopeStatement* tmp; | 402 ScopeStatement* tmp; |
418 while(tmp = targetLoopStatement->isScopeStatement()) | 403 while(tmp = targetLoopStatement->isScopeStatement()) |
429 } | 414 } |
430 } | 415 } |
431 assert(found); | 416 assert(found); |
432 } | 417 } |
433 else { | 418 else { |
434 DtoFinallyBlocks(enclosingtryfinally, p->loopbbs.back().enclosingtryfinally); | 419 DtoEnclosingHandlers(enclosinghandler, p->loopbbs.back().enclosinghandler); |
435 llvm::BranchInst::Create(p->loopbbs.back().end, p->scopebb()); | 420 llvm::BranchInst::Create(p->loopbbs.back().end, p->scopebb()); |
436 } | 421 } |
437 | 422 |
438 // the break terminated this basicblock, start a new one | 423 // the break terminated this basicblock, start a new one |
439 llvm::BasicBlock* oldend = gIR->scopeend(); | 424 llvm::BasicBlock* oldend = gIR->scopeend(); |
452 DtoDwarfStopPoint(loc.linnum); | 437 DtoDwarfStopPoint(loc.linnum); |
453 | 438 |
454 if (ident != 0) { | 439 if (ident != 0) { |
455 Logger::println("ident = %s", ident->toChars()); | 440 Logger::println("ident = %s", ident->toChars()); |
456 | 441 |
457 DtoFinallyBlocks(enclosingtryfinally, target->enclosingtryfinally); | 442 DtoEnclosingHandlers(enclosinghandler, target->enclosinghandler); |
458 | 443 |
459 // get the loop statement the label refers to | 444 // get the loop statement the label refers to |
460 Statement* targetLoopStatement = target->statement; | 445 Statement* targetLoopStatement = target->statement; |
461 ScopeStatement* tmp; | 446 ScopeStatement* tmp; |
462 while(tmp = targetLoopStatement->isScopeStatement()) | 447 while(tmp = targetLoopStatement->isScopeStatement()) |
471 } | 456 } |
472 } | 457 } |
473 assert(0); | 458 assert(0); |
474 } | 459 } |
475 else { | 460 else { |
476 DtoFinallyBlocks(enclosingtryfinally, gIR->loopbbs.back().enclosingtryfinally); | 461 DtoEnclosingHandlers(enclosinghandler, gIR->loopbbs.back().enclosinghandler); |
477 llvm::BranchInst::Create(gIR->loopbbs.back().begin, gIR->scopebb()); | 462 llvm::BranchInst::Create(gIR->loopbbs.back().begin, gIR->scopebb()); |
478 } | 463 } |
479 } | 464 } |
480 | 465 |
481 ////////////////////////////////////////////////////////////////////////////// | 466 ////////////////////////////////////////////////////////////////////////////// |
597 //Logger::cout() << "calling: " << *fn << '\n'; | 582 //Logger::cout() << "calling: " << *fn << '\n'; |
598 LLValue* arg = DtoBitCast(e->getRVal(), fn->getFunctionType()->getParamType(0)); | 583 LLValue* arg = DtoBitCast(e->getRVal(), fn->getFunctionType()->getParamType(0)); |
599 //Logger::cout() << "arg: " << *arg << '\n'; | 584 //Logger::cout() << "arg: " << *arg << '\n'; |
600 gIR->ir->CreateCall(fn, arg, ""); | 585 gIR->ir->CreateCall(fn, arg, ""); |
601 gIR->ir->CreateUnreachable(); | 586 gIR->ir->CreateUnreachable(); |
587 | |
588 // need a block after the throw for now | |
589 llvm::BasicBlock* oldend = gIR->scopeend(); | |
590 llvm::BasicBlock* bb = llvm::BasicBlock::Create("afterthrow", p->topfunc(), oldend); | |
591 p->scope() = IRScope(bb,oldend); | |
602 } | 592 } |
603 | 593 |
604 ////////////////////////////////////////////////////////////////////////////// | 594 ////////////////////////////////////////////////////////////////////////////// |
605 | 595 |
606 // used to build the sorted list of cases | 596 // used to build the sorted list of cases |
765 | 755 |
766 // do switch body | 756 // do switch body |
767 assert(body); | 757 assert(body); |
768 | 758 |
769 p->scope() = IRScope(bodybb, endbb); | 759 p->scope() = IRScope(bodybb, endbb); |
770 p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,p->scopebb(),endbb)); | 760 p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,p->scopebb(),endbb)); |
771 body->toIR(p); | 761 body->toIR(p); |
772 p->loopbbs.pop_back(); | 762 p->loopbbs.pop_back(); |
773 | 763 |
774 if (!p->scopereturned()) | 764 if (!p->scopereturned()) |
775 llvm::BranchInst::Create(endbb, p->scopebb()); | 765 llvm::BranchInst::Create(endbb, p->scopebb()); |
849 | 839 |
850 llvm::BasicBlock* oldend = gIR->scopeend(); | 840 llvm::BasicBlock* oldend = gIR->scopeend(); |
851 llvm::BasicBlock* endbb = llvm::BasicBlock::Create("unrolledend", p->topfunc(), oldend); | 841 llvm::BasicBlock* endbb = llvm::BasicBlock::Create("unrolledend", p->topfunc(), oldend); |
852 | 842 |
853 p->scope() = IRScope(p->scopebb(),endbb); | 843 p->scope() = IRScope(p->scopebb(),endbb); |
854 p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,p->scopebb(),endbb)); | 844 p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,p->scopebb(),endbb)); |
855 | 845 |
856 for (int i=0; i<statements->dim; ++i) | 846 for (int i=0; i<statements->dim; ++i) |
857 { | 847 { |
858 Statement* s = (Statement*)statements->data[i]; | 848 Statement* s = (Statement*)statements->data[i]; |
859 s->toIR(p); | 849 s->toIR(p); |
972 DtoAssign(dst, src); | 962 DtoAssign(dst, src); |
973 value->ir.irLocal->value = valvar; | 963 value->ir.irLocal->value = valvar; |
974 } | 964 } |
975 | 965 |
976 // emit body | 966 // emit body |
977 p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,nextbb,endbb)); | 967 p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,nextbb,endbb)); |
978 body->toIR(p); | 968 body->toIR(p); |
979 p->loopbbs.pop_back(); | 969 p->loopbbs.pop_back(); |
980 | 970 |
981 if (!p->scopereturned()) | 971 if (!p->scopereturned()) |
982 llvm::BranchInst::Create(nextbb, p->scopebb()); | 972 llvm::BranchInst::Create(nextbb, p->scopebb()); |
1045 assert(tf == NULL); | 1035 assert(tf == NULL); |
1046 | 1036 |
1047 llvm::BasicBlock* oldend = gIR->scopeend(); | 1037 llvm::BasicBlock* oldend = gIR->scopeend(); |
1048 llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergoto", p->topfunc(), oldend); | 1038 llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergoto", p->topfunc(), oldend); |
1049 | 1039 |
1050 DtoGoto(&loc, label->ident, enclosingtryfinally); | 1040 DtoGoto(&loc, label->ident, enclosinghandler); |
1051 | 1041 |
1052 p->scope() = IRScope(bb,oldend); | 1042 p->scope() = IRScope(bb,oldend); |
1053 } | 1043 } |
1054 | 1044 |
1055 ////////////////////////////////////////////////////////////////////////////// | 1045 ////////////////////////////////////////////////////////////////////////////// |
1066 llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergotodefault", p->topfunc(), oldend); | 1056 llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergotodefault", p->topfunc(), oldend); |
1067 | 1057 |
1068 assert(!p->scopereturned()); | 1058 assert(!p->scopereturned()); |
1069 assert(sw->sdefault->bodyBB); | 1059 assert(sw->sdefault->bodyBB); |
1070 | 1060 |
1071 DtoFinallyBlocks(enclosingtryfinally, sw->enclosingtryfinally); | 1061 DtoEnclosingHandlers(enclosinghandler, sw->enclosinghandler); |
1072 | 1062 |
1073 llvm::BranchInst::Create(sw->sdefault->bodyBB, p->scopebb()); | 1063 llvm::BranchInst::Create(sw->sdefault->bodyBB, p->scopebb()); |
1074 p->scope() = IRScope(bb,oldend); | 1064 p->scope() = IRScope(bb,oldend); |
1075 } | 1065 } |
1076 | 1066 |
1091 if (!cs->bodyBB) | 1081 if (!cs->bodyBB) |
1092 { | 1082 { |
1093 cs->bodyBB = llvm::BasicBlock::Create("goto_case", p->topfunc(), p->scopeend()); | 1083 cs->bodyBB = llvm::BasicBlock::Create("goto_case", p->topfunc(), p->scopeend()); |
1094 } | 1084 } |
1095 | 1085 |
1096 DtoFinallyBlocks(enclosingtryfinally, sw->enclosingtryfinally); | 1086 DtoEnclosingHandlers(enclosinghandler, sw->enclosinghandler); |
1097 | 1087 |
1098 llvm::BranchInst::Create(cs->bodyBB, p->scopebb()); | 1088 llvm::BranchInst::Create(cs->bodyBB, p->scopebb()); |
1099 p->scope() = IRScope(bb,oldend); | 1089 p->scope() = IRScope(bb,oldend); |
1100 } | 1090 } |
1101 | 1091 |
1120 body->toIR(p); | 1110 body->toIR(p); |
1121 } | 1111 } |
1122 | 1112 |
1123 ////////////////////////////////////////////////////////////////////////////// | 1113 ////////////////////////////////////////////////////////////////////////////// |
1124 | 1114 |
1115 static LLConstant* generate_unique_critical_section() | |
1116 { | |
1117 const LLType* Mty = DtoMutexType(); | |
1118 return new llvm::GlobalVariable(Mty, false, llvm::GlobalValue::InternalLinkage, LLConstant::getNullValue(Mty), ".uniqueCS", gIR->module); | |
1119 } | |
1120 | |
1125 void SynchronizedStatement::toIR(IRState* p) | 1121 void SynchronizedStatement::toIR(IRState* p) |
1126 { | 1122 { |
1127 Logger::println("SynchronizedStatement::toIR(): %s", loc.toChars()); | 1123 Logger::println("SynchronizedStatement::toIR(): %s", loc.toChars()); |
1128 LOG_SCOPE; | 1124 LOG_SCOPE; |
1129 | 1125 |
1130 Logger::attention(loc, "synchronized is currently ignored. only the body will be emitted"); | 1126 if (global.params.symdebug) |
1131 | 1127 DtoDwarfStopPoint(loc.linnum); |
1132 if (global.params.symdebug) | 1128 |
1133 DtoDwarfStopPoint(loc.linnum); | 1129 // enter lock |
1134 | 1130 if (exp) |
1131 { | |
1132 llsync = exp->toElem(p)->getRVal(); | |
1133 DtoEnterMonitor(llsync); | |
1134 } | |
1135 else | |
1136 { | |
1137 llsync = generate_unique_critical_section(); | |
1138 DtoEnterCritical(llsync); | |
1139 } | |
1140 | |
1141 // emit body | |
1135 body->toIR(p); | 1142 body->toIR(p); |
1136 } | 1143 |
1137 | 1144 // exit lock |
1138 ////////////////////////////////////////////////////////////////////////////// | 1145 // no point in a unreachable unlock, terminating statements must insert this themselves. |
1139 | 1146 if (p->scopereturned()) |
1140 /* this has moved to asmstmt.cpp | 1147 return; |
1141 void AsmStatement::toIR(IRState* p) | 1148 else if (exp) |
1142 { | 1149 DtoLeaveMonitor(llsync); |
1143 Logger::println("AsmStatement::toIR(): %s", loc.toChars()); | 1150 else |
1144 LOG_SCOPE; | 1151 DtoLeaveCritical(llsync); |
1145 // error("%s: inline asm is not yet implemented", loc.toChars()); | 1152 } |
1146 // fatal(); | 1153 |
1147 | |
1148 assert(!asmcode && !asmalign && !refparam && !naked && !regs); | |
1149 | |
1150 Token* t = tokens; | |
1151 assert(t); | |
1152 | |
1153 std::string asmstr; | |
1154 | |
1155 do { | |
1156 Logger::println("token: %s", t->toChars()); | |
1157 asmstr.append(t->toChars()); | |
1158 asmstr.append(" "); | |
1159 } while (t = t->next); | |
1160 | |
1161 Logger::println("asm expr = '%s'", asmstr.c_str()); | |
1162 | |
1163 // create function type | |
1164 std::vector<const LLType*> args; | |
1165 const llvm::FunctionType* fty = llvm::FunctionType::get(DtoSize_t(), args, false); | |
1166 | |
1167 // create inline asm callee | |
1168 llvm::InlineAsm* inasm = llvm::InlineAsm::get(fty, asmstr, "r,r", false); | |
1169 | |
1170 assert(0); | |
1171 } | |
1172 */ | |
1173 ////////////////////////////////////////////////////////////////////////////// | 1154 ////////////////////////////////////////////////////////////////////////////// |
1174 | 1155 |
1175 void VolatileStatement::toIR(IRState* p) | 1156 void VolatileStatement::toIR(IRState* p) |
1176 { | 1157 { |
1177 Logger::println("VolatileStatement::toIR(): %s", loc.toChars()); | 1158 Logger::println("VolatileStatement::toIR(): %s", loc.toChars()); |
1179 | 1160 |
1180 if (global.params.symdebug) | 1161 if (global.params.symdebug) |
1181 DtoDwarfStopPoint(loc.linnum); | 1162 DtoDwarfStopPoint(loc.linnum); |
1182 | 1163 |
1183 // mark in-volatile | 1164 // mark in-volatile |
1184 bool old = gIR->func()->inVolatile; | 1165 // FIXME |
1185 gIR->func()->inVolatile = true; | |
1186 | 1166 |
1187 // has statement | 1167 // has statement |
1188 if (statement != NULL) | 1168 if (statement != NULL) |
1189 { | 1169 { |
1190 // load-store | 1170 // load-store |
1191 DtoMemoryBarrier(false, true, false, false); | 1171 DtoMemoryBarrier(false, true, false, false); |
1192 | 1172 |
1193 // do statement | 1173 // do statement |
1194 statement->toIR(p); | 1174 statement->toIR(p); |
1195 | 1175 |
1196 // no point in a unreachable barrier, terminating statements should insert this themselves. | 1176 // no point in a unreachable barrier, terminating statements must insert this themselves. |
1197 if (statement->fallOffEnd()) | 1177 if (statement->fallOffEnd()) |
1198 { | 1178 { |
1199 // store-load | 1179 // store-load |
1200 DtoMemoryBarrier(false, false, true, false); | 1180 DtoMemoryBarrier(false, false, true, false); |
1201 } | 1181 } |
1206 // load-store & store-load | 1186 // load-store & store-load |
1207 DtoMemoryBarrier(false, true, true, false); | 1187 DtoMemoryBarrier(false, true, true, false); |
1208 } | 1188 } |
1209 | 1189 |
1210 // restore volatile state | 1190 // restore volatile state |
1211 gIR->func()->inVolatile = old; | 1191 // FIXME |
1212 } | 1192 } |
1213 | 1193 |
1214 ////////////////////////////////////////////////////////////////////////////// | 1194 ////////////////////////////////////////////////////////////////////////////// |
1215 | 1195 |
1216 ////////////////////////////////////////////////////////////////////////////// | 1196 ////////////////////////////////////////////////////////////////////////////// |