From feea94424c27357cfbc54ffc3c600ac5b7440c93 Mon Sep 17 00:00:00 2001 From: Tomas Lindquist Olsen Date: Sun, 28 Oct 2007 02:46:06 +0200 Subject: [PATCH] [svn r71] Fixed accessing parent function arguments from inside nested delegates. Some cleanups in VarExp::toElem. --- gen/toir.c | 108 +++++++++++++++++-------------------------------- gen/tollvm.c | 10 ++++- gen/toobj.c | 14 ++++++- test/nested1.d | 13 ++++++ test/nested2.d | 16 ++++++++ 5 files changed, 87 insertions(+), 74 deletions(-) create mode 100644 test/nested1.d create mode 100644 test/nested2.d diff --git a/gen/toir.c b/gen/toir.c index 6c555d43..d16473fe 100644 --- a/gen/toir.c +++ b/gen/toir.c @@ -113,10 +113,6 @@ elem* VarExp::toElem(IRState* p) { Logger::println("VarDeclaration %s", vd->toChars()); - if (vd->nestedref) { - Logger::println("has nested ref"); - } - // _arguments if (vd->ident == Id::_arguments) { @@ -124,7 +120,6 @@ elem* VarExp::toElem(IRState* p) assert(vd->llvmValue); e->mem = vd->llvmValue; e->type = elem::VAR; - return e; } // _argptr else if (vd->ident == Id::_argptr) @@ -133,54 +128,39 @@ elem* VarExp::toElem(IRState* p) assert(vd->llvmValue); e->mem = vd->llvmValue; e->type = elem::VAR; - return e; } - - // needed to take care of forward references of global variables - if (!vd->llvmTouched && vd->isDataseg()) - vd->toObjFile(); - - if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) + // _dollar + else if (vd->ident == Id::dollar) + { + assert(!p->arrays.empty()); + llvm::Value* tmp = LLVM_DtoGEPi(p->arrays.back(),0,0,"tmp",p->scopebb()); + e->val = new llvm::LoadInst(tmp,"tmp",p->scopebb()); + e->type = elem::VAL; + } + // typeinfo + else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) { Logger::println("TypeInfoDeclaration"); + tid->toObjFile(); + assert(tid->llvmValue); + const llvm::Type* vartype = LLVM_DtoType(type); + if (tid->llvmValue->getType() != llvm::PointerType::get(vartype)) + e->mem = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp"); + else + e->mem = tid->llvmValue; + e->type = elem::VAR; } - - // this must be a dollar expression or some other magic value - // or it could be a forward declaration of a global variable - if (!vd->llvmValue) - { - assert(!vd->nestedref); - Logger::println("special - no llvmValue"); - // dollar - if (!p->arrays.empty()) - { - llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); - //llvm::Value* tmp = new llvm::GetElementPtrInst(p->arrays.back(),zero,zero,"tmp",p->scopebb()); - llvm::Value* tmp = LLVM_DtoGEP(p->arrays.back(),zero,zero,"tmp",p->scopebb()); - e->val = new llvm::LoadInst(tmp,"tmp",p->scopebb()); - e->type = elem::VAL; - } - // typeinfo - else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) - { - tid->toObjFile(); - assert(tid->llvmValue); - e->val = tid->llvmValue; - e->type = elem::VAR; - } - // global forward ref - else { - Logger::println("unsupported magic: %s\n", vd->toChars()); - assert(0 && "only magic supported is $, _arguments, _argptr"); - } - return e; + // nested variable + else if (vd->nestedref) { + e->mem = LLVM_DtoNestedVariable(vd); + e->type = elem::VAR; + e->vardecl = vd; } - // function parameter - if (vd->storage_class & STCparameter) { - assert(!vd->nestedref); + else if (vd->isParameter()) { Logger::println("function param"); - if (vd->storage_class & (STCref | STCout)) { + assert(vd->llvmValue); + if (vd->isRef() || vd->isOut()) { e->mem = vd->llvmValue; e->type = elem::VAR; } @@ -205,30 +185,16 @@ elem* VarExp::toElem(IRState* p) } } else { - // nested variable - if (vd->nestedref) { - e->mem = LLVM_DtoNestedVariable(vd); - } - // normal local variable - else { - if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) { - Logger::println("typeinfo varexp"); - const llvm::Type* vartype = LLVM_DtoType(type); - if (tid->llvmValue->getType() != llvm::PointerType::get(vartype)) { - e->mem = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp"); - } - else { - e->mem = tid->llvmValue; - } - Logger::cout() << "got:" << '\n' << *tid->llvmValue << "returned:" << '\n' << *e->mem << '\n'; - } - else { - e->mem = vd->llvmValue; - } - } + // take care of forward references of global variables + if (!vd->llvmTouched && vd->isDataseg()) + vd->toObjFile(); + assert(vd->llvmValue); + e->mem = vd->llvmValue; e->vardecl = vd; e->type = elem::VAR; } + + assert(e->mem || e->val); } else if (FuncDeclaration* fdecl = var->isFuncDeclaration()) { @@ -238,7 +204,6 @@ elem* VarExp::toElem(IRState* p) e->val = fdecl->llvmValue; e->type = elem::FUNC; e->funcdecl = fdecl; - return e; } else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration()) { @@ -256,7 +221,6 @@ elem* VarExp::toElem(IRState* p) assert(0 && "Unimplemented VarExp type"); } - assert(e->mem || e->val); return e; } @@ -1260,10 +1224,12 @@ elem* CallExp::toElem(IRState* p) call->setCallingConv(LLVM_DtoCallingConv(dlink)); } } - else if (delegateCall) + else if (delegateCall) { call->setCallingConv(LLVM_DtoCallingConv(dlink)); - else if (fn->callconv != (unsigned)-1) + } + else if (fn->callconv != (unsigned)-1) { call->setCallingConv(fn->callconv); + } delete fn; return e; diff --git a/gen/tollvm.c b/gen/tollvm.c index ca5c883e..2cd7e95b 100644 --- a/gen/tollvm.c +++ b/gen/tollvm.c @@ -1306,7 +1306,10 @@ llvm::Value* LLVM_DtoNestedVariable(VarDeclaration* vd) // on this stack if (fd == f) { - return LLVM_DtoGEPi(vd->llvmValue,0,unsigned(vd->llvmNestedIndex),"tmp"); + llvm::Value* v = LLVM_DtoGEPi(vd->llvmValue,0,unsigned(vd->llvmNestedIndex),"tmp"); + if (vd->isParameter() && (vd->isRef() || vd->isOut())) + v = gIR->ir->CreateLoad(v,"tmp"); + return v; } // on a caller stack @@ -1325,7 +1328,10 @@ llvm::Value* LLVM_DtoNestedVariable(VarDeclaration* vd) while (f) { if (fd == f) { - return LLVM_DtoGEPi(ptr,0,vd->llvmNestedIndex,"tmp"); + llvm::Value* v = LLVM_DtoGEPi(ptr,0,vd->llvmNestedIndex,"tmp"); + if (vd->isParameter() && (vd->isRef() || vd->isOut())) + v = gIR->ir->CreateLoad(v,"tmp"); + return v; } else { ptr = LLVM_DtoGEPi(ptr,0,0,"tmp"); diff --git a/gen/toobj.c b/gen/toobj.c index 8bf5fda7..24621a62 100644 --- a/gen/toobj.c +++ b/gen/toobj.c @@ -769,7 +769,13 @@ void FuncDeclaration::toObjFile() for (std::set::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) { VarDeclaration* vd = *i; vd->llvmNestedIndex = j++; - nestTypes.push_back(LLVM_DtoType(vd->type)); + if (vd->isParameter()) { + assert(vd->llvmValue); + nestTypes.push_back(vd->llvmValue->getType()); + } + else { + nestTypes.push_back(LLVM_DtoType(vd->type)); + } } const llvm::StructType* nestSType = llvm::StructType::get(nestTypes); Logger::cout() << "nested var struct has type:" << '\n' << *nestSType; @@ -779,6 +785,12 @@ void FuncDeclaration::toObjFile() llvm::Value* ptr = gIR->ir->CreateBitCast(llvmThisVar, parentNested->getType(), "tmp"); gIR->ir->CreateStore(ptr, LLVM_DtoGEPi(llvmNested, 0,0, "tmp")); } + for (std::set::iterator i=llvmNestedVars.begin(); i!=llvmNestedVars.end(); ++i) { + VarDeclaration* vd = *i; + if (vd->isParameter()) { + gIR->ir->CreateStore(vd->llvmValue, LLVM_DtoGEPi(llvmNested, 0, vd->llvmNestedIndex, "tmp")); + } + } } // copy _argptr to a memory location diff --git a/test/nested1.d b/test/nested1.d new file mode 100644 index 00000000..a08a9a53 --- /dev/null +++ b/test/nested1.d @@ -0,0 +1,13 @@ +module nested1; + +void func(int i) +{ + (){ + assert(i == 3); + }(); +} + +void main() +{ + func(3); +} diff --git a/test/nested2.d b/test/nested2.d new file mode 100644 index 00000000..e707ac4d --- /dev/null +++ b/test/nested2.d @@ -0,0 +1,16 @@ +module nested2; + +void func(ref int i) +{ + delegate { + assert(i == 3); + i++; + }(); +} + +void main() +{ + int i = 3; + func(i); + assert(i == 4); +}