diff gen/statements.cpp @ 108:288fe1029e1f trunk

[svn r112] Fixed 'case 1,2,3:' style case statements. Fixed a bunch of bugs with return/break/continue in loops. Fixed support for the DMDFE hidden implicit return value variable. This can be needed for some foreach statements where the loop body is converted to a nested delegate, but also possibly returns from the function. Added std.math to phobos. Added AA runtime support code, done ground work for implementing AAs. Several other bugfixes.
author lindquist
date Tue, 20 Nov 2007 05:29:20 +0100
parents 5071469303d4
children 5ab8e92611f9
line wrap: on
line diff
--- a/gen/statements.cpp	Tue Nov 20 00:02:35 2007 +0100
+++ b/gen/statements.cpp	Tue Nov 20 05:29:20 2007 +0100
@@ -163,7 +163,7 @@
         Logger::cout() << "if conditional: " << *cond_val << '\n';
         cond_val = DtoBoolean(cond_val);
     }
-    llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebegin());
+    llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebb());
 
     // replace current scope
     gIR->scope() = IRScope(ifbb,elsebb);
@@ -171,7 +171,7 @@
     // do scoped statements
     ifbody->toIR(p);
     if (!gIR->scopereturned()) {
-        new llvm::BranchInst(endbb,gIR->scopebegin());
+        new llvm::BranchInst(endbb,gIR->scopebb());
     }
 
     if (elsebody) {
@@ -179,7 +179,7 @@
         gIR->scope() = IRScope(elsebb,endbb);
         elsebody->toIR(p);
         if (!gIR->scopereturned()) {
-            new llvm::BranchInst(endbb,gIR->scopebegin());
+            new llvm::BranchInst(endbb,gIR->scopebb());
         }
     }
 
@@ -199,14 +199,14 @@
     llvm::BasicBlock* beginbb = 0;
 
     // remove useless branches by clearing and reusing the current basicblock
-    llvm::BasicBlock* bb = p->scopebegin();
+    llvm::BasicBlock* bb = p->scopebb();
     if (bb->empty()) {
         beginbb = bb;
     }
     else {
         assert(!p->scopereturned());
         beginbb = new llvm::BasicBlock("scope", p->topfunc(), oldend);
-        new llvm::BranchInst(beginbb, p->scopebegin());
+        new llvm::BranchInst(beginbb, p->scopebb());
     }
     llvm::BasicBlock* endbb = new llvm::BasicBlock("endscope", p->topfunc(), oldend);
 
@@ -234,7 +234,7 @@
 
     // move into the while block
     p->ir->CreateBr(whilebb);
-    //new llvm::BranchInst(whilebb, gIR->scopebegin());
+    //new llvm::BranchInst(whilebb, gIR->scopebb());
 
     // replace current scope
     gIR->scope() = IRScope(whilebb,endbb);
@@ -256,7 +256,8 @@
     p->loopbbs.pop_back();
 
     // loop
-    new llvm::BranchInst(whilebb, gIR->scopebegin());
+    if (!gIR->scopereturned())
+        new llvm::BranchInst(whilebb, gIR->scopebb());
 
     // rewrite the scope
     gIR->scope() = IRScope(endbb,oldend);
@@ -276,13 +277,16 @@
     llvm::BasicBlock* endbb = new llvm::BasicBlock("enddowhile", gIR->topfunc(), oldend);
 
     // move into the while block
-    new llvm::BranchInst(dowhilebb, gIR->scopebegin());
+    assert(!gIR->scopereturned());
+    new llvm::BranchInst(dowhilebb, gIR->scopebb());
 
     // replace current scope
     gIR->scope() = IRScope(dowhilebb,endbb);
 
     // do-while body code
+    p->loopbbs.push_back(IRScope(dowhilebb,endbb));
     body->toIR(p);
+    p->loopbbs.pop_back();
 
     // create the condition
     DValue* cond_e = condition->toElem(p);
@@ -290,7 +294,7 @@
     delete cond_e;
 
     // conditional branch
-    llvm::Value* ifbreak = new llvm::BranchInst(dowhilebb, endbb, cond_val, gIR->scopebegin());
+    llvm::Value* ifbreak = new llvm::BranchInst(dowhilebb, endbb, cond_val, gIR->scopebb());
 
     // rewrite the scope
     gIR->scope() = IRScope(endbb,oldend);
@@ -316,7 +320,7 @@
     init->toIR(p);
 
     // move into the for condition block, ie. start the loop
-    new llvm::BranchInst(forbb, gIR->scopebegin());
+    new llvm::BranchInst(forbb, gIR->scopebb());
 
     p->loopbbs.push_back(IRScope(forincbb,endbb));
 
@@ -338,7 +342,8 @@
     body->toIR(p);
 
     // move into the for increment block
