changeset 262:88252a1af660 trunk

[svn r280] Fixed a bunch of issues with switch statements. Ended up a bit far reaching...
author lindquist
date Sat, 14 Jun 2008 05:13:49 +0200
parents 5723b7385c25
children 2be09ee06bc7
files dmd/mars.c dmd/statement.c dmd/statement.h gen/functions.cpp gen/irstate.cpp gen/statements.cpp gen/toir.cpp readme.txt tango/lib/gc/basic/gc.d tangotests/nested2.d
diffstat 10 files changed, 126 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- 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<path>       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<arch>       emit code specific to <arch>\n\
                  x86 x86-64 ppc32 ppc64\n\
   -noasm         do not allow use of inline asm\n\
--- 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()
--- 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
--- 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
--- 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;
 }
--- 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<llvm::BasicBlock*, std::vector<llvm::ConstantInt*> > CasePair;
-    std::vector<CasePair> vcases;
-    std::vector<Statement*> vbodies;
-    Array caseArray;
-    for (int i=0; i<cases->dim; ++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<llvm::ConstantInt*> 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; i<cases->dim; ++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<LLConstant*> inits;
         for (size_t i=0; i<caseArray.dim; ++i)
         {
+            CaseStatement* cs = (CaseStatement*)cases->data[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; i<n; ++i)
-    {
-        size_t nc = vcases[i].second.size();
-        for (size_t j=0; j<nc; ++j)
-        {
-            si->addCase(vcases[i].second[j], vcases[i].first);
-        }
-    }
+    // do switch body
+    assert(body);
 
-    // insert case statements
-    for (size_t i=0; i<n; ++i)
-    {
-        llvm::BasicBlock* nextbb = (i == n-1) ? (defbb ? defbb : endbb) : vcases[i+1].first;
-        p->scope() = 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; i<cases->dim; ++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);
--- 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
--- 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
--- 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();
 }
--- 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
+}