comparison gen/statements.c @ 81:3587401b6eeb trunk

[svn r85] Fixed: if a return statement appeared in the try block of a nested try-finally, only the inner-most finally block would be executed. Changed: Renamed all the LLVM_Dto... helper function to just Dto...
author lindquist
date Thu, 01 Nov 2007 17:27:18 +0100
parents 7299ff502248
children d8dd47ef3973
comparison
equal deleted inserted replaced
80:7299ff502248 81:3587401b6eeb
5 #include <sstream> 5 #include <sstream>
6 #include <fstream> 6 #include <fstream>
7 #include <iostream> 7 #include <iostream>
8 8
9 #include "gen/llvm.h" 9 #include "gen/llvm.h"
10 #include "llvm/Transforms/Utils/Cloning.h"
10 11
11 #include "total.h" 12 #include "total.h"
12 #include "init.h" 13 #include "init.h"
13 #include "symbol.h" 14 #include "symbol.h"
14 #include "mtype.h" 15 #include "mtype.h"
38 else { 39 else {
39 Logger::println("*** ATTENTION: null statement found in CompoundStatement"); 40 Logger::println("*** ATTENTION: null statement found in CompoundStatement");
40 //assert(0); 41 //assert(0);
41 } 42 }
42 } 43 }
43
44 } 44 }
45 45
46 ////////////////////////////////////////////////////////////////////////////// 46 //////////////////////////////////////////////////////////////////////////////
47 47
48 void ReturnStatement::toIR(IRState* p) 48 void ReturnStatement::toIR(IRState* p)
53 53
54 if (exp) 54 if (exp)
55 { 55 {
56 Logger::println("return type is: %s", exp->type->toChars()); 56 Logger::println("return type is: %s", exp->type->toChars());
57 57
58 Type* exptype = LLVM_DtoDType(exp->type); 58 Type* exptype = DtoDType(exp->type);
59 TY expty = exptype->ty; 59 TY expty = exptype->ty;
60 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { 60 if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
61 assert(LLVM_DtoIsPassedByRef(exptype)); 61 assert(DtoIsPassedByRef(exptype));
62 62
63 TypeFunction* f = p->topfunctype(); 63 TypeFunction* f = p->topfunctype();
64 assert(f->llvmRetInPtr && f->llvmRetArg); 64 assert(f->llvmRetInPtr && f->llvmRetArg);
65 65
66 p->exps.push_back(IRExp(NULL,exp,f->llvmRetArg)); 66 p->exps.push_back(IRExp(NULL,exp,f->llvmRetArg));
67 elem* e = exp->toElem(p); 67 elem* e = exp->toElem(p);
68 p->exps.pop_back(); 68 p->exps.pop_back();
69 69
70 if (expty == Tstruct) { 70 if (expty == Tstruct) {
71 if (!e->inplace) 71 if (!e->inplace)
72 LLVM_DtoStructCopy(f->llvmRetArg,e->getValue()); 72 DtoStructCopy(f->llvmRetArg,e->getValue());
73 } 73 }
74 else if (expty == Tdelegate) { 74 else if (expty == Tdelegate) {
75 if (!e->inplace) 75 if (!e->inplace)
76 LLVM_DtoDelegateCopy(f->llvmRetArg,e->getValue()); 76 DtoDelegateCopy(f->llvmRetArg,e->getValue());
77 } 77 }
78 else if (expty == Tarray) { 78 else if (expty == Tarray) {
79 if (e->type == elem::SLICE) { 79 if (e->type == elem::SLICE) {
80 assert(e->mem); 80 assert(e->mem);
81 LLVM_DtoSetArray(f->llvmRetArg,e->arg,e->mem); 81 DtoSetArray(f->llvmRetArg,e->arg,e->mem);
82 } 82 }
83 else if (!e->inplace) { 83 else if (!e->inplace) {
84 if (e->type == elem::NUL) { 84 if (e->type == elem::NUL) {
85 LLVM_DtoNullArray(f->llvmRetArg); 85 DtoNullArray(f->llvmRetArg);
86 } 86 }
87 else { 87 else {
88 LLVM_DtoArrayAssign(f->llvmRetArg, e->getValue()); 88 DtoArrayAssign(f->llvmRetArg, e->getValue());
89 } 89 }
90 } 90 }
91 } 91 }
92 else 92 else
93 assert(0); 93 assert(0);
94 94
95 IRFunction::FinallyVec& fin = p->func().finallys; 95 IRFunction::FinallyVec& fin = p->func().finallys;
96 if (fin.empty()) 96 if (fin.empty())
97 new llvm::ReturnInst(p->scopebb()); 97 new llvm::ReturnInst(p->scopebb());
98 else { 98 else {
99 new llvm::BranchInst(fin.back().bb, p->scopebb()); 99 new llvm::BranchInst(fin.back().retbb, p->scopebb());
100 fin.back().ret = true;
101 } 100 }
102 delete e; 101 delete e;
103 } 102 }
104 else { 103 else {
105 elem* e = exp->toElem(p); 104 elem* e = exp->toElem(p);
110 IRFunction::FinallyVec& fin = p->func().finallys; 109 IRFunction::FinallyVec& fin = p->func().finallys;
111 if (fin.empty()) { 110 if (fin.empty()) {
112 new llvm::ReturnInst(v, p->scopebb()); 111 new llvm::ReturnInst(v, p->scopebb());
113 } 112 }
114 else { 113 else {
115 llvm::Value* rettmp = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint()); 114 if (!p->func().finallyretval)
115 p->func().finallyretval = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint());
116 llvm::Value* rettmp = p->func().finallyretval;
116 new llvm::StoreInst(v,rettmp,p->scopebb()); 117 new llvm::StoreInst(v,rettmp,p->scopebb());
117 new llvm::BranchInst(fin.back().bb, p->scopebb()); 118 new llvm::BranchInst(fin.back().retbb, p->scopebb());
118 fin.back().ret = true;
119 fin.back().retval = rettmp;
120 } 119 }
121 } 120 }
122 } 121 }
123 else 122 else
124 { 123 {
126 IRFunction::FinallyVec& fin = p->func().finallys; 125 IRFunction::FinallyVec& fin = p->func().finallys;
127 if (fin.empty()) { 126 if (fin.empty()) {
128 new llvm::ReturnInst(p->scopebb()); 127 new llvm::ReturnInst(p->scopebb());
129 } 128 }
130 else { 129 else {
131 new llvm::BranchInst(fin.back().bb, p->scopebb()); 130 new llvm::BranchInst(fin.back().retbb, p->scopebb());
132 fin.back().ret = true;
133 } 131 }
134 } 132 }
135 else { 133 else {
136 assert(0); // why should this ever happen? 134 assert(0); // why should this ever happen?
137 new llvm::UnreachableInst(p->scopebb()); 135 new llvm::UnreachableInst(p->scopebb());
171 169
172 llvm::BasicBlock* oldend = gIR->scopeend(); 170 llvm::BasicBlock* oldend = gIR->scopeend();
173 171
174 llvm::BasicBlock* ifbb = new llvm::BasicBlock("if", gIR->topfunc(), oldend); 172 llvm::BasicBlock* ifbb = new llvm::BasicBlock("if", gIR->topfunc(), oldend);
175 llvm::BasicBlock* endbb = new llvm::BasicBlock("endif", gIR->topfunc(), oldend); 173 llvm::BasicBlock* endbb = new llvm::BasicBlock("endif", gIR->topfunc(), oldend);
176 llvm::BasicBlock* elsebb = 0; 174 llvm::BasicBlock* elsebb = elsebody ? new llvm::BasicBlock("else", gIR->topfunc(), endbb) : endbb;
177 if (elsebody) {
178 elsebb = new llvm::BasicBlock("else", gIR->topfunc(), endbb);
179 }
180 else {
181 elsebb = endbb;
182 }
183 175
184 if (cond_val->getType() != llvm::Type::Int1Ty) { 176 if (cond_val->getType() != llvm::Type::Int1Ty) {
185 Logger::cout() << "if conditional: " << *cond_val << '\n'; 177 Logger::cout() << "if conditional: " << *cond_val << '\n';
186 cond_val = LLVM_DtoBoolean(cond_val); 178 cond_val = DtoBoolean(cond_val);
187 } 179 }
188 llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebegin()); 180 llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebegin());
189 181
190 // replace current scope 182 // replace current scope
191 gIR->scope() = IRScope(ifbb,elsebb); 183 gIR->scope() = IRScope(ifbb,elsebb);
192
193 bool endifUsed = false;
194 184
195 // do scoped statements 185 // do scoped statements
196 ifbody->toIR(p); 186 ifbody->toIR(p);
197 if (!gIR->scopereturned()) { 187 if (!gIR->scopereturned()) {
198 new llvm::BranchInst(endbb,gIR->scopebegin()); 188 new llvm::BranchInst(endbb,gIR->scopebegin());
199 endifUsed = true;
200 } 189 }
201 190
202 if (elsebody) { 191 if (elsebody) {
203 //assert(0); 192 //assert(0);
204 gIR->scope() = IRScope(elsebb,endbb); 193 gIR->scope() = IRScope(elsebb,endbb);
205 elsebody->toIR(p); 194 elsebody->toIR(p);
206 if (!gIR->scopereturned()) { 195 if (!gIR->scopereturned()) {
207 new llvm::BranchInst(endbb,gIR->scopebegin()); 196 new llvm::BranchInst(endbb,gIR->scopebegin());
208 endifUsed = true;
209 } 197 }
210 } 198 }
211 199
212 // rewrite the scope 200 // rewrite the scope
213 gIR->scope() = IRScope(endbb,oldend); 201 gIR->scope() = IRScope(endbb,oldend);
221 LOG_SCOPE; 209 LOG_SCOPE;
222 210
223 llvm::BasicBlock* oldend = p->scopeend(); 211 llvm::BasicBlock* oldend = p->scopeend();
224 212
225 llvm::BasicBlock* beginbb = 0; 213 llvm::BasicBlock* beginbb = 0;
226 214
227 // remove useless branches by clearing and reusing the current basicblock 215 // remove useless branches by clearing and reusing the current basicblock
228 llvm::BasicBlock* bb = p->scopebegin(); 216 llvm::BasicBlock* bb = p->scopebegin();
229 if (bb->empty()) { 217 if (bb->empty()) {
230 beginbb = bb; 218 beginbb = bb;
231 } 219 }
265 // replace current scope 253 // replace current scope
266 gIR->scope() = IRScope(whilebb,endbb); 254 gIR->scope() = IRScope(whilebb,endbb);
267 255
268 // create the condition 256 // create the condition
269 elem* cond_e = condition->toElem(p); 257 elem* cond_e = condition->toElem(p);
270 llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue()); 258 llvm::Value* cond_val = DtoBoolean(cond_e->getValue());
271 delete cond_e; 259 delete cond_e;
272 260
273 // conditional branch 261 // conditional branch
274 llvm::Value* ifbreak = new llvm::BranchInst(whilebodybb, endbb, cond_val, p->scopebb()); 262 llvm::Value* ifbreak = new llvm::BranchInst(whilebodybb, endbb, cond_val, p->scopebb());
275 263
308 // do do-while body code 296 // do do-while body code
309 body->toIR(p); 297 body->toIR(p);
310 298
311 // create the condition 299 // create the condition
312 elem* cond_e = condition->toElem(p); 300 elem* cond_e = condition->toElem(p);
313 llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue()); 301 llvm::Value* cond_val = DtoBoolean(cond_e->getValue());
314 delete cond_e; 302 delete cond_e;
315 303
316 // conditional branch 304 // conditional branch
317 llvm::Value* ifbreak = new llvm::BranchInst(dowhilebb, endbb, cond_val, gIR->scopebegin()); 305 llvm::Value* ifbreak = new llvm::BranchInst(dowhilebb, endbb, cond_val, gIR->scopebegin());
318 306
347 // replace current scope 335 // replace current scope
348 gIR->scope() = IRScope(forbb,forbodybb); 336 gIR->scope() = IRScope(forbb,forbodybb);
349 337
350 // create the condition 338 // create the condition
351 elem* cond_e = condition->toElem(p); 339 elem* cond_e = condition->toElem(p);
352 llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue()); 340 llvm::Value* cond_val = DtoBoolean(cond_e->getValue());
353 delete cond_e; 341 delete cond_e;
354 342
355 // conditional branch 343 // conditional branch
356 llvm::Value* ifbreak = new llvm::BranchInst(forbodybb, endbb, cond_val, forbb); 344 llvm::Value* ifbreak = new llvm::BranchInst(forbodybb, endbb, cond_val, forbb);
357 345
426 //statement->toIR(p); // this seems to be redundant 414 //statement->toIR(p); // this seems to be redundant
427 } 415 }
428 416
429 ////////////////////////////////////////////////////////////////////////////// 417 //////////////////////////////////////////////////////////////////////////////
430 418
419 static void replaceFinallyBBs(std::vector<llvm::BasicBlock*>& a, std::vector<llvm::BasicBlock*>& b)
420 {
421 }
422
431 void TryFinallyStatement::toIR(IRState* p) 423 void TryFinallyStatement::toIR(IRState* p)
432 { 424 {
433 static int wsi = 0; 425 Logger::println("TryFinallyStatement::toIR(): %s", toChars());
434 Logger::println("TryFinallyStatement::toIR(%d): %s", wsi++, toChars()); 426 LOG_SCOPE;
435 LOG_SCOPE; 427
436 428 // create basic blocks
437 llvm::BasicBlock* oldend = p->scopeend(); 429 llvm::BasicBlock* oldend = p->scopeend();
438 430
439 llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend); 431 llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend);
440 llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend); 432 llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend);
433 llvm::BasicBlock* finallyretbb = new llvm::BasicBlock("finallyreturn", p->topfunc(), oldend);
441 llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend); 434 llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend);
442 435
443 // pass the previous BB into this 436 // pass the previous BB into this
437 assert(!gIR->scopereturned());
444 new llvm::BranchInst(trybb, p->scopebb()); 438 new llvm::BranchInst(trybb, p->scopebb());
445 439
440 // do the try block
446 p->scope() = IRScope(trybb,finallybb); 441 p->scope() = IRScope(trybb,finallybb);
442 gIR->func().finallys.push_back(IRFinally(finallybb,finallyretbb));
443 IRFinally& fin = p->func().finallys.back();
447 444
448 assert(body); 445 assert(body);
449 gIR->func().finallys.push_back(IRFinally(finallybb));
450 body->toIR(p); 446 body->toIR(p);
451 if (!gIR->scopereturned()) 447
448 // terminate try BB
449 if (!p->scopereturned())
452 new llvm::BranchInst(finallybb, p->scopebb()); 450 new llvm::BranchInst(finallybb, p->scopebb());
453 451
454 // rewrite the scope 452 // do finally block
455 p->scope() = IRScope(finallybb,endbb); 453 p->scope() = IRScope(finallybb,finallyretbb);
456
457 assert(finalbody); 454 assert(finalbody);
458 finalbody->toIR(p); 455 finalbody->toIR(p);
459 if (gIR->func().finallys.back().ret) { 456
460 llvm::Value* retval = p->func().finallys.back().retval; 457 // terminate finally
458 if (!gIR->scopereturned()) {
459 new llvm::BranchInst(endbb, p->scopebb());
460 }
461
462 // do finally block (return path)
463 p->scope() = IRScope(finallyretbb,endbb);
464 assert(finalbody);
465 finalbody->toIR(p); // hope this will work, otherwise it's time it gets fixed
466
467 // terminate finally (return path)
468 size_t nfin = p->func().finallys.size();
469 if (nfin > 1) {
470 IRFinally& ofin = p->func().finallys[nfin-2];
471 p->ir->CreateBr(ofin.retbb);
472 }
473 // no outer
474 else
475 {
476 llvm::Value* retval = p->func().finallyretval;
461 if (retval) { 477 if (retval) {
462 retval = new llvm::LoadInst(retval,"tmp",p->scopebb()); 478 retval = p->ir->CreateLoad(retval,"tmp");
463 new llvm::ReturnInst(retval, p->scopebb()); 479 p->ir->CreateRet(retval);
464 } 480 }
465 else { 481 else {
466 new llvm::ReturnInst(p->scopebb()); 482 FuncDeclaration* fd = p->func().decl;
467 } 483 if (fd->isMain()) {
468 } 484 assert(fd->type->next->ty == Tvoid);
469 else if (!gIR->scopereturned()) { 485 p->ir->CreateRet(DtoConstInt(0));
470 new llvm::BranchInst(endbb, p->scopebb()); 486 }
471 } 487 else {
472 488 p->ir->CreateRetVoid();
489 }
490 }
491 }
492
493 // rewrite the scope
473 p->func().finallys.pop_back(); 494 p->func().finallys.pop_back();
474
475 // rewrite the scope
476 p->scope() = IRScope(endbb,oldend); 495 p->scope() = IRScope(endbb,oldend);
477 } 496 }
478 497
479 ////////////////////////////////////////////////////////////////////////////// 498 //////////////////////////////////////////////////////////////////////////////
480 499
506 LOG_SCOPE; 525 LOG_SCOPE;
507 526
508 Logger::println("*** ATTENTION: throw is not yet implemented, replacing expression with assert(0);"); 527 Logger::println("*** ATTENTION: throw is not yet implemented, replacing expression with assert(0);");
509 528
510 llvm::Value* line = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false); 529 llvm::Value* line = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
511 LLVM_DtoAssert(NULL, line, NULL); 530 DtoAssert(NULL, line, NULL);
512 531
513 /* 532 /*
514 assert(exp); 533 assert(exp);
515 elem* e = exp->toElem(p); 534 elem* e = exp->toElem(p);
516 delete e; 535 delete e;
651 llvm::Value* val = arr->getValue(); 670 llvm::Value* val = arr->getValue();
652 Logger::cout() << "aggr2llvm = " << *val << '\n'; 671 Logger::cout() << "aggr2llvm = " << *val << '\n';
653 672
654 llvm::Value* numiters = 0; 673 llvm::Value* numiters = 0;
655 674
656 const llvm::Type* keytype = key ? LLVM_DtoType(key->type) : LLVM_DtoSize_t(); 675 const llvm::Type* keytype = key ? DtoType(key->type) : DtoSize_t();
657 llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint()); 676 llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint());
658 if (key) key->llvmValue = keyvar; 677 if (key) key->llvmValue = keyvar;
659 678
660 const llvm::Type* valtype = LLVM_DtoType(value->type); 679 const llvm::Type* valtype = DtoType(value->type);
661 llvm::Value* valvar = !value->isRef() ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL; 680 llvm::Value* valvar = !value->isRef() ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL;
662 681
663 Type* aggrtype = LLVM_DtoDType(aggr->type); 682 Type* aggrtype = DtoDType(aggr->type);
664 if (aggrtype->ty == Tsarray) 683 if (aggrtype->ty == Tsarray)
665 { 684 {
666 assert(llvm::isa<llvm::PointerType>(val->getType())); 685 assert(llvm::isa<llvm::PointerType>(val->getType()));
667 assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0))); 686 assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0)));
668 size_t n = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements(); 687 size_t n = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements();
674 if (arr->type == elem::SLICE) { 693 if (arr->type == elem::SLICE) {
675 numiters = arr->arg; 694 numiters = arr->arg;
676 val = arr->mem; 695 val = arr->mem;
677 } 696 }
678 else { 697 else {
679 numiters = p->ir->CreateLoad(LLVM_DtoGEPi(val,0,0,"tmp",p->scopebb())); 698 numiters = p->ir->CreateLoad(DtoGEPi(val,0,0,"tmp",p->scopebb()));
680 val = p->ir->CreateLoad(LLVM_DtoGEPi(val,0,1,"tmp",p->scopebb())); 699 val = p->ir->CreateLoad(DtoGEPi(val,0,1,"tmp",p->scopebb()));
681 } 700 }
682 } 701 }
683 else 702 else
684 { 703 {
685 assert(0 && "aggregate type is not Tarray or Tsarray"); 704 assert(0 && "aggregate type is not Tarray or Tsarray");
723 742
724 // get value for this iteration 743 // get value for this iteration
725 llvm::Constant* zero = llvm::ConstantInt::get(keytype,0,false); 744 llvm::Constant* zero = llvm::ConstantInt::get(keytype,0,false);
726 llvm::Value* loadedKey = p->ir->CreateLoad(keyvar,"tmp"); 745 llvm::Value* loadedKey = p->ir->CreateLoad(keyvar,"tmp");
727 if (aggrtype->ty == Tsarray) 746 if (aggrtype->ty == Tsarray)
728 value->llvmValue = LLVM_DtoGEP(val,zero,loadedKey,"tmp"); 747 value->llvmValue = DtoGEP(val,zero,loadedKey,"tmp");
729 else if (aggrtype->ty == Tarray) 748 else if (aggrtype->ty == Tarray)
730 value->llvmValue = new llvm::GetElementPtrInst(val,loadedKey,"tmp",p->scopebb()); 749 value->llvmValue = new llvm::GetElementPtrInst(val,loadedKey,"tmp",p->scopebb());
731 750
732 if (!value->isRef()) { 751 if (!value->isRef()) {
733 elem* e = new elem; 752 elem* e = new elem;
734 e->mem = value->llvmValue; 753 e->mem = value->llvmValue;
735 e->type = elem::VAR; 754 e->type = elem::VAR;
736 LLVM_DtoAssign(LLVM_DtoDType(value->type), valvar, e->getValue()); 755 DtoAssign(DtoDType(value->type), valvar, e->getValue());
737 delete e; 756 delete e;
738 value->llvmValue = valvar; 757 value->llvmValue = valvar;
739 } 758 }
740 759
741 // body 760 // body