Mercurial > projects > ldc
diff 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 |
line wrap: on
line diff
--- a/gen/statements.c Wed Oct 31 22:35:39 2007 +0100 +++ b/gen/statements.c Thu Nov 01 17:27:18 2007 +0100 @@ -7,6 +7,7 @@ #include <iostream> #include "gen/llvm.h" +#include "llvm/Transforms/Utils/Cloning.h" #include "total.h" #include "init.h" @@ -40,7 +41,6 @@ //assert(0); } } - } ////////////////////////////////////////////////////////////////////////////// @@ -55,10 +55,10 @@ { Logger::println("return type is: %s", exp->type->toChars()); - Type* exptype = LLVM_DtoDType(exp->type); + Type* exptype = DtoDType(exp->type); TY expty = exptype->ty; if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { - assert(LLVM_DtoIsPassedByRef(exptype)); + assert(DtoIsPassedByRef(exptype)); TypeFunction* f = p->topfunctype(); assert(f->llvmRetInPtr && f->llvmRetArg); @@ -69,23 +69,23 @@ if (expty == Tstruct) { if (!e->inplace) - LLVM_DtoStructCopy(f->llvmRetArg,e->getValue()); + DtoStructCopy(f->llvmRetArg,e->getValue()); } else if (expty == Tdelegate) { if (!e->inplace) - LLVM_DtoDelegateCopy(f->llvmRetArg,e->getValue()); + DtoDelegateCopy(f->llvmRetArg,e->getValue()); } else if (expty == Tarray) { if (e->type == elem::SLICE) { assert(e->mem); - LLVM_DtoSetArray(f->llvmRetArg,e->arg,e->mem); + DtoSetArray(f->llvmRetArg,e->arg,e->mem); } else if (!e->inplace) { if (e->type == elem::NUL) { - LLVM_DtoNullArray(f->llvmRetArg); + DtoNullArray(f->llvmRetArg); } else { - LLVM_DtoArrayAssign(f->llvmRetArg, e->getValue()); + DtoArrayAssign(f->llvmRetArg, e->getValue()); } } } @@ -96,8 +96,7 @@ if (fin.empty()) new llvm::ReturnInst(p->scopebb()); else { - new llvm::BranchInst(fin.back().bb, p->scopebb()); - fin.back().ret = true; + new llvm::BranchInst(fin.back().retbb, p->scopebb()); } delete e; } @@ -112,11 +111,11 @@ new llvm::ReturnInst(v, p->scopebb()); } else { - llvm::Value* rettmp = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint()); + if (!p->func().finallyretval) + p->func().finallyretval = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint()); + llvm::Value* rettmp = p->func().finallyretval; new llvm::StoreInst(v,rettmp,p->scopebb()); - new llvm::BranchInst(fin.back().bb, p->scopebb()); - fin.back().ret = true; - fin.back().retval = rettmp; + new llvm::BranchInst(fin.back().retbb, p->scopebb()); } } } @@ -128,8 +127,7 @@ new llvm::ReturnInst(p->scopebb()); } else { - new llvm::BranchInst(fin.back().bb, p->scopebb()); - fin.back().ret = true; + new llvm::BranchInst(fin.back().retbb, p->scopebb()); } } else { @@ -173,30 +171,21 @@ llvm::BasicBlock* ifbb = new llvm::BasicBlock("if", gIR->topfunc(), oldend); llvm::BasicBlock* endbb = new llvm::BasicBlock("endif", gIR->topfunc(), oldend); - llvm::BasicBlock* elsebb = 0; - if (elsebody) { - elsebb = new llvm::BasicBlock("else", gIR->topfunc(), endbb); - } - else { - elsebb = endbb; - } + llvm::BasicBlock* elsebb = elsebody ? new llvm::BasicBlock("else", gIR->topfunc(), endbb) : endbb; if (cond_val->getType() != llvm::Type::Int1Ty) { Logger::cout() << "if conditional: " << *cond_val << '\n'; - cond_val = LLVM_DtoBoolean(cond_val); + cond_val = DtoBoolean(cond_val); } llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebegin()); // replace current scope gIR->scope() = IRScope(ifbb,elsebb); - bool endifUsed = false; - // do scoped statements ifbody->toIR(p); if (!gIR->scopereturned()) { new llvm::BranchInst(endbb,gIR->scopebegin()); - endifUsed = true; } if (elsebody) { @@ -205,7 +194,6 @@ elsebody->toIR(p); if (!gIR->scopereturned()) { new llvm::BranchInst(endbb,gIR->scopebegin()); - endifUsed = true; } } @@ -223,7 +211,7 @@ llvm::BasicBlock* oldend = p->scopeend(); llvm::BasicBlock* beginbb = 0; - + // remove useless branches by clearing and reusing the current basicblock llvm::BasicBlock* bb = p->scopebegin(); if (bb->empty()) { @@ -267,7 +255,7 @@ // create the condition elem* cond_e = condition->toElem(p); - llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue()); + llvm::Value* cond_val = DtoBoolean(cond_e->getValue()); delete cond_e; // conditional branch @@ -310,7 +298,7 @@ // create the condition elem* cond_e = condition->toElem(p); - llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue()); + llvm::Value* cond_val = DtoBoolean(cond_e->getValue()); delete cond_e; // conditional branch @@ -349,7 +337,7 @@ // create the condition elem* cond_e = condition->toElem(p); - llvm::Value* cond_val = LLVM_DtoBoolean(cond_e->getValue()); + llvm::Value* cond_val = DtoBoolean(cond_e->getValue()); delete cond_e; // conditional branch @@ -428,51 +416,82 @@ ////////////////////////////////////////////////////////////////////////////// +static void replaceFinallyBBs(std::vector<llvm::BasicBlock*>& a, std::vector<llvm::BasicBlock*>& b) +{ +} + void TryFinallyStatement::toIR(IRState* p) { - static int wsi = 0; - Logger::println("TryFinallyStatement::toIR(%d): %s", wsi++, toChars()); + Logger::println("TryFinallyStatement::toIR(): %s", toChars()); LOG_SCOPE; + // create basic blocks llvm::BasicBlock* oldend = p->scopeend(); llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend); llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend); + llvm::BasicBlock* finallyretbb = new llvm::BasicBlock("finallyreturn", p->topfunc(), oldend); llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend); // pass the previous BB into this + assert(!gIR->scopereturned()); new llvm::BranchInst(trybb, p->scopebb()); + // do the try block p->scope() = IRScope(trybb,finallybb); + gIR->func().finallys.push_back(IRFinally(finallybb,finallyretbb)); + IRFinally& fin = p->func().finallys.back(); assert(body); - gIR->func().finallys.push_back(IRFinally(finallybb)); body->toIR(p); - if (!gIR->scopereturned()) + + // terminate try BB + if (!p->scopereturned()) new llvm::BranchInst(finallybb, p->scopebb()); - // rewrite the scope - p->scope() = IRScope(finallybb,endbb); - + // do finally block + p->scope() = IRScope(finallybb,finallyretbb); assert(finalbody); finalbody->toIR(p); - if (gIR->func().finallys.back().ret) { - llvm::Value* retval = p->func().finallys.back().retval; - if (retval) { - retval = new llvm::LoadInst(retval,"tmp",p->scopebb()); - new llvm::ReturnInst(retval, p->scopebb()); - } - else { - new llvm::ReturnInst(p->scopebb()); - } - } - else if (!gIR->scopereturned()) { + + // terminate finally + if (!gIR->scopereturned()) { new llvm::BranchInst(endbb, p->scopebb()); } - p->func().finallys.pop_back(); + // do finally block (return path) + p->scope() = IRScope(finallyretbb,endbb); + assert(finalbody); + finalbody->toIR(p); // hope this will work, otherwise it's time it gets fixed + + // terminate finally (return path) + size_t nfin = p->func().finallys.size(); + if (nfin > 1) { + IRFinally& ofin = p->func().finallys[nfin-2]; + p->ir->CreateBr(ofin.retbb); + } + // no outer + else + { + llvm::Value* retval = p->func().finallyretval; + if (retval) { + retval = p->ir->CreateLoad(retval,"tmp"); + p->ir->CreateRet(retval); + } + else { + FuncDeclaration* fd = p->func().decl; + if (fd->isMain()) { + assert(fd->type->next->ty == Tvoid); + p->ir->CreateRet(DtoConstInt(0)); + } + else { + p->ir->CreateRetVoid(); + } + } + } // rewrite the scope + p->func().finallys.pop_back(); p->scope() = IRScope(endbb,oldend); } @@ -508,7 +527,7 @@ Logger::println("*** ATTENTION: throw is not yet implemented, replacing expression with assert(0);"); llvm::Value* line = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false); - LLVM_DtoAssert(NULL, line, NULL); + DtoAssert(NULL, line, NULL); /* assert(exp); @@ -653,14 +672,14 @@ llvm::Value* numiters = 0; - const llvm::Type* keytype = key ? LLVM_DtoType(key->type) : LLVM_DtoSize_t(); + const llvm::Type* keytype = key ? DtoType(key->type) : DtoSize_t(); llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint()); if (key) key->llvmValue = keyvar; - const llvm::Type* valtype = LLVM_DtoType(value->type); + const llvm::Type* valtype = DtoType(value->type); llvm::Value* valvar = !value->isRef() ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL; - Type* aggrtype = LLVM_DtoDType(aggr->type); + Type* aggrtype = DtoDType(aggr->type); if (aggrtype->ty == Tsarray) { assert(llvm::isa<llvm::PointerType>(val->getType())); @@ -676,8 +695,8 @@ val = arr->mem; } else { - numiters = p->ir->CreateLoad(LLVM_DtoGEPi(val,0,0,"tmp",p->scopebb())); - val = p->ir->CreateLoad(LLVM_DtoGEPi(val,0,1,"tmp",p->scopebb())); + numiters = p->ir->CreateLoad(DtoGEPi(val,0,0,"tmp",p->scopebb())); + val = p->ir->CreateLoad(DtoGEPi(val,0,1,"tmp",p->scopebb())); } } else @@ -725,7 +744,7 @@ llvm::Constant* zero = llvm::ConstantInt::get(keytype,0,false); llvm::Value* loadedKey = p->ir->CreateLoad(keyvar,"tmp"); if (aggrtype->ty == Tsarray) - value->llvmValue = LLVM_DtoGEP(val,zero,loadedKey,"tmp"); + value->llvmValue = DtoGEP(val,zero,loadedKey,"tmp"); else if (aggrtype->ty == Tarray) value->llvmValue = new llvm::GetElementPtrInst(val,loadedKey,"tmp",p->scopebb()); @@ -733,7 +752,7 @@ elem* e = new elem; e->mem = value->llvmValue; e->type = elem::VAR; - LLVM_DtoAssign(LLVM_DtoDType(value->type), valvar, e->getValue()); + DtoAssign(DtoDType(value->type), valvar, e->getValue()); delete e; value->llvmValue = valvar; }