diff gen/tollvm.cpp @ 129:8096ba7082db trunk

[svn r133] Fixed some problems with inlining not happening :P Fixed problems with certain cases of deeply nested classes/functions.
author lindquist
date Fri, 28 Dec 2007 22:55:24 +0100
parents 9c79b61fb638
children 5825d48b27d1
line wrap: on
line diff
--- a/gen/tollvm.cpp	Fri Nov 30 17:12:08 2007 +0100
+++ b/gen/tollvm.cpp	Fri Dec 28 22:55:24 2007 +0100
@@ -796,64 +796,143 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::Value* DtoNestedVariable(VarDeclaration* vd)
+static void print_frame_worker(VarDeclaration* var, Dsymbol* par)
 {
-    FuncDeclaration* fd = vd->toParent()->isFuncDeclaration();
-    assert(fd != NULL);
-
-    IRFunction* fcur = gIR->func();
-    FuncDeclaration* f = fcur->decl;
-
-    // on this stack
-    if (fd == f) {
-        llvm::Value* vdv = vd->llvmValue;
-        if (!vdv)
-        {
-            Logger::println(":o null vd->llvmValue for: %s", vd->toChars());
-            vdv = fd->llvmNested;
-            assert(vdv);
-        }
-        assert(vd->llvmNestedIndex != ~0);
-        llvm::Value* v = DtoGEPi(vdv,0,unsigned(vd->llvmNestedIndex),"tmp");
-        if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) {
-            Logger::cout() << "1267 loading: " << *v << '\n';
-            v = gIR->ir->CreateLoad(v,"tmp");
-        }
-        return v;
+    if (var->toParent2() == par)
+    {
+        Logger::println("parent found: '%s' kind: '%s'", par->toChars(), par->kind());
+        return;
     }
 
-    // on a caller stack
-    llvm::Value* ptr = f->llvmThisVar;
+    Logger::println("diving into parent: '%s' kind: '%s'", par->toChars(), par->kind());
+    LOG_SCOPE;
+    print_frame_worker(var, par->toParent2());
+}
+
+static void print_nested_frame_list(VarDeclaration* var, Dsymbol* par)
+{
+    Logger::println("PRINTING FRAME LIST FOR NESTED VAR: '%s'", var->toChars());
+    {
+        LOG_SCOPE;
+        print_frame_worker(var, par);
+    }
+    Logger::println("DONE");
+}
+
+static const llvm::Type* get_next_frame_ptr_type(Dsymbol* sc)
+{
+    assert(sc->isFuncDeclaration() || sc->isClassDeclaration());
+    Dsymbol* p = sc->toParent2();
+    assert(p->isFuncDeclaration() || p->isClassDeclaration());
+    if (FuncDeclaration* fd = p->isFuncDeclaration())
+    {
+        llvm::Value* v = fd->llvmNested;
+        assert(v);
+        return v->getType();
+    }
+    else if (ClassDeclaration* cd = p->isClassDeclaration())
+    {
+        return DtoType(cd->type);
+    }
+    else
+    {
+        Logger::println("symbol: '%s' kind: '%s'", sc->toChars(), sc->kind());
+        assert(0);
+    }
+}
+
+static llvm::Value* get_frame_ptr_impl(VarDeclaration* vd, Dsymbol* sc, llvm::Value* v)
+{
+    if (vd->toParent2() == sc)
+    {
+        return v;
+    }
+    else if (FuncDeclaration* fd = sc->isFuncDeclaration())
+    {
+        Logger::println("scope is function");
+        v = DtoBitCast(v, get_next_frame_ptr_type(fd));
+        Logger::cout() << "v = " << *v << '\n';
+
+        if (fd->toParent2() == vd->toParent2())
+            return v;
+
+        if (fd->toParent2()->isFuncDeclaration())
+        {
+            v = DtoGEPi(v, 0,0, "tmp");
+            v = DtoLoad(v);
+        }
+        else if (ClassDeclaration* cd = fd->toParent2()->isClassDeclaration())
+        {
+            size_t idx = 2;
+            idx += cd->llvmIRStruct->interfaces.size();
+            v = DtoGEPi(v,0,idx,"tmp");
+            v = DtoLoad(v);
+        }
+        else
+        {
+            assert(0);
+        }
+        return get_frame_ptr_impl(vd, fd->toParent2(), v);
+    }
+    else if (ClassDeclaration* cd = sc->isClassDeclaration())
+    {
+        Logger::println("scope is class");
+        /*size_t idx = 2;
+        idx += cd->llvmIRStruct->interfaces.size();
+        v = DtoGEPi(v,0,idx,"tmp");
+        Logger::cout() << "gep = " << *v << '\n';
+        v = DtoLoad(v);*/
+        return get_frame_ptr_impl(vd, cd->toParent2(), v);
+    }
+    else
+    {
+        Logger::println("symbol: '%s'", sc->toChars());
+        assert(0);
+    }
+}
+
+static llvm::Value* get_frame_ptr(VarDeclaration* vd)
+{
+    Logger::println("RESOLVING FRAME PTR FOR NESTED VAR: '%s'", vd->toChars());
+    LOG_SCOPE;
+    IRFunction* irfunc = gIR->func();
+
+    // in the parent scope already
+    if (vd->toParent2() == irfunc->decl)
+        return irfunc->decl->llvmNested;
+
+    // use the 'this' pointer
+    llvm::Value* ptr = irfunc->decl->llvmThisVar;
     assert(ptr);
 
-    f = f->toParent()->isFuncDeclaration();
-    assert(f);
-    assert(f->llvmNested);
-    const llvm::Type* nesttype = f->llvmNested->getType();
-    assert(nesttype);
+    // return the fully resolved frame pointer
+    ptr = get_frame_ptr_impl(vd, irfunc->decl, ptr);
+    Logger::cout() << "FOUND: '" << *ptr << "'\n";
 
-    ptr = gIR->ir->CreateBitCast(ptr, nesttype, "tmp");
+    return ptr;
+}
 
-    Logger::cout() << "nested var reference:" << '\n' << *ptr << *nesttype << '\n';
+llvm::Value* DtoNestedVariable(VarDeclaration* vd)
+{
+    // log the frame list
+    IRFunction* irfunc = gIR->func();
+    print_nested_frame_list(vd, irfunc->decl);
 
-    while (f) {
-        if (fd == f) {
-            llvm::Value* v = DtoGEPi(ptr,0,vd->llvmNestedIndex,"tmp");
-            if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) {
-                Logger::cout() << "1291 loading: " << *v << '\n';
-                v = gIR->ir->CreateLoad(v,"tmp");
-            }
-            return v;
-        }
-        else {
-            ptr = DtoGEPi(ptr,0,0,"tmp");
-            ptr = gIR->ir->CreateLoad(ptr,"tmp");
-        }
-        f = f->toParent()->isFuncDeclaration();
-    }
+    // resolve frame ptr
+    llvm::Value* ptr = get_frame_ptr(vd);
+    Logger::cout() << "nested ptr = " << *ptr << '\n';
+
+    // we must cast here to be sure. nested classes just have a void*
+    ptr = DtoBitCast(ptr, vd->toParent2()->isFuncDeclaration()->llvmNested->getType());
 
-    assert(0 && "nested var not found");
-    return NULL;
+    // index nested var and load (if necessary)
+    llvm::Value* v = DtoGEPi(ptr, 0, vd->llvmNestedIndex, "tmp");
+    // references must be loaded, for normal variables this IS already the variable storage!!!
+    if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)))
+        v = DtoLoad(v);
+
+    Logger::cout() << "FINAL RESULT: " << *v << '\n';
+    return v;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////