diff gen/statements.c @ 40:8b0e809563df trunk

[svn r44] Lots of bug fixes. New array literal support New array ~= operator support (for single element) New with statement support More...
author lindquist
date Fri, 19 Oct 2007 07:43:21 +0200
parents 77cdca8c210f
children ff359b65fa62
line wrap: on
line diff
--- a/gen/statements.c	Wed Oct 10 06:21:31 2007 +0200
+++ b/gen/statements.c	Fri Oct 19 07:43:21 2007 +0200
@@ -6,12 +6,7 @@
 #include <fstream>
 #include <iostream>
 
-#include "llvm/Type.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Constants.h"
-#include "llvm/Instructions.h"
-#include "llvm/IntrinsicInst.h"
-#include "llvm/CallingConv.h"
+#include "gen/llvm.h"
 
 #include "total.h"
 #include "init.h"
@@ -41,8 +36,8 @@
         if (s)
             s->toIR(p);
         else {
-            Logger::println("NULL statement found in CompoundStatement !! :S");
-            assert(0);
+            Logger::println("*** ATTENTION: null statement found in CompoundStatement");
+            //assert(0);
         }
     }
 
@@ -56,11 +51,14 @@
     Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars());
     LOG_SCOPE;
 
+    IRFunction::FinallyVec& fin = p->func().finallys;
+
     if (exp)
     {
-        TY expty = exp->type->ty;
+        Type* exptype = LLVM_DtoDType(exp->type);
+        TY expty = exptype->ty;
         if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
-            assert(expty == Tstruct || expty == Tdelegate || expty == Tarray);
+            assert(LLVM_DtoIsPassedByRef(exptype));
 
             TypeFunction* f = p->topfunctype();
             assert(f->llvmRetInPtr && f->llvmRetArg);
@@ -69,17 +67,14 @@
             elem* e = exp->toElem(p);
             p->lvals.pop_back();
 
-            // structliterals do this themselves
-            // also they dont produce any value
             if (expty == Tstruct) {
                 if (!e->inplace) {
-                    TypeStruct* ts = (TypeStruct*)exp->type;
+                    TypeStruct* ts = (TypeStruct*)exptype;
                     assert(e->mem);
                     LLVM_DtoStructCopy(ts,f->llvmRetArg,e->mem);
                 }
             }
             else if (expty == Tdelegate) {
-                // do nothing, handled by the DelegateExp
                 LLVM_DtoDelegateCopy(f->llvmRetArg,e->mem);
             }
             else if (expty == Tarray) {
@@ -91,26 +86,47 @@
             else
             assert(0);
 
-            new llvm::ReturnInst(p->scopebb());
+            if (fin.empty())
+                new llvm::ReturnInst(p->scopebb());
+            else {
+                new llvm::BranchInst(fin.back().bb);
+                fin.back().ret = true;
+            }
             delete e;
         }
         else {
             elem* e = exp->toElem(p);
             llvm::Value* v = e->getValue();
-            Logger::cout() << *v << '\n';
-            new llvm::ReturnInst(v, p->scopebb());
             delete e;
+            Logger::cout() << "return value is '" <<*v << "'\n";
+            if (fin.empty()) {
+                new llvm::ReturnInst(v, p->scopebb());
+            }
+            else {
+                llvm::Value* rettmp = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint());
+                new llvm::StoreInst(v,rettmp,p->scopebb());
+                new llvm::BranchInst(fin.back().bb, p->scopebb());
+                fin.back().ret = true;
+                fin.back().retval = rettmp;
+            }
         }
     }
     else
     {
-        if (p->topfunc()->getReturnType() == llvm::Type::VoidTy)
-            new llvm::ReturnInst(p->scopebb());
-        else
+        if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
+            if (fin.empty()) {
+                new llvm::ReturnInst(p->scopebb());
+            }
+            else {
+                new llvm::BranchInst(fin.back().bb);
+                fin.back().ret = true;
+            }
+        }
+        else {
+            assert(0); // why should this ever happen?
             new llvm::UnreachableInst(p->scopebb());
+        }
     }
-
-    p->scope().returned = true;
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -196,33 +212,26 @@
 
     llvm::BasicBlock* oldend = p->scopeend();
 
-    IRScope irs;
+    llvm::BasicBlock* beginbb = 0;
+    
     // remove useless branches by clearing and reusing the current basicblock
     llvm::BasicBlock* bb = p->scopebegin();
     if (bb->empty()) {
-        irs.begin = bb;
+        beginbb = bb;
     }
     else {
-        irs.begin = new llvm::BasicBlock("scope", p->topfunc(), oldend);
-        new llvm::BranchInst(irs.begin, p->scopebegin());
+        assert(!p->scopereturned());
+        beginbb = new llvm::BasicBlock("scope", p->topfunc(), oldend);
+        new llvm::BranchInst(beginbb, p->scopebegin());
     }
