changeset 15:37a4fdab33fc trunk

[svn r19] * Added support for reassigning 'this' inside class constructors. * Added preliminary support for UnrolledLoopStatement. That is foreach on a tuple.
author lindquist
date Wed, 03 Oct 2007 04:56:32 +0200
parents 0e86428ee567
children 860524276608
files dmd/declaration.h dmd/func.c gen/elem.c gen/elem.h gen/irstate.h gen/statements.c gen/toir.c gen/toobj.c test/classes8.d test/unrolled.d
diffstat 10 files changed, 138 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/declaration.h	Wed Oct 03 02:15:12 2007 +0200
+++ b/dmd/declaration.h	Wed Oct 03 04:56:32 2007 +0200
@@ -511,6 +511,7 @@
     FuncDeclaration *isFuncDeclaration() { return this; }
 
     bool llvmQueued;
+    llvm::Value* llvmThisVar;
 };
 
 struct FuncAliasDeclaration : FuncDeclaration
--- a/dmd/func.c	Wed Oct 03 02:15:12 2007 +0200
+++ b/dmd/func.c	Wed Oct 03 04:56:32 2007 +0200
@@ -74,6 +74,7 @@
     nrvo_var = NULL;
     shidden = NULL;
     llvmQueued = false;
+    llvmThisVar = NULL;
 }
 
 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
--- a/gen/elem.c	Wed Oct 03 02:15:12 2007 +0200
+++ b/gen/elem.c	Wed Oct 03 04:56:32 2007 +0200
@@ -18,6 +18,7 @@
     inplace = false;
     field = false;
     callconv = (unsigned)-1;
+    isthis = false;
 
     vardecl = 0;
     funcdecl = 0;
--- a/gen/elem.h	Wed Oct 03 02:15:12 2007 +0200
+++ b/gen/elem.h	Wed Oct 03 04:56:32 2007 +0200
@@ -32,6 +32,7 @@
     bool inplace;
     bool field;
     unsigned callconv;
+    bool isthis;
 
     VarDeclaration* vardecl;
     FuncDeclaration* funcdecl;
--- a/gen/irstate.h	Wed Oct 03 02:15:12 2007 +0200
+++ b/gen/irstate.h	Wed Oct 03 04:56:32 2007 +0200
@@ -78,9 +78,11 @@
     // classes TODO move into IRClass
     typedef std::vector<ClassDeclaration*> ClassDeclVec;
     ClassDeclVec classes;
+
     typedef std::vector<FuncDeclaration*> FuncDeclVec;
     typedef std::vector<FuncDeclVec> ClassMethodVec;
     ClassMethodVec classmethods;
+
     typedef std::vector<bool> BoolVec;
     BoolVec queueClassMethods;
 
@@ -111,6 +113,9 @@
     // VarDeclaration for __dollar, but I can't see how to get the
     // array pointer from this :(
     LvalVec arrays;
+
+    // keeping track of the declaration for the current function body
+    FuncDeclVec funcdecls;
 };
 
 #endif // LLVMDC_GEN_IRSTATE_H
--- a/gen/statements.c	Wed Oct 03 02:15:12 2007 +0200
+++ b/gen/statements.c	Wed Oct 03 04:56:32 2007 +0200
@@ -27,7 +27,7 @@
 #include "gen/runtime.h"
 #include "gen/arrays.h"
 
