[svn r133] Fixed some problems with inlining not happening :P

Fixed problems with certain cases of deeply nested classes/functions.
This commit is contained in:
Tomas Lindquist Olsen 2007-12-28 22:55:24 +01:00
parent f420bc1265
commit 5eb88f9e80
17 changed files with 263 additions and 59 deletions

View file

@ -606,6 +606,7 @@ struct FuncDeclaration : Declaration
FuncDeclaration *isFuncDeclaration() { return this; } FuncDeclaration *isFuncDeclaration() { return this; }
// llvmdc stuff
bool llvmQueued; bool llvmQueued;
llvm::Value* llvmThisVar; llvm::Value* llvmThisVar;
std::set<VarDeclaration*> llvmNestedVars; std::set<VarDeclaration*> llvmNestedVars;

View file

@ -247,7 +247,7 @@ int runLINK()
argv.push((void*)s); argv.push((void*)s);
} }
if (!global.params.useInline) { if (!(global.params.useInline || global.params.llvmInline)) {
argv.push((void *)"-disable-inlining"); argv.push((void *)"-disable-inlining");
} }

View file

@ -264,6 +264,7 @@ int main(int argc, char *argv[])
global.params.useArrayBounds = 0; global.params.useArrayBounds = 0;
global.params.useSwitchError = 0; global.params.useSwitchError = 0;
global.params.useInline = 0; // this one messes things up to a point where codegen breaks 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.obj = 1;
global.params.Dversion = 2; global.params.Dversion = 2;
@ -471,9 +472,10 @@ int main(int argc, char *argv[])
#endif #endif
else if (strcmp(p + 1, "inline") == 0) { else if (strcmp(p + 1, "inline") == 0) {
// TODO // 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 // someday maybe we can support it, for now llvm does an excellent job at inlining
global.params.useInline = 0; //1 global.params.useInline = 0; //1
global.params.llvmInline = 1;
} }
else if (strcmp(p + 1, "nofloat") == 0) else if (strcmp(p + 1, "nofloat") == 0)
global.params.nofloat = 1; global.params.nofloat = 1;

View file

@ -129,6 +129,7 @@ struct Param
char *tt_os; char *tt_os;
char *data_layout; char *data_layout;
char disassemble; char disassemble;
char llvmInline;
}; };
struct Global struct Global

View file