-    irs.end = new llvm::BasicBlock("endscope", p->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("endscope", p->topfunc(), oldend);
 
-    gIR->scope() = irs;
+    gIR->scope() = IRScope(beginbb, endbb);
 
     statement->toIR(p);
 
     p->scope() = IRScope(p->scopebb(),oldend);
-    irs.end->eraseFromParent();
-
-    /*
-    if (!gIR->scopereturned()) {
-        new llvm::BranchInst(irs.end, gIR->scopebegin());
-    }
-
-    // rewrite the scope
-    gIR->scope() = IRScope(irs.end,oldend);
-    */
+    endbb->eraseFromParent();
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -239,7 +248,8 @@
     llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend);
 
     // move into the while block
-    new llvm::BranchInst(whilebb, gIR->scopebegin());
+    p->ir->CreateBr(whilebb);
+    //new llvm::BranchInst(whilebb, gIR->scopebegin());
 
     // replace current scope
     gIR->scope() = IRScope(whilebb,endbb);
@@ -324,10 +334,7 @@
     // move into the for condition block, ie. start the loop
     new llvm::BranchInst(forbb, gIR->scopebegin());
 
-    IRScope loop;
-    loop.begin = forincbb;
-    loop.end = endbb;
-    p->loopbbs.push_back(loop);
+    p->loopbbs.push_back(IRScope(forincbb,endbb));
 
     // replace current scope
     gIR->scope() = IRScope(forbb,forbodybb);
@@ -419,30 +426,46 @@
     Logger::println("TryFinallyStatement::toIR(%d): %s", wsi++, toChars());
     LOG_SCOPE;
 
-    llvm::BasicBlock* oldend = gIR->scopeend();
+    llvm::BasicBlock* oldend = p->scopeend();
 
-    llvm::BasicBlock* trybb = new llvm::BasicBlock("try", gIR->topfunc(), oldend);
-    llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", gIR->topfunc(), oldend);
-    llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", gIR->topfunc(), oldend);
+    llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend);
+    llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend);
 
     // pass the previous BB into this
-    new llvm::BranchInst(trybb, gIR->scopebegin());
+    new llvm::BranchInst(trybb, p->scopebb());
 
-    gIR->scope() = IRScope(trybb,finallybb);
+    p->scope() = IRScope(trybb,finallybb);
 
     assert(body);
+    gIR->func().finallys.push_back(IRFinally(finallybb));
     body->toIR(p);
-    new llvm::BranchInst(finallybb, gIR->scopebegin());
+    if (!gIR->scopereturned())
+        new llvm::BranchInst(finallybb, p->scopebb());
 
     // rewrite the scope
-    gIR->scope() = IRScope(finallybb,endbb);
+    p->scope() = IRScope(finallybb,endbb);
 
     assert(finalbody);
     finalbody->toIR(p);
-    new llvm::BranchInst(endbb, gIR->scopebegin());
+    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()) {
+        new llvm::BranchInst(endbb, p->scopebb());
+    }
+
+    p->func().finallys.pop_back();
 
     // rewrite the scope
-    gIR->scope() = IRScope(endbb,oldend);
+    p->scope() = IRScope(endbb,oldend);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -628,7 +651,7 @@
     const llvm::Type* valtype = LLVM_DtoType(value->type);
     llvm::Value* valvar = new llvm::AllocaInst(keytype, "foreachval", p->topallocapoint());
 
-    if (aggr->type->ty == Tsarray)
+    if (LLVM_DtoDType(aggr->type)->ty == Tsarray)
     {
         assert(llvm::isa<llvm::PointerType>(val->getType()));
         assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0)));
@@ -686,7 +709,7 @@
     body->toIR(p);
     p->loopbbs.pop_back();
 
-    if (!p->scope().returned)
+    if (!p->scopereturned())
         new llvm::BranchInst(nexbb, p->scopebb());
 
     // end
@@ -734,12 +757,29 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
+void WithStatement::toIR(IRState* p)
+{
+    Logger::println("WithStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    assert(exp);
+    assert(body);
+
+    elem* e = exp->toElem(p);
+    wthis->llvmValue = e->getValue();
+    delete e;
+
+    body->toIR(p);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
 //////////////////////////////////////////////////////////////////////////////
 
 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();}
 //STUBST(BreakStatement);
 //STUBST(ForStatement);
-STUBST(WithStatement);
+//STUBST(WithStatement);
 STUBST(SynchronizedStatement);
 //STUBST(ReturnStatement);
 //STUBST(ContinueStatement);