-/* --------------------------------------------------------------------------------------- */
+//////////////////////////////////////////////////////////////////////////////
 
 void CompoundStatement::toIR(IRState* p)
 {
@@ -71,6 +71,8 @@
     //p->bbs.pop();
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void ReturnStatement::toIR(IRState* p)
 {
     static int rsi = 0;
@@ -134,6 +136,8 @@
     p->scope().returned = true;
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void ExpStatement::toIR(IRState* p)
 {
     static int esi = 0;
@@ -150,6 +154,8 @@
     p->buf.writenl();*/
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void IfStatement::toIR(IRState* p)
 {
     static int wsi = 0;
@@ -204,6 +210,8 @@
     gIR->scope() = IRScope(endbb,oldend);
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void ScopeStatement::toIR(IRState* p)
 {
     Logger::println("ScopeStatement::toIR(): %s", toChars());
@@ -240,6 +248,8 @@
     */
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void WhileStatement::toIR(IRState* p)
 {
     static int wsi = 0;
@@ -281,6 +291,8 @@
     gIR->scope() = IRScope(endbb,oldend);
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void DoStatement::toIR(IRState* p)
 {
     static int wsi = 0;
@@ -313,6 +325,8 @@
     gIR->scope() = IRScope(endbb,oldend);
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void ForStatement::toIR(IRState* p)
 {
     static int wsi = 0;
@@ -374,6 +388,8 @@
     gIR->scope() = IRScope(endbb,oldend);
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void BreakStatement::toIR(IRState* p)
 {
     static int wsi = 0;
@@ -389,6 +405,8 @@
     }
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void ContinueStatement::toIR(IRState* p)
 {
     static int wsi = 0;
@@ -404,6 +422,8 @@
     }
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void OnScopeStatement::toIR(IRState* p)
 {
     static int wsi = 0;
@@ -414,6 +434,8 @@
     //statement->toIR(p); // this seems to be redundant
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void TryFinallyStatement::toIR(IRState* p)
 {
     static int wsi = 0;
@@ -446,6 +468,8 @@
     gIR->scope() = IRScope(endbb,oldend);
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void TryCatchStatement::toIR(IRState* p)
 {
     static int wsi = 0;
@@ -465,6 +489,8 @@
     }
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void ThrowStatement::toIR(IRState* p)
 {
     static int wsi = 0;
@@ -478,6 +504,8 @@
     delete e;
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
 void SwitchStatement::toIR(IRState* p)
 {
     Logger::println("SwitchStatement::toIR(): %s", toChars());
@@ -561,6 +589,35 @@
     gIR->scope() = IRScope(endbb,oldend);
 }
 
+//////////////////////////////////////////////////////////////////////////////
+
+void UnrolledLoopStatement::toIR(IRState* p)
+{
+    Logger::println("UnrolledLoopStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    llvm::BasicBlock* oldend = gIR->scopeend();
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("unrolledend", p->topfunc(), oldend);
+
+    p->scope() = IRScope(p->scopebb(),endbb);
+    p->loopbbs.push_back(IRScope(p->scopebb(),endbb));
+
+    for (int i=0; i<statements->dim; ++i)
+    {
+        Statement* s = (Statement*)statements->data[i];
+        s->toIR(p);
+    }
+
+    p->loopbbs.pop_back();
+
+    new llvm::BranchInst(endbb, p->scopebb());
+    p->scope() = IRScope(endbb,oldend);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+
 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();}
 //STUBST(BreakStatement);
 //STUBST(ForStatement);
@@ -589,5 +646,5 @@
 STUBST(GotoCaseStatement);
 STUBST(GotoDefaultStatement);
 STUBST(GotoStatement);
-STUBST(UnrolledLoopStatement);
+//STUBST(UnrolledLoopStatement);
 //STUBST(OnScopeStatement);
--- a/gen/toir.c	Wed Oct 03 02:15:12 2007 +0200
+++ b/gen/toir.c	Wed Oct 03 04:56:32 2007 +0200
@@ -384,8 +384,19 @@
     else if (e1ty == Tclass) {
         if (e2ty == Tclass) {
             llvm::Value* tmp = r->getValue();
-            Logger::cout() << "tmp: " << *tmp << ", " << *l->mem << '\n';
-            new llvm::StoreInst(tmp, l->mem, p->scopebb());
+            Logger::cout() << "tmp: " << *tmp << " ||| " << *l->mem << '\n';
+            // assignment to this in constructor special case
+            if (l->isthis) {
+                FuncDeclaration* fdecl = p->funcdecls.back();
+                // respecify the this param
+                if (!llvm::isa<llvm::AllocaInst>(fdecl->llvmThisVar))
+                    fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", p->topallocapoint());
+                new llvm::StoreInst(tmp, fdecl->llvmThisVar, p->scopebb());
+            }
+            // regular class ref -> class ref assignment
+            else {
+                new llvm::StoreInst(tmp, l->mem, p->scopebb());
+            }
         }
         else
         assert(0);
@@ -1218,7 +1229,7 @@
             TypeStruct* ts = (TypeStruct*)e1->type->next;
             ts->sym->offsetToIndex(vd->offset, vdoffsets);
             Logger::println("Struct member offset:%d", vd->offset);
-            src = l->val;
+            src = l->val ? l->val : l->mem;
         }
         else if (e1->type->ty == Tclass) {
             TypeClass* tc = (TypeClass*)e1->type;
@@ -1279,7 +1290,7 @@
     elem* e = new elem;
 
     if (VarDeclaration* vd = var->isVarDeclaration()) {
-        assert(vd->llvmValue == 0);
+        /*assert(vd->llvmValue == 0);
 
         llvm::Function* fn = p->topfunc();
         assert(fn);
@@ -1292,10 +1303,14 @@
         v = ++fn->arg_begin();
         else
         v = fn->arg_begin();
-        assert(v);
+        assert(v);*/
 
-        e->val = v;
+        llvm::Value* v = p->funcdecls.back()->llvmThisVar;
+        if (llvm::isa<llvm::AllocaInst>(v))
+            v = new llvm::LoadInst(v, "tmp", p->scopebb());
+        e->mem = v;
         e->type = elem::VAL;
+        e->isthis = true;
     }
     else {
         assert(0);
@@ -1794,7 +1809,7 @@
 
     e->inplace = true;
     e->type = elem::VAR;
-    
+
     return e;
 }
 
--- a/gen/toobj.c	Wed Oct 03 02:15:12 2007 +0200
+++ b/gen/toobj.c	Wed Oct 03 04:56:32 2007 +0200
@@ -665,9 +665,20 @@
         // function definition
         if (allow_fbody && fbody != 0)
         {
+            gIR->funcdecls.push_back(this);
+
             // first make absolutely sure the type is up to date
             f->llvmType = llvmValue->getType()->getContainedType(0);
 
+            // this handling
+            if (f->llvmUsesThis) {
+                if (f->llvmRetInPtr)
+                    llvmThisVar = ++func->arg_begin();
+                else
+                    llvmThisVar = func->arg_begin();
+                assert(llvmThisVar != 0);
+            }
+
             if (isMain())
                 gIR->emitMain = true;
 
@@ -716,6 +727,8 @@
                 // possibly assert(lastbb->getNumPredecessors() == 0); ??? try it out sometime ...
                 new llvm::UnreachableInst(lastbb);
             }
+
+            gIR->funcdecls.pop_back();
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes8.d	Wed Oct 03 04:56:32 2007 +0200
@@ -0,0 +1,22 @@
+class A {
+    int i;
+    int l;
+    this(bool b,bool b2=false) {
+        if (b) this = new B;
+        i = 4;
+        if (b2) this = new C;
+        l = 64;
+    }
+}
+class B : A{
+    this() {
+        super(false);
+    }
+}
+class C : A{
+    this() {
+        super(false);
+    }
+}
+void main() {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/unrolled.d	Wed Oct 03 04:56:32 2007 +0200
@@ -0,0 +1,13 @@
+module unrolled;
+
+void test(T...)(T t) {
+    foreach (value; t) {
+        printf("%d\n", value);
+        if (value == 2)
+            break;
+    }
+}
+
+void main() {
+    test(1,4,3);
+}