# HG changeset patch # User lindquist # Date 1198878924 -3600 # Node ID 8096ba7082dbb3034411d086e3de30dd2ba87fb7 # Parent e5fe8521bbfab8338eaa0336bddb89b269ce78e7 [svn r133] Fixed some problems with inlining not happening :P Fixed problems with certain cases of deeply nested classes/functions. diff -r e5fe8521bbfa -r 8096ba7082db dmd/declaration.h --- 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 llvmNestedVars; diff -r e5fe8521bbfa -r 8096ba7082db dmd/link.c --- 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"); } diff -r e5fe8521bbfa -r 8096ba7082db dmd/mars.c --- 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; diff -r e5fe8521bbfa -r 8096ba7082db dmd/mars.h --- 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 diff -r e5fe8521bbfa -r 8096ba7082db gen/functions.cpp --- 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); diff -r e5fe8521bbfa -r 8096ba7082db gen/optimizer.cpp --- 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); } diff -r e5fe8521bbfa -r 8096ba7082db gen/toir.cpp --- 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) { diff -r e5fe8521bbfa -r 8096ba7082db gen/tollvm.cpp --- 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; } ////////////////////////////////////////////////////////////////////////////////////////// diff -r e5fe8521bbfa -r 8096ba7082db gen/toobj.cpp --- 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 diff -r e5fe8521bbfa -r 8096ba7082db llvmdc.kdevelop.filelist --- 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 diff -r e5fe8521bbfa -r 8096ba7082db test/bug73.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); +} diff -r e5fe8521bbfa -r 8096ba7082db test/nested10.d --- /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); +} diff -r e5fe8521bbfa -r 8096ba7082db test/nested5.d --- 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); } diff -r e5fe8521bbfa -r 8096ba7082db test/nested6.d --- 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++); } } diff -r e5fe8521bbfa -r 8096ba7082db test/nested7.d --- /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); +} diff -r e5fe8521bbfa -r 8096ba7082db test/nested8.d --- /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); +} diff -r e5fe8521bbfa -r 8096ba7082db test/nested9.d --- /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); +}