From 14bc59f31a84bef64b4e068026441d8c7e7ef012 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 12 Sep 2013 08:54:39 +0200 Subject: [PATCH 1/5] Nested context creation code beautification. --- gen/nested.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/gen/nested.cpp b/gen/nested.cpp index cf961bd6..d45b47d0 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -203,7 +203,10 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) Logger::println("DtoNestedContext for %s", sym->toPrettyChars()); LOG_SCOPE; + // The function we are currently in, and the constructed object/called + // function might inherit a context pointer from. IrFunction* irfunc = gIR->func(); + bool fromParent = true; LLValue* val; @@ -237,28 +240,27 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) return llvm::ConstantPointerNull::get(getVoidPtrType()); } - struct FuncDeclaration* fd = 0; - if (AggregateDeclaration *ad = sym->isAggregateDeclaration()) + struct FuncDeclaration* frameToPass = 0; + if (AggregateDeclaration *ad = sym->isAggregateDeclaration()) { // If sym is a nested struct or a nested class, pass the frame // of the function where sym is declared. - fd = ad->toParent()->isFuncDeclaration(); - else - if (FuncDeclaration* symfd = sym->isFuncDeclaration()) { + frameToPass = ad->toParent()->isFuncDeclaration(); + } else if (FuncDeclaration* symfd = sym->isFuncDeclaration()) { // Make sure we've had a chance to analyze nested context usage DtoCreateNestedContextType(symfd); // if this is for a function that doesn't access variables from // enclosing scopes, it doesn't matter what we pass. - // Tell LLVM about it by passing an 'undef'. - if (symfd && symfd->ir.irFunc->depth == -1) + if (symfd->ir.irFunc->depth == -1) return llvm::UndefValue::get(getVoidPtrType()); - // If sym is a nested function, and it's parent context is different than the - // one we got, adjust it. - fd = getParentFunc(symfd, true); + // If sym is a nested function, and its parent context is different + // than the one we got, adjust it. + frameToPass = getParentFunc(symfd, true); } - if (fd) { - Logger::println("For nested function, parent is %s", fd->toChars()); + + if (frameToPass) { + Logger::println("Parent frame is from %s", frameToPass->toChars()); FuncDeclaration* ctxfd = irfunc->decl; Logger::println("Current function is %s", ctxfd->toChars()); if (fromParent) { @@ -267,7 +269,7 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) } Logger::println("Context is from %s", ctxfd->toChars()); - unsigned neededDepth = fd->ir.irFunc->depth; + unsigned neededDepth = frameToPass->ir.irFunc->depth; unsigned ctxDepth = ctxfd->ir.irFunc->depth; Logger::cout() << "Needed depth: " << neededDepth << '\n'; @@ -280,7 +282,8 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) } else { val = DtoBitCast(val, LLPointerType::getUnqual(ctxfd->ir.irFunc->frameType)); val = DtoGEPi(val, 0, neededDepth); - val = DtoAlignedLoad(val, (std::string(".frame.") + fd->toChars()).c_str()); + val = DtoAlignedLoad(val, + (std::string(".frame.") + frameToPass->toChars()).c_str()); } } From 90127ab87a74a02a45ea7ae76e16a3fa89de3536 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 12 Sep 2013 10:21:01 +0200 Subject: [PATCH 2/5] Fix broken indentation in debug log output. --- gen/toir.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 7a6200d3..01546ff9 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -377,7 +377,10 @@ DValue* StringExp::toElem(IRState* p) llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage; if (Logger::enabled()) - Logger::cout() << "type: " << *at << "\ninit: " << *_init << '\n'; + { + Logger::cout() << "type: " << *at << '\n'; + Logger::cout() << "init: " << *_init << '\n'; + } llvm::GlobalVariable* gvar = new llvm::GlobalVariable(*gIR->module, at, true, _linkage, _init, ".str"); gvar->setUnnamedAddr(true); From 0063546bc3485e33a5ed0e4327a4b96428a7659d Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 12 Sep 2013 10:23:21 +0200 Subject: [PATCH 3/5] Added newline at end of file. --- gen/dibuilder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/dibuilder.h b/gen/dibuilder.h index 27d9e854..712391a4 100644 --- a/gen/dibuilder.h +++ b/gen/dibuilder.h @@ -190,4 +190,4 @@ public: } // namespace ldc -#endif \ No newline at end of file +#endif From e5463f77b7d87ad0581819acc64893cbf1ecf448 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 12 Sep 2013 13:46:45 +0200 Subject: [PATCH 4/5] FuncDeclaration::nestedVars should only be filled in DtoCreateNestedContextType. --- gen/nested.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/gen/nested.cpp b/gen/nested.cpp index d45b47d0..5aee6af4 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -302,14 +302,13 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) { return; fd->ir.irFunc->nestedContextCreated = true; - if (fd->nestedVars.empty()) { - // fill nestedVars - size_t nnest = fd->closureVars.dim; - for (size_t i = 0; i < nnest; ++i) - { - VarDeclaration* vd = static_cast(fd->closureVars.data[i]); - fd->nestedVars.insert(vd); - } + // fill nestedVars + assert(fd->nestedVars.empty() && "nestedVars should only be filled here"); + size_t nnest = fd->closureVars.dim; + for (size_t i = 0; i < nnest; ++i) + { + VarDeclaration* vd = static_cast(fd->closureVars.data[i]); + fd->nestedVars.insert(vd); } // construct nested variables array From 243146199fac706e8314cedaf4a2011bc614f6b6 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 12 Sep 2013 13:47:54 +0200 Subject: [PATCH 5/5] Function literals start again at nesting depth zero. GitHub: Fixes #447. --- gen/nested.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gen/nested.cpp b/gen/nested.cpp index 5aee6af4..fe79627d 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -319,7 +319,13 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) { LLStructType* innerFrameType = NULL; unsigned depth = -1; - if (!fd->isStatic()) { + + // Static functions and function (not delegate) literals don't allow + // access to a parent context, even if they are nested. + const bool certainlyNewRoot = fd->isStatic() || + (fd->isFuncLiteralDeclaration() && + static_cast(fd)->tok == TOKfunction); + if (!certainlyNewRoot) { if (FuncDeclaration* parfd = getParentFunc(fd, true)) { // Make sure the parent has already been analyzed. DtoCreateNestedContextType(parfd);