diff gen/llvmhelpers.cpp @ 486:a34078905d01

Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in. Reimplemented support for nested functions/class using a new approach. Added error on taking address of intrinsic. Fixed problems with the ->syntaxCopy of TypeFunction delegate exp. Removed DtoDType and replaced all uses with ->toBasetype() instead. Removed unused inplace stuff. Fixed a bunch of issues in the runtime unittests, not complete yet. Added mini tests.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Sun, 10 Aug 2008 08:37:38 +0200
parents d86af825e8d9
children a3d6c9eedcb6 837af2a63564
line wrap: on
line diff
--- a/gen/llvmhelpers.cpp	Sat Aug 09 09:03:52 2008 +0200
+++ b/gen/llvmhelpers.cpp	Sun Aug 10 08:37:38 2008 +0200
@@ -349,154 +349,70 @@
 // NESTED VARIABLE HELPERS
 ////////////////////////////////////////////////////////////////////////////////////////*/
 
-/*
-
-got:
-
-    context pointer of 'this' function
-
-    declaration for target context's function
-
-want:
-
-    context pointer of target function in call chain
-
-*/
-
-static LLValue* dive_into_nested(Dsymbol* from, LLValue* val)
+DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
 {
-    from = from->toParent2();
-
-    // parent is a function
-    if (FuncDeclaration* f = from->isFuncDeclaration())
+    Dsymbol* vdparent = vd->toParent2();
+    assert(vdparent);
+    
+    IrFunction* irfunc = gIR->func();
+    
+    // is the nested variable in this scope?
+    if (vdparent == irfunc->decl)
     {
-        IrFunction* irfunc = f->ir.irFunc;
-        // parent has nested var struct
-        if (irfunc->nestedVar)
-        {
-            return DtoBitCast(val, irfunc->nestedVar->getType());
-        }
-        // parent has this argument
-        else if (irfunc->thisVar)
-        {
-            return DtoBitCast(val, irfunc->thisVar->getType()->getContainedType(0));
-        }
-        // none of the above, means no context is required, dummy.
-        else
-        {
-            return getNullPtr(getVoidPtrType());
-        }
+        LLValue* val = vd->ir.getIrValue();
+        return new DVarValue(astype, vd, val, true);
+    }
+    
+    // get it from the nested context
+    LLValue* ctx = 0;
+    if (irfunc->decl->isMember2())
+    {
+        ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
+        LLValue* val = DtoLoad(irfunc->thisArg);
+        ctx = DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
     }
-    // parent is a class
-    else if (ClassDeclaration* c = from->isClassDeclaration())
-    {
-        return DtoBitCast(DtoLoad(val), DtoType(c->type));
-    }
-    // parent is not valid
     else
-    {
-        assert(0 && "!(class|function)");
-    }
+        ctx = irfunc->nestArg;
+    assert(ctx);
+    
+    assert(vd->ir.irLocal);
+    LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType()));
+    val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex);
+    val = DtoLoad(val);
+    assert(vd->ir.irLocal->value);
+    val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars());
+    return new DVarValue(astype, vd, val, true);
 }
 
