changeset 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 e5fe8521bbfa
children a7dfa0ed966c
files dmd/declaration.h dmd/link.c dmd/mars.c dmd/mars.h gen/functions.cpp gen/optimizer.cpp gen/toir.cpp gen/tollvm.cpp gen/toobj.cpp llvmdc.kdevelop.filelist test/bug73.d test/nested10.d test/nested5.d test/nested6.d test/nested7.d test/nested8.d test/nested9.d
diffstat 17 files changed, 266 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/declaration.h	Fri Nov 30 17:12:08 2007 +0100
+++ b/dmd/declaration.h	Fri Dec 28 22:55:24 2007 +0100
@@ -606,6 +606,7 @@
 
     FuncDeclaration *isFuncDeclaration() { return this; }
 
+    // llvmdc stuff
     bool llvmQueued;
     llvm::Value* llvmThisVar;
     std::set<VarDeclaration*> llvmNestedVars;
--- a/dmd/link.c	Fri Nov 30 17:12:08 2007 +0100
+++ b/dmd/link.c	Fri Dec 28 22:55:24 2007 +0100
@@ -247,7 +247,7 @@
         argv.push((void*)s);
     }
 
-    if (!global.params.useInline) {
+    if (!(global.params.useInline || global.params.llvmInline)) {
         argv.push((void *)"-disable-inlining");
     }
 
--- a/dmd/mars.c	Fri Nov 30 17:12:08 2007 +0100
+++ b/dmd/mars.c	Fri Dec 28 22:55:24 2007 +0100
@@ -264,6 +264,7 @@
     global.params.useArrayBounds = 0;
     global.params.useSwitchError = 0;
     global.params.useInline = 0; // this one messes things up to a point where codegen breaks
+    global.params.llvmInline = 0; // use this one instead to know if inline passes should be run
     global.params.obj = 1;
     global.params.Dversion = 2;
 
@@ -471,9 +472,10 @@
 #endif
 	    else if (strcmp(p + 1, "inline") == 0) {
             // TODO
-            // the ast rewrites dmd does for inling messes up the ast
+            // the ast rewrites dmd does for inlining messes up the ast.
             // someday maybe we can support it, for now llvm does an excellent job at inlining
             global.params.useInline = 0; //1
+            global.params.llvmInline = 1;
         }
 	    else if (strcmp(p + 1, "nofloat") == 0)
 		global.params.nofloat = 1;
--- a/dmd/mars.h	Fri Nov 30 17:12:08 2007 +0100
+++ b/dmd/mars.h	Fri Dec 28 22:55:24 2007 +0100
@@ -129,6 +129,7 @@
     char *tt_os;
     char *data_layout;
     char disassemble;
+    char llvmInline;
 };
 
 struct Global
--- a/gen/functions.cpp	Fri Nov 30 17:12:08 2007 +0100
+++ b/gen/functions.cpp	Fri Dec 28 22:55:24 2007 +0100
@@ -540,7 +540,7 @@
                         }
                     }
                     const llvm::StructType* nestSType = llvm::StructType::get(nestTypes);
-                    Logger::cout() << "nested var struct has type:" << '\n' << *nestSType;
+                    Logger::cout() << "nested var struct has type:" << *nestSType << '\n';
                     fd->llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",allocaPoint);
                     if (parentNested) {
                         assert(fd->llvmThisVar);
--- a/gen/optimizer.cpp	Fri Nov 30 17:12:08 2007 +0100
+++ b/gen/optimizer.cpp	Fri Dec 28 22:55:24 2007 +0100
@@ -13,8 +13,6 @@
 void llvmdc_optimize_module(Module* m, char lvl, bool doinline)
 {
     assert(lvl >= 0 && lvl <= 5);
-    if (lvl == 0)
-        return;
 
     PassManager pm;
     pm.add(new TargetData(m));
@@ -24,12 +22,12 @@
         pm.add(createRaiseAllocationsPass());
         pm.add(createCFGSimplificationPass());
         pm.add(createPromoteMemoryToRegisterPass());
+        pm.add(createGlobalOptimizerPass());
+        pm.add(createGlobalDCEPass());
     }
 
     if (lvl >= 2)
     {
-        pm.add(createGlobalOptimizerPass());
-        pm.add(createGlobalDCEPass());
         pm.add(createIPConstantPropagationPass());
         pm.add(createDeadArgEliminationPass());
         pm.add(createInstructionCombiningPass());
@@ -77,5 +75,6 @@
 
     // level 4 and 5 are linktime optimizations
 
-    pm.run(*m);
+    if (lvl > 0 || doinline)
+        pm.run(*m);
 }
--- a/gen/toir.cpp	Fri Nov 30 17:12:08 2007 +0100
+++ b/gen/toir.cpp	Fri Dec 28 22:55:24 2007 +0100
@@ -1824,6 +1824,18 @@
             idx += tc->sym->llvmIRStruct->interfaces.size();
             DtoStore(thisval->getRVal(), DtoGEPi(emem,0,idx,"tmp"));
         }
