# HG changeset patch # User lindquist # Date 1213413229 -7200 # Node ID 88252a1af660d7959b22a50cbfa2d762f555e864 # Parent 5723b7385c25c7c11a41df4c54b3c02e4f34aaa9 [svn r280] Fixed a bunch of issues with switch statements. Ended up a bit far reaching... diff -r 5723b7385c25 -r 88252a1af660 dmd/mars.c --- a/dmd/mars.c Fri Jun 13 08:21:11 2008 +0200 +++ b/dmd/mars.c Sat Jun 14 05:13:49 2008 +0200 @@ -192,7 +192,7 @@ -J where to look for string imports\n\ -ignore ignore unsupported pragmas\n\ -inline do function inlining\n\ - -Llinkerflag pass linkerflag to link\n\ + -Llinkerflag pass linkerflag to llvm-ld\n\ -m emit code specific to \n\ x86 x86-64 ppc32 ppc64\n\ -noasm do not allow use of inline asm\n\ diff -r 5723b7385c25 -r 88252a1af660 dmd/statement.c --- a/dmd/statement.c Fri Jun 13 08:21:11 2008 +0200 +++ b/dmd/statement.c Sat Jun 14 05:13:49 2008 +0200 @@ -2124,6 +2124,7 @@ this->statement = s; cblock = NULL; bodyBB = NULL; + llvmIdx = NULL; } Statement *CaseStatement::syntaxCopy() diff -r 5723b7385c25 -r 88252a1af660 dmd/statement.h --- a/dmd/statement.h Fri Jun 13 08:21:11 2008 +0200 +++ b/dmd/statement.h Sat Jun 14 05:13:49 2008 +0200 @@ -57,6 +57,7 @@ { class Value; class BasicBlock; + class ConstantInt; } // Back end @@ -453,6 +454,7 @@ // LLVMDC llvm::BasicBlock* bodyBB; + llvm::ConstantInt* llvmIdx; }; struct DefaultStatement : Statement diff -r 5723b7385c25 -r 88252a1af660 gen/functions.cpp --- a/gen/functions.cpp Fri Jun 13 08:21:11 2008 +0200 +++ b/gen/functions.cpp Sat Jun 14 05:13:49 2008 +0200 @@ -1,4 +1,5 @@ #include "gen/llvm.h" +#include "llvm/Support/CFG.h" #include "mtype.h" #include "aggregate.h" @@ -735,17 +736,21 @@ // would be nice to figure out how to assert that this is correct llvm::BasicBlock* lastbb = &func->getBasicBlockList().back(); if (lastbb->empty()) { - if (lastbb->getNumUses() == 0) - lastbb->eraseFromParent(); - else { - new llvm::UnreachableInst(lastbb); - /*if (func->getReturnType() == LLType::VoidTy) { - llvm::ReturnInst::Create(lastbb); - } - else { - llvm::ReturnInst::Create(llvm::UndefValue::get(func->getReturnType()), lastbb); - }*/ - } + new llvm::UnreachableInst(lastbb); +// if (llvm::pred_begin(lastbb) != llvm::pred_end(lastbb)) +// { +// Logger::println("Erasing lastbb"); +// lastbb->eraseFromParent(); +// } +// else { +// new llvm::UnreachableInst(lastbb); +// // if (func->getReturnType() == LLType::VoidTy) { +// // llvm::ReturnInst::Create(lastbb); +// // } +// // else { +// // llvm::ReturnInst::Create(llvm::UndefValue::get(func->getReturnType()), lastbb); +// // } +// } } // if the last block is not terminated we return a null value or void diff -r 5723b7385c25 -r 88252a1af660 gen/irstate.cpp --- a/gen/irstate.cpp Fri Jun 13 08:21:11 2008 +0200 +++ b/gen/irstate.cpp Sat Jun 14 05:13:49 2008 +0200 @@ -39,7 +39,7 @@ { begin = b; end = e; - builder.SetInsertPoint(b); + //builder.SetInsertPoint(b); this->s = s; this->enclosingtryfinally = enclosingtryfinally; } diff -r 5723b7385c25 -r 88252a1af660 gen/statements.cpp --- a/gen/statements.cpp Fri Jun 13 08:21:11 2008 +0200 +++ b/gen/statements.cpp Sat Jun 14 05:13:49 2008 +0200 @@ -223,7 +223,7 @@ Logger::println("ScopeStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - llvm::BasicBlock* oldend = p->scopeend(); + /*llvm::BasicBlock* oldend = p->scopeend(); llvm::BasicBlock* beginbb = 0; @@ -233,19 +233,23 @@ beginbb = bb; } else { - assert(!p->scopereturned()); beginbb = llvm::BasicBlock::Create("scope", p->topfunc(), oldend); - llvm::BranchInst::Create(beginbb, p->scopebb()); + if (!p->scopereturned()) + llvm::BranchInst::Create(beginbb, bb); } + llvm::BasicBlock* endbb = llvm::BasicBlock::Create("endscope", p->topfunc(), oldend); - - gIR->scope() = IRScope(beginbb, endbb); + if (beginbb != bb) + p->scope() = IRScope(beginbb, endbb); + else + p->scope().end = endbb;*/ if (statement) statement->toIR(p); - p->scope() = IRScope(p->scopebb(),oldend); - endbb->eraseFromParent(); + /*p->scope().end = oldend; + Logger::println("Erasing scope endbb"); + endbb->eraseFromParent();*/ } ////////////////////////////////////////////////////////////////////////////// @@ -398,6 +402,11 @@ Logger::println("BreakStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; + // don't emit two terminators in a row + // happens just before DMD generated default statements if the last case terminates + if (p->scopereturned()) + return; + if (ident != 0) { Logger::println("ident = %s", ident->toChars()); @@ -411,17 +420,17 @@ // find the right break block and jump there IRState::LoopScopeVec::reverse_iterator it; - for(it = gIR->loopbbs.rbegin(); it != gIR->loopbbs.rend(); ++it) { + for(it = p->loopbbs.rbegin(); it != p->loopbbs.rend(); ++it) { if(it->s == targetLoopStatement) { - llvm::BranchInst::Create(it->end, gIR->scopebb()); + llvm::BranchInst::Create(it->end, p->scopebb()); return; } } assert(0); } else { - emit_finallyblocks(p, enclosingtryfinally, gIR->loopbbs.back().enclosingtryfinally); - llvm::BranchInst::Create(gIR->loopbbs.back().end, gIR->scopebb()); + emit_finallyblocks(p, enclosingtryfinally, p->loopbbs.back().enclosingtryfinally); + llvm::BranchInst::Create(p->loopbbs.back().end, p->scopebb()); } } @@ -642,57 +651,29 @@ llvm::BasicBlock* oldend = gIR->scopeend(); - // collect the needed cases - typedef std::pair > CasePair; - std::vector vcases; - std::vector vbodies; - Array caseArray; - for (int i=0; idim; ++i) - { - CaseStatement* cs = (CaseStatement*)cases->data[i]; - - std::string lblname("case"); - llvm::BasicBlock* bb = llvm::BasicBlock::Create(lblname, p->topfunc(), oldend); - cs->bodyBB = bb; - - std::vector tmp; - CaseStatement* last; - bool first = true; - do { - // integral case - if (cs->exp->type->isintegral()) { - LLConstant* c = cs->exp->toConstElem(p); - tmp.push_back(isaConstantInt(c)); - } - // string case - else { - assert(cs->exp->op == TOKstring); - // for string switches this is unfortunately necessary or there will be duplicates in the list - if (first) { - caseArray.push(new Case((StringExp*)cs->exp, i)); - first = false; - } - } - last = cs; - } - while (cs = cs->statement->isCaseStatement()); - - vcases.push_back(CasePair(bb, tmp)); - vbodies.push_back(last->statement); - } - // string switch? llvm::GlobalVariable* switchTable = 0; + Array caseArray; if (!condition->type->isintegral()) { + Logger::println("is string switch"); + // build array of the stringexpS + for (int i=0; idim; ++i) + { + CaseStatement* cs = (CaseStatement*)cases->data[i]; + + assert(cs->exp->op == TOKstring); + caseArray.push(new Case((StringExp*)cs->exp, i)); + } // first sort it caseArray.sort(); // iterate and add indices to cases std::vector inits; for (size_t i=0; idata[i]; + cs->llvmIdx = DtoConstUint(i); Case* c = (Case*)caseArray.data[i]; - vcases[c->index].second.push_back(DtoConstUint(i)); inits.push_back(c->str->toConstElem(p)); } // build static array for ptr or final array @@ -717,9 +698,13 @@ switchTable = new llvm::GlobalVariable(sTy, true, llvm::GlobalValue::InternalLinkage, sInit, "string_switch_table", gIR->module); } + // body block + llvm::BasicBlock* bodybb = llvm::BasicBlock::Create("switchbody", p->topfunc(), oldend); + // default llvm::BasicBlock* defbb = 0; - if (!hasNoDefault) { + if (sdefault) { + Logger::println("has default"); defbb = llvm::BasicBlock::Create("default", p->topfunc(), oldend); sdefault->bodyBB = defbb; } @@ -740,47 +725,22 @@ } llvm::SwitchInst* si = llvm::SwitchInst::Create(condVal, defbb ? defbb : endbb, cases->dim, p->scopebb()); - // add the cases - size_t n = vcases.size(); - for (size_t i=0; iaddCase(vcases[i].second[j], vcases[i].first); - } - } + // do switch body + assert(body); - // insert case statements - for (size_t i=0; iscope() = IRScope(vcases[i].first,nextbb); - p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,p->scopebb(),endbb)); - vbodies[i]->toIR(p); - p->loopbbs.pop_back(); + p->scope() = IRScope(bodybb, endbb); + p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,p->scopebb(),endbb)); + body->toIR(p); + p->loopbbs.pop_back(); - llvm::BasicBlock* curbb = p->scopebb(); - if (curbb->empty() || !curbb->back().isTerminator()) - { - llvm::BranchInst::Create(nextbb, curbb); - } - } + if (!p->scopereturned()) + llvm::BranchInst::Create(endbb, p->scopebb()); - // default statement - if (defbb) + // add the cases + for (int i=0; idim; ++i) { - p->scope() = IRScope(defbb,endbb); - p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,p->scopebb(),endbb)); - Logger::println("doing default statement"); - sdefault->statement->toIR(p); - p->loopbbs.pop_back(); - - llvm::BasicBlock* curbb = p->scopebb(); - if (curbb->empty() || !curbb->back().isTerminator()) - { - llvm::BranchInst::Create(endbb, curbb); - } + CaseStatement* cs = (CaseStatement*)cases->data[i]; + si->addCase(cs->llvmIdx, cs->bodyBB); } gIR->scope() = IRScope(endbb,oldend); @@ -792,7 +752,50 @@ Logger::println("CaseStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - assert(0); + if (!bodyBB) + { + bodyBB = llvm::BasicBlock::Create("case", p->topfunc(), p->scopeend()); + } + else + { + bodyBB->moveAfter(p->scopebb()); + } + + if (exp->type->isintegral()) { + assert(!llvmIdx); + LLConstant* c = exp->toConstElem(p); + llvmIdx = isaConstantInt(c); + } + else { + assert(llvmIdx); + } + + if (!p->scopereturned()) + llvm::BranchInst::Create(bodyBB, p->scopebb()); + + p->scope() = IRScope(bodyBB, p->scopeend()); + + assert(statement); + statement->toIR(p); +} + +////////////////////////////////////////////////////////////////////////////// +void DefaultStatement::toIR(IRState* p) +{ + Logger::println("DefaultStatement::toIR(): %s", loc.toChars()); + LOG_SCOPE; + + assert(bodyBB); + + bodyBB->moveAfter(p->scopebb()); + + if (!p->scopereturned()) + llvm::BranchInst::Create(bodyBB, p->scopebb()); + + p->scope() = IRScope(bodyBB, p->scopeend()); + + assert(statement); + statement->toIR(p); } ////////////////////////////////////////////////////////////////////////////// @@ -1083,7 +1086,10 @@ llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergotocase", p->topfunc(), oldend); assert(!p->scopereturned()); - assert(cs->bodyBB); + if (!cs->bodyBB) + { + cs->bodyBB = llvm::BasicBlock::Create("case", p->topfunc(), p->scopeend()); + } emit_finallyblocks(p, enclosingtryfinally, sw->enclosingtryfinally); @@ -1205,7 +1211,7 @@ //STUBST(SynchronizedStatement); //STUBST(ReturnStatement); //STUBST(ContinueStatement); -STUBST(DefaultStatement); +//STUBST(DefaultStatement); //STUBST(CaseStatement); //STUBST(SwitchStatement); STUBST(SwitchErrorStatement); diff -r 5723b7385c25 -r 88252a1af660 gen/toir.cpp --- a/gen/toir.cpp Fri Jun 13 08:21:11 2008 +0200 +++ b/gen/toir.cpp Sat Jun 14 05:13:49 2008 +0200 @@ -2193,7 +2193,7 @@ DValue* HaltExp::toElem(IRState* p) { - Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars()); + Logger::print("HaltExp::toElem: %s\n", toChars()); LOG_SCOPE; #if 0 diff -r 5723b7385c25 -r 88252a1af660 readme.txt --- a/readme.txt Fri Jun 13 08:21:11 2008 +0200 +++ b/readme.txt Sat Jun 14 05:13:49 2008 +0200 @@ -8,9 +8,9 @@ only Linux is tested so use the command: 'premake --target gnu' to generate a Makefile, then just type 'make'. -You need LLVM 2.2. Get it from the LLVM website. +You need the latest stable LLVM. See the LLVM website. -For more information visit the website: +For more information visit the LLVMDC website: http://www.dsource.org/projects/llvmdc [1] http://www.digitalmars.com/d diff -r 5723b7385c25 -r 88252a1af660 tango/lib/gc/basic/gc.d --- a/tango/lib/gc/basic/gc.d Fri Jun 13 08:21:11 2008 +0200 +++ b/tango/lib/gc/basic/gc.d Sat Jun 14 05:13:49 2008 +0200 @@ -69,7 +69,9 @@ // // NOTE: Due to popular demand, this has been re-enabled. It still has // the problems mentioned above though, so I guess we'll see. - _gc.fullCollectNoStack(); // not really a 'collect all' -- still scans + + // FIXME: LLVMDC crashes ... + //_gc.fullCollectNoStack(); // not really a 'collect all' -- still scans // static data area, roots, and ranges. _gc.Dtor(); } diff -r 5723b7385c25 -r 88252a1af660 tangotests/nested2.d --- a/tangotests/nested2.d Fri Jun 13 08:21:11 2008 +0200 +++ b/tangotests/nested2.d Sat Jun 14 05:13:49 2008 +0200 @@ -29,4 +29,4 @@ exec(&bar); return 0; -} \ No newline at end of file +}