-LLValue* DtoNestedContext(FuncDeclaration* func)
+LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
 {
-    Logger::println("listing context frame list for funcdecl '%s'", func->toPrettyChars());
+    Logger::println("DtoNestedContext for %s", sym->toPrettyChars());
     LOG_SCOPE;
 
-    int level = 0;
-
     IrFunction* irfunc = gIR->func();
-    Dsymbol* current = irfunc->decl;
-
-    // this context ?
-    if (current == func)
-    {
+    
+    if (irfunc->nestedVar)
         return irfunc->nestedVar;
-    }
-
-    // otherwise use the context argument
-    LLValue* val = dive_into_nested(current, irfunc->thisVar);
-    current = current->toParent2();
-    assert(val);
-
-    for (;;)
+    else if (irfunc->nestArg)
+        return irfunc->nestArg;
+    else if (irfunc->thisArg)
     {
-        Logger::cout() << "context: " << *val << '\n';
-        Logger::println("(%d) looking in: %s (%s)", level, current->toPrettyChars(), current->kind());
-        if (FuncDeclaration* f = current->isFuncDeclaration())
-        {
-            if (f == func)
-            {
-                Logger::println("-> found <-");
-                Logger::cout() << "-> val: " << *val << '\n';
-                return val;
-            }
-            else
-            {
-                val = DtoLoad(DtoGEPi(val,0,0));
-            }
-        }
-        else if (ClassDeclaration* c = current->isClassDeclaration())
-        {
-            val = DtoLoad(DtoGEPi(val, 0, 2+c->vthis->ir.irField->index));
-            val = dive_into_nested(current, val);
-        }
-        else
-        {
-            Logger::cout() << "val: " << *val << '\n';
-            assert(0 && "!(class|function)");
-        }
-        current = current->toParent2();
-        ++level;
+        ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
+        assert(cd);
+        if (!cd->vthis)
+            return getNullPtr(getVoidPtrType());
+        LLValue* val = DtoLoad(irfunc->thisArg);
+        return DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
     }
-
-    assert(0);
-    return val;
-}
-
-DValue* DtoNestedVariable(Type* astype, VarDeclaration* vd)
-{
-    IrFunction* irfunc = gIR->func();
-
-    // var parent (the scope we're looking for)
-    Dsymbol* varParent = vd->toParent2();
-
-    // on level 0
-    if (varParent == irfunc->decl)
+    else
     {
-        LLValue* nest = irfunc->nestedVar;
-        LLValue* v = DtoGEPi(nest, 0, vd->ir.irLocal->nestedIndex, "tmp");
-        // references must be loaded to get the variable address
-        if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)))
-            v = DtoLoad(v);
-        return new DVarValue(astype, vd, v, true);
+        if (irfunc->decl->isStatic())
+        {
+            irfunc->decl->error("is static and cannot access nested %s %s", sym->kind(), sym->toChars());
+            fatal();
+        }
+        return getNullPtr(getVoidPtrType());
     }
-
-    // on level n != 0
-    FuncDeclaration* varFunc = varParent->isFuncDeclaration();
-    assert(varFunc);
-
-    // get context of variable
-    LLValue* ctx = DtoNestedContext(varFunc);
-
-    // if no local var, it's the context itself (class this)
-    if (!vd->ir.irLocal)
-        return new DImValue(astype, ctx);
-
-    // extract variable
-    IrLocal* local = vd->ir.irLocal;
-    assert(local);
-    assert(local->nestedIndex >= 0);
-    LLValue* val = DtoGEPi(ctx, 0, local->nestedIndex);
-
-    // references must be loaded to get the variable address
-    if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)))
-        val = DtoLoad(val);
-
-    Logger::cout() << "value: " << *val << '\n';
-
-    return new DVarValue(astype, vd, val, true);
 }
 
 /****************************************************************************************/
@@ -509,15 +425,15 @@
     Logger::cout() << "DtoAssign(...);\n";
     LOG_SCOPE;
 