+        else if (tc->sym->isNested())
+        {
+            size_t idx = 2;
+            idx += tc->sym->llvmIRStruct->interfaces.size();
+            llvm::Value* nest = p->func()->decl->llvmNested;
+            if (!nest)
+                nest = p->func()->decl->llvmThisVar;
+            assert(nest);
+            llvm::Value* gep = DtoGEPi(emem,0,idx,"tmp");
+            nest = DtoBitCast(nest, gep->getType()->getContainedType(0));
+            DtoStore(nest, gep);
+        }
 
         // then call constructor
         if (arguments) {
--- 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;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
--- a/gen/toobj.cpp	Fri Nov 30 17:12:08 2007 +0100
+++ b/gen/toobj.cpp	Fri Dec 28 22:55:24 2007 +0100
@@ -138,7 +138,7 @@
 
     // run optimizer
     if (global.params.optimize) {
-        llvmdc_optimize_module(ir.module, global.params.optimizeLevel, global.params.useInline);
+        llvmdc_optimize_module(ir.module, global.params.optimizeLevel, global.params.llvmInline);
     }
 
     // write bytecode
--- a/llvmdc.kdevelop.filelist	Fri Nov 30 17:12:08 2007 +0100
+++ b/llvmdc.kdevelop.filelist	Fri Dec 28 22:55:24 2007 +0100
@@ -259,6 +259,7 @@
 test/arrays8.d
 test/arrays9.d
 test/assign.d
+test/ast1.d
 test/b.d
 test/bitops.d
 test/bug1.d
@@ -336,6 +337,7 @@
 test/c.d
 test/classes.d
 test/classes10.d
+test/classes11.d
 test/classes2.d
 test/classes3.d
 test/classes4.d
@@ -406,9 +408,15 @@
 test/multiarr4.d
 test/neg.d
 test/nested1.d
+test/nested10.d
 test/nested2.d
 test/nested3.d
 test/nested4.d
+test/nested5.d
+test/nested6.d
+test/nested7.d
+test/nested8.d
+test/nested9.d
 test/pointers.d
 test/pt.d
 test/ptrarith.d
--- a/test/bug73.d	Fri Nov 30 17:12:08 2007 +0100
+++ b/test/bug73.d	Fri Dec 28 22:55:24 2007 +0100
@@ -11,4 +11,9 @@
 
 void main()
 {
-}
\ No newline at end of file
+    char[] hello = "hello world";
+    int i = find(hello, 'w');
+    assert(i == 6);
+    i = find(hello, 'z');
+    assert(i == -1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nested10.d	Fri Dec 28 22:55:24 2007 +0100
@@ -0,0 +1,20 @@
+module nested10;
+
+void main()
+{
+    int j = 3;
+    void F()
+    {
+        int i = j;
+        printf("F: i = %d, j = %d\n", i, j);
+        void G()
+        {
+            printf("G: i = %d, j = %d\n", i, j);
+            j += i;
+        }
+        G();
+    }
+    F();
+    printf("6 = %d\n", j);
+    assert(j == 6);
+}
--- a/test/nested5.d	Fri Nov 30 17:12:08 2007 +0100
+++ b/test/nested5.d	Fri Dec 28 22:55:24 2007 +0100
@@ -11,9 +11,11 @@
         void func()
         {
             printf("Hello world %d\n", i++);
+            //i++;
         }
     }
 
     scope c = new C;
     c.func();
+    assert(i == 44);
 }
--- a/test/nested6.d	Fri Nov 30 17:12:08 2007 +0100
+++ b/test/nested6.d	Fri Dec 28 22:55:24 2007 +0100
@@ -4,19 +4,19 @@
 {
     int i = 42;
 
-    printf("Hello world %d\n", i++);
+    printf("main() %d\n", i++);
 
     class C
     {
         void func()
         {
-            printf("Hello world %d\n", i++);
+            printf("C.func() %d\n", i++);
 
             class C2
             {
                 void func2()
                 {
-                    printf("Hello world %d\n", i++);
+                    printf("C2.func2() %d\n", i++);
                 }
             }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nested7.d	Fri Dec 28 22:55:24 2007 +0100
@@ -0,0 +1,32 @@
+module nested7;
+
+void main()
+{
+    int i;
+    i = 52;
+    printf("i = %d\n", i);
+
+    void func()
+    {
+        i++;
+
+        void func2()
+        {
+            i++;
+
+            void func3()
+            {
+                i++;
+            }
+
+            func3();
+        }
+
+        func2();
+    }
+
+    func();
+
+    printf("i = %d\n", i);
+    assert(i == 55);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nested8.d	Fri Dec 28 22:55:24 2007 +0100
@@ -0,0 +1,30 @@
+module nested8;
+
+void main()
+{
+    int i = 1;
+    void func()
+    {
+        printf("func()\n");
+        i++;
+        void func2()
+        {
+            printf(" func2()\n");
+            int j = i + 1;
+            void func3()
+            {
+                printf("  func3()\n");
+                j++;
+                printf("  done = %d\n", j);
+            }
+            func3();
+            i = j;
+            printf(" done = %d\n", j);
+        }
+        func2();
+        printf("done\n");
+    }
+    func();
+    printf("i == %d\n", i);
+    assert(i == 4);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nested9.d	Fri Dec 28 22:55:24 2007 +0100
@@ -0,0 +1,13 @@
+module nested9;
+
+void main()
+{
+    int i = 42;
+    int func()
+    {
+        return i + 1;
+    }
+    int j = func();
+    printf("j = %d\n", j);
+    assert(j == 43);
+}