-    new llvm::BranchInst(forincbb, gIR->scopebegin());
+    if (!gIR->scopereturned())
+        new llvm::BranchInst(forincbb, gIR->scopebb());
     gIR->scope() = IRScope(forincbb, endbb);
 
     // increment
@@ -348,7 +353,8 @@
     }
 
     // loop
-    new llvm::BranchInst(forbb, gIR->scopebegin());
+    if (!gIR->scopereturned())
+        new llvm::BranchInst(forbb, gIR->scopebb());
 
     p->loopbbs.pop_back();
 
@@ -368,7 +374,7 @@
         assert(0);
     }
     else {
-        new llvm::BranchInst(gIR->loopbbs.back().end, gIR->scopebegin());
+        new llvm::BranchInst(gIR->loopbbs.back().end, gIR->scopebb());
     }
 }
 
@@ -384,7 +390,7 @@
         assert(0);
     }
     else {
-        new llvm::BranchInst(gIR->loopbbs.back().begin, gIR->scopebegin());
+        new llvm::BranchInst(gIR->loopbbs.back().begin, gIR->scopebb());
     }
 }
 
@@ -527,25 +533,33 @@
     llvm::BasicBlock* oldend = gIR->scopeend();
 
     // collect the needed cases
-    typedef std::pair<llvm::BasicBlock*, llvm::ConstantInt*> CasePair;
+    typedef std::pair<llvm::BasicBlock*, std::vector<llvm::ConstantInt*> > CasePair;
     std::vector<CasePair> vcases;
+    std::vector<Statement*> vbodies;
     for (int i=0; i<cases->dim; ++i)
     {
         CaseStatement* cs = (CaseStatement*)cases->data[i];
 
-        // get the case value
-        DValue* e = cs->exp->toElem(p);
-        DConstValue* ce = e->isConst();
-        assert(ce);
-        llvm::ConstantInt* ec = isaConstantInt(ce->c);
-        assert(ec);
-        delete e;
-
         // create the case bb with a nice label
         std::string lblname("case"+std::string(cs->exp->toChars()));
         llvm::BasicBlock* bb = new llvm::BasicBlock(lblname, p->topfunc(), oldend);
 
-        vcases.push_back(CasePair(bb,ec));
+        std::vector<llvm::ConstantInt*> tmp;
+        CaseStatement* last;
+        do {
+            // get the case value
+            DValue* e = cs->exp->toElem(p);
+            DConstValue* ce = e->isConst();
+            assert(ce);
+            llvm::ConstantInt* ec = isaConstantInt(ce->c);
+            assert(ec);
+            tmp.push_back(ec);
+            last = cs;
+        }
+        while (cs = cs->statement->isCaseStatement());
+
+        vcases.push_back(CasePair(bb, tmp));
+        vbodies.push_back(last->statement);
     }
 
     // default
@@ -566,7 +580,11 @@
     size_t n = vcases.size();
     for (size_t i=0; i<n; ++i)
     {
-        si->addCase(vcases[i].second, vcases[i].first);
+        size_t nc = vcases[i].second.size();
+        for (size_t j=0; j<nc; ++j)
+        {
+            si->addCase(vcases[i].second[j], vcases[i].first);
+        }
     }
 
     // insert case statements
@@ -576,7 +594,7 @@
         p->scope() = IRScope(vcases[i].first,nextbb);
 
         p->loopbbs.push_back(IRScope(p->scopebb(),endbb));
-        static_cast<CaseStatement*>(cases->data[i])->statement->toIR(p);
+        vbodies[i]->toIR(p);
         p->loopbbs.pop_back();
 
         llvm::BasicBlock* curbb = p->scopebb();
@@ -606,6 +624,15 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////
+void CaseStatement::toIR(IRState* p)
+{
+    Logger::println("CaseStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    assert(0);
+}
+
+//////////////////////////////////////////////////////////////////////////////
 
 void UnrolledLoopStatement::toIR(IRState* p)
 {
@@ -735,7 +762,7 @@
     }
     new llvm::BranchInst(bodybb, endbb, done, p->scopebb());
 
-    // body
+    // init body
     p->scope() = IRScope(bodybb,nextbb);
 
     // get value for this iteration
@@ -750,12 +777,10 @@
         DValue* dst = new DVarValue(value->type, valvar, true);
         DValue* src = new DVarValue(value->type, value->llvmValue, true);
         DtoAssign(dst, src);
-        delete dst;
-        delete src;
         value->llvmValue = valvar;
     }
 
-    // body
+    // emit body
     p->loopbbs.push_back(IRScope(nextbb,endbb));
     body->toIR(p);
     p->loopbbs.pop_back();
@@ -860,7 +885,7 @@
 //STUBST(ReturnStatement);
 //STUBST(ContinueStatement);
 STUBST(DefaultStatement);
-STUBST(CaseStatement);
+//STUBST(CaseStatement);
 //STUBST(SwitchStatement);
 STUBST(SwitchErrorStatement);
 STUBST(Statement);