-    Type* t = DtoDType(lhs->getType());
-    Type* t2 = DtoDType(rhs->getType());
+    Type* t = lhs->getType()->toBasetype();
+    Type* t2 = rhs->getType()->toBasetype();
 
     if (t->ty == Tstruct) {
         if (!t->equals(t2)) {
             // TODO: fix this, use 'rhs' for something
             DtoAggrZeroInit(lhs->getLVal());
         }
-        else if (!rhs->inPlace()) {
+        else {
             DtoAggrCopy(lhs->getLVal(), rhs->getRVal());
         }
     }
@@ -559,7 +475,7 @@
     else if (t->ty == Tdelegate) {
         if (rhs->isNull())
             DtoAggrZeroInit(lhs->getLVal());
-        else if (!rhs->inPlace()) {
+        else {
             LLValue* l = lhs->getLVal();
             LLValue* r = rhs->getRVal();
             Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n';
@@ -665,8 +581,8 @@
 {
     const LLType* tolltype = DtoType(_to);
 
-    Type* to = DtoDType(_to);
-    Type* from = DtoDType(val->getType());
+    Type* to = _to->toBasetype();
+    Type* from = val->getType()->toBasetype();
     assert(from->isintegral());
 
     size_t fromsz = from->size();
@@ -720,8 +636,8 @@
 {
     const LLType* tolltype = DtoType(to);
 
-    Type* totype = DtoDType(to);
-    Type* fromtype = DtoDType(val->getType());
+    Type* totype = to->toBasetype();
+    Type* fromtype = val->getType()->toBasetype();
     assert(fromtype->ty == Tpointer || fromtype->ty == Tfunction);
 
     LLValue* rval;
@@ -749,8 +665,8 @@
 
     const LLType* tolltype = DtoType(to);
 
-    Type* totype = DtoDType(to);
-    Type* fromtype = DtoDType(val->getType());
+    Type* totype = to->toBasetype();
+    Type* fromtype = val->getType()->toBasetype();
     assert(fromtype->isfloating());
 
     size_t fromsz = fromtype->size();
@@ -814,7 +730,7 @@
 
 DValue* DtoCast(Loc& loc, DValue* val, Type* to)
 {
-    Type* fromtype = DtoDType(val->getType());
+    Type* fromtype = val->getType()->toBasetype();
     Logger::println("Casting from '%s' to '%s'", fromtype->toChars(), to->toChars());
     if (fromtype->isintegral()) {
         return DtoCastInt(loc, val, to);
@@ -879,10 +795,10 @@
     gIR->ir->CreateCondBr(cond, initbb, endinitbb);
     gIR->scope() = IRScope(initbb,endinitbb);
     DValue* ie = DtoInitializer(gvar, init);
-    if (!ie->inPlace()) {
-        DValue* dst = new DVarValue(t, gvar, true);
-        DtoAssign(init->loc, dst, ie);
-    }
+    
+    DVarValue dst(t, gvar, true);
+    DtoAssign(init->loc, &dst, ie);
+    
     gIR->ir->CreateStore(DtoConstBool(true), gflag);
     gIR->ir->CreateBr(endinitbb);
     gIR->scope() = IRScope(endinitbb,oldend);
@@ -1001,7 +917,7 @@
     }
 
     const LLType* _type = DtoType(vd->type);
-    Type* t = DtoDType(vd->type);
+    Type* t = vd->type->toBasetype();
 
     //Logger::cout() << "initializer: " << *_init << '\n';
     if (_type != _init->getType()) {
@@ -1218,9 +1134,23 @@
             if (vd->nestedref) {
                 Logger::println("has nestedref set");
                 assert(vd->ir.irLocal);
-                vd->ir.irLocal->value = gIR->func()->decl->ir.irFunc->nestedVar;
-                assert(vd->ir.irLocal->value);
+                
+                // alloca as usual is no value already
+                if (!vd->ir.irLocal->value)
+                {
+                    vd->ir.irLocal->value = DtoAlloca(DtoType(vd->type), vd->toChars());
+                }
+                
+                // store the address into the nested vars array
+                
                 assert(vd->ir.irLocal->nestedIndex >= 0);
+                LLValue* gep = DtoGEPi(gIR->func()->decl->ir.irFunc->nestedVar, 0, vd->ir.irLocal->nestedIndex);
+                
+                assert(isaPointer(vd->ir.irLocal->value));
+                LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
+                
+                DtoStore(val, gep);
+                
             }
             // normal stack variable, allocate storage on the stack if it has not already been done
             else if(!vd->ir.irLocal) {
@@ -1241,6 +1171,10 @@
                     DtoDwarfLocalVariable(allocainst, vd);
                 }
             }
+            else
+            {
+                assert(vd->ir.irLocal->value);
+            }
 
             Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n';
             DValue* ie = DtoInitializer(vd->ir.irLocal->value, vd->init);