diff --git a/gen/nested.cpp b/gen/nested.cpp index cf961bd6..fe79627d 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()); } } @@ -299,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 @@ -317,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); 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);