@ -540,7 +540,7 @@ void DtoDefineFunc(FuncDeclaration* fd)
} }
} }
const llvm::StructType* nestSType = llvm::StructType::get(nestTypes); 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); fd->llvmNested = new llvm::AllocaInst(nestSType,"nestedvars",allocaPoint);
if (parentNested) { if (parentNested) {
assert(fd->llvmThisVar); assert(fd->llvmThisVar);

View file

@ -13,8 +13,6 @@ using namespace llvm;
void llvmdc_optimize_module(Module* m, char lvl, bool doinline) void llvmdc_optimize_module(Module* m, char lvl, bool doinline)
{ {
assert(lvl >= 0 && lvl <= 5); assert(lvl >= 0 && lvl <= 5);
if (lvl == 0)
return;
PassManager pm; PassManager pm;
pm.add(new TargetData(m)); pm.add(new TargetData(m));
@ -24,12 +22,12 @@ void llvmdc_optimize_module(Module* m, char lvl, bool doinline)
pm.add(createRaiseAllocationsPass()); pm.add(createRaiseAllocationsPass());
pm.add(createCFGSimplificationPass()); pm.add(createCFGSimplificationPass());
pm.add(createPromoteMemoryToRegisterPass()); pm.add(createPromoteMemoryToRegisterPass());
pm.add(createGlobalOptimizerPass());
pm.add(createGlobalDCEPass());
} }
if (lvl >= 2) if (lvl >= 2)
{ {
pm.add(createGlobalOptimizerPass());
pm.add(createGlobalDCEPass());
pm.add(createIPConstantPropagationPass()); pm.add(createIPConstantPropagationPass());
pm.add(createDeadArgEliminationPass()); pm.add(createDeadArgEliminationPass());
pm.add(createInstructionCombiningPass()); pm.add(createInstructionCombiningPass());
@ -77,5 +75,6 @@ void llvmdc_optimize_module(Module* m, char lvl, bool doinline)
// level 4 and 5 are linktime optimizations // level 4 and 5 are linktime optimizations
pm.run(*m); if (lvl > 0 || doinline)
pm.run(*m);
} }

View file

@ -1824,6 +1824,18 @@ DValue* NewExp::toElem(IRState* p)
idx += tc->sym->llvmIRStruct->interfaces.size(); idx += tc->sym->llvmIRStruct->interfaces.size();
DtoStore(thisval->getRVal(), DtoGEPi(emem,0,idx,"tmp")); 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 // then call constructor
if (arguments) { if (arguments) {

View file

@ -796,64 +796,143 @@ llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expressio
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* DtoNestedVariable(VarDeclaration* vd) static void print_frame_worker(VarDeclaration* var, Dsymbol* par)
{ {
FuncDeclaration* fd = vd->toParent()->isFuncDeclaration(); if (var->toParent2() == par)
assert(fd != NULL); {
Logger::println("parent found: '%s' kind: '%s'", par->toChars(), par->kind());
return;
}
IRFunction* fcur = gIR->func(); Logger::println("diving into parent: '%s' kind: '%s'", par->toChars(), par->kind());
FuncDeclaration* f = fcur->decl; LOG_SCOPE;
print_frame_worker(var, par->toParent2());
}
// on this stack static void print_nested_frame_list(VarDeclaration* var, Dsymbol* par)
if (fd == f) { {
llvm::Value* vdv = vd->llvmValue; Logger::println("PRINTING FRAME LIST FOR NESTED VAR: '%s'", var->toChars());
if (!vdv) {
{ LOG_SCOPE;
Logger::println(":o null vd->llvmValue for: %s", vd->toChars()); print_frame_worker(var, par);
vdv = fd->llvmNested; }
assert(vdv); Logger::println("DONE");
} }
assert(vd->llvmNestedIndex != ~0);
llvm::Value* v = DtoGEPi(vdv,0,unsigned(vd->llvmNestedIndex),"tmp"); static const llvm::Type* get_next_frame_ptr_type(Dsymbol* sc)
if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) { {
Logger::cout() << "1267 loading: " << *v << '\n'; assert(sc->isFuncDeclaration() || sc->isClassDeclaration());
v = gIR->ir->CreateLoad(v,"tmp"); 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; 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';
// on a caller stack if (fd->toParent2() == vd->toParent2())
llvm::Value* ptr = f->llvmThisVar; 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); assert(ptr);
f = f->toParent()->isFuncDeclaration(); // return the fully resolved frame pointer
assert(f); ptr = get_frame_ptr_impl(vd, irfunc->decl, ptr);
assert(f->llvmNested); Logger::cout() << "FOUND: '" << *ptr << "'\n";
const llvm::Type* nesttype = f->llvmNested->getType();
assert(nesttype);
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) { // resolve frame ptr
if (fd == f) { llvm::Value* ptr = get_frame_ptr(vd);
llvm::Value* v = DtoGEPi(ptr,0,vd->llvmNestedIndex,"tmp"); Logger::cout() << "nested ptr = " << *ptr << '\n';
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();
}
assert(0 && "nested var not found"); // we must cast here to be sure. nested classes just have a void*
return NULL; ptr = DtoBitCast(ptr, vd->toParent2()->isFuncDeclaration()->llvmNested->getType());
// 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;
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////

View file

@ -138,7 +138,7 @@ void Module::genobjfile()
// run optimizer // run optimizer
if (global.params.optimize) { 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 // write bytecode

View file

@ -259,6 +259,7 @@ test/arrays7.d
test/arrays8.d test/arrays8.d
test/arrays9.d test/arrays9.d
test/assign.d test/assign.d
test/ast1.d
test/b.d test/b.d
test/bitops.d test/bitops.d
test/bug1.d test/bug1.d
@ -336,6 +337,7 @@ test/bug9.d
test/c.d test/c.d
test/classes.d test/classes.d
test/classes10.d test/classes10.d
test/classes11.d
test/classes2.d test/classes2.d
test/classes3.d test/classes3.d
test/classes4.d test/classes4.d
@ -406,9 +408,15 @@ test/multiarr3.d
test/multiarr4.d test/multiarr4.d
test/neg.d test/neg.d
test/nested1.d test/nested1.d
test/nested10.d
test/nested2.d test/nested2.d
test/nested3.d test/nested3.d
test/nested4.d test/nested4.d
test/nested5.d
test/nested6.d
test/nested7.d
test/nested8.d
test/nested9.d
test/pointers.d test/pointers.d
test/pt.d test/pt.d
test/ptrarith.d test/ptrarith.d

View file

@ -11,4 +11,9 @@ int find(char[] s, dchar c)
void main() void main()
{ {
} char[] hello = "hello world";
int i = find(hello, 'w');
assert(i == 6);
i = find(hello, 'z');
assert(i == -1);
}

20
test/nested10.d Normal file
View file

@ -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);
}

View file

@ -11,9 +11,11 @@ void main()
void func() void func()
{ {
printf("Hello world %d\n", i++); printf("Hello world %d\n", i++);
//i++;
} }
} }
scope c = new C; scope c = new C;
c.func(); c.func();
assert(i == 44);
} }

View file

@ -4,19 +4,19 @@ void main()
{ {
int i = 42; int i = 42;
printf("Hello world %d\n", i++); printf("main() %d\n", i++);
class C class C
{ {
void func() void func()
{ {
printf("Hello world %d\n", i++); printf("C.func() %d\n", i++);
class C2 class C2
{ {
void func2() void func2()
{ {
printf("Hello world %d\n", i++); printf("C2.func2() %d\n", i++);
} }
} }

32
test/nested7.d Normal file
View file

@ -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);
}

30
test/nested8.d Normal file
View file

@ -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);
}

13
test/nested9.d Normal file
View file

@ -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);
}