From e7c880cd0823709a2bd065a8df264a87bbbfb380 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Sun, 19 Dec 2010 12:13:00 +0300 Subject: [PATCH] Store the right context frame in nested structs and classes. --- gen/nested.cpp | 53 +++++++++++++++++++++++++++++--------------------- gen/toir.cpp | 6 ++++++ 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/gen/nested.cpp b/gen/nested.cpp index 2366cc5b..a55c1dba 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -289,6 +289,14 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) return llvm::UndefValue::get(getVoidPtrType()); } if (nestedCtx == NCHybrid) { + class FuncDeclaration* fd = 0; + #if DMDV2 + 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 + #endif if (FuncDeclaration* symfd = sym->isFuncDeclaration()) { // Make sure we've had a chance to analyze nested context usage #if DMDV2 @@ -305,31 +313,32 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) // If sym is a nested function, and it's parent context is different than the // one we got, adjust it. - if (FuncDeclaration* fd = getParentFunc(symfd, true)) { - Logger::println("For nested function, parent is %s", fd->toChars()); - FuncDeclaration* ctxfd = irfunc->decl; - Logger::println("Current function is %s", ctxfd->toChars()); - if (fromParent) { - ctxfd = getParentFunc(ctxfd, true); - assert(ctxfd && "Context from outer function, but no outer function?"); - } - Logger::println("Context is from %s", ctxfd->toChars()); + fd = getParentFunc(symfd, true); + } + if (fd) { + Logger::println("For nested function, parent is %s", fd->toChars()); + FuncDeclaration* ctxfd = irfunc->decl; + Logger::println("Current function is %s", ctxfd->toChars()); + if (fromParent) { + ctxfd = getParentFunc(ctxfd, true); + assert(ctxfd && "Context from outer function, but no outer function?"); + } + Logger::println("Context is from %s", ctxfd->toChars()); - unsigned neededDepth = fd->ir.irFunc->depth; - unsigned ctxDepth = ctxfd->ir.irFunc->depth; + unsigned neededDepth = fd->ir.irFunc->depth; + unsigned ctxDepth = ctxfd->ir.irFunc->depth; - Logger::cout() << "Needed depth: " << neededDepth << '\n'; - Logger::cout() << "Context depth: " << ctxDepth << '\n'; + Logger::cout() << "Needed depth: " << neededDepth << '\n'; + Logger::cout() << "Context depth: " << ctxDepth << '\n'; - if (neededDepth >= ctxDepth) { - // assert(neededDepth <= ctxDepth + 1 && "How are we going more than one nesting level up?"); - // fd needs the same context as we do, so all is well - Logger::println("Calling sibling function or directly nested function"); - } 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()); - } + if (neededDepth >= ctxDepth) { + // assert(neededDepth <= ctxDepth + 1 && "How are we going more than one nesting level up?"); + // fd needs the same context as we do, so all is well + Logger::println("Calling sibling function or directly nested function"); + } 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()); } } } diff --git a/gen/toir.cpp b/gen/toir.cpp index 3aeaef49..193f8872 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2597,6 +2597,12 @@ DValue* StructLiteralExp::toElem(IRState* p) IF_LOG Logger::println("expr %zu = %s", it.index, expr->toChars()); val = expr->toElem(gIR); } +#if DMDV2 + else if (vd == sd->vthis) { + IF_LOG Logger::println("initializing vthis"); + val = new DImValue(sd->type, DtoNestedContext(loc, sd)); + } +#endif else { IF_LOG Logger::println("using default initializer");