mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-08 20:06:03 +03:00
[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:
parent
f420bc1265
commit
5eb88f9e80
17 changed files with 263 additions and 59 deletions
|
@ -606,6 +606,7 @@ struct FuncDeclaration : Declaration
|
|||
|
||||
FuncDeclaration *isFuncDeclaration() { return this; }
|
||||
|
||||
// llvmdc stuff
|
||||
bool llvmQueued;
|
||||
llvm::Value* llvmThisVar;
|
||||
std::set<VarDeclaration*> llvmNestedVars;
|
||||
|
|
|
@ -247,7 +247,7 @@ int runLINK()
|
|||
argv.push((void*)s);
|
||||
}
|
||||
|
||||
if (!global.params.useInline) {
|
||||
if (!(global.params.useInline || global.params.llvmInline)) {
|
||||
argv.push((void *)"-disable-inlining");
|
||||
}
|
||||
|
||||
|
|
|
@ -264,6 +264,7 @@ int main(int argc, char *argv[])
|
|||
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 @@ int main(int argc, char *argv[])
|
|||
#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;
|
||||
|
|
|
@ -129,6 +129,7 @@ struct Param
|
|||
char *tt_os;
|
||||
char *data_layout;
|
||||
char disassemble;
|
||||
char llvmInline;
|
||||
};
|
||||
|
||||
struct Global
|
||||
|
|
|
@ -540,7 +540,7 @@ void DtoDefineFunc(FuncDeclaration* fd)
|
|||
}
|
||||
}
|
||||
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);
|
||||
|
|
|
@ -13,8 +13,6 @@ using namespace llvm;
|
|||
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 @@ void llvmdc_optimize_module(Module* m, char lvl, bool doinline)
|
|||
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 @@ void llvmdc_optimize_module(Module* m, char lvl, bool doinline)
|
|||
|
||||
// level 4 and 5 are linktime optimizations
|
||||
|
||||
if (lvl > 0 || doinline)
|
||||
pm.run(*m);
|
||||
}
|
||||
|
|
12
gen/toir.cpp
12
gen/toir.cpp
|
@ -1824,6 +1824,18 @@ DValue* NewExp::toElem(IRState* p)
|
|||
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) {
|
||||
|
|
169
gen/tollvm.cpp
169
gen/tollvm.cpp
|
@ -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();
|
||||
assert(fd != NULL);
|
||||
|
||||
IRFunction* fcur = gIR->func();
|
||||
FuncDeclaration* f = fcur->decl;
|
||||
|
||||
// on this stack
|
||||
if (fd == f) {
|
||||
llvm::Value* vdv = vd->llvmValue;
|
||||
if (!vdv)
|
||||
if (var->toParent2() == par)
|
||||
{
|
||||
Logger::println(":o null vd->llvmValue for: %s", vd->toChars());
|
||||
vdv = fd->llvmNested;
|
||||
assert(vdv);
|
||||
Logger::println("parent found: '%s' kind: '%s'", par->toChars(), par->kind());
|
||||
return;
|
||||
}
|
||||
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");
|
||||
|
||||
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';
|
||||
|
||||
// on a caller stack
|
||||
llvm::Value* ptr = f->llvmThisVar;
|
||||
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");
|
||||
}
|
||||
// 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());
|
||||
|
||||
// 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;
|
||||
}
|
||||
else {
|
||||
ptr = DtoGEPi(ptr,0,0,"tmp");
|
||||
ptr = gIR->ir->CreateLoad(ptr,"tmp");
|
||||
}
|
||||
f = f->toParent()->isFuncDeclaration();
|
||||
}
|
||||
|
||||
assert(0 && "nested var not found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -138,7 +138,7 @@ void Module::genobjfile()
|
|||
|
||||
// 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
|
||||
|
|
|
@ -259,6 +259,7 @@ test/arrays7.d
|
|||
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/bug9.d
|
|||
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/multiarr3.d
|
|||
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
|
||||
|
|
|
@ -11,4 +11,9 @@ int find(char[] s, dchar c)
|
|||
|
||||
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
20
test/nested10.d
Normal 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);
|
||||
}
|
|
@ -11,9 +11,11 @@ void main()
|
|||
void func()
|
||||
{
|
||||
printf("Hello world %d\n", i++);
|
||||
//i++;
|
||||
}
|
||||
}
|
||||
|
||||
scope c = new C;
|
||||
c.func();
|
||||
assert(i == 44);
|
||||
}
|
||||
|
|
|
@ -4,19 +4,19 @@ void main()
|
|||
{
|
||||
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++);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
32
test/nested7.d
Normal file
32
test/nested7.d
Normal 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
30
test/nested8.d
Normal 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
13
test/nested9.d
Normal 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);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue