# HG changeset patch # User Frits van Bommel # Date 1239969001 -7200 # Node ID 5f340a6dc749091f804d485035b9157a6d341af1 # Parent b6370749ec8de8b0aba61dcdf0f630391244cb24 Fix nested functions. My last patch was a little over-zealous in passing `undef`, it always passed `undef` to inner functions expecting a single context frame. diff -r b6370749ec8d -r 5f340a6dc749 gen/nested.cpp --- a/gen/nested.cpp Fri Apr 17 03:47:56 2009 +0200 +++ b/gen/nested.cpp Fri Apr 17 13:50:01 2009 +0200 @@ -5,6 +5,7 @@ #include "gen/llvmhelpers.h" #include "gen/logger.h" #include "gen/tollvm.h" +#include "gen/functions.h" #include "llvm/Support/CommandLine.h" namespace cl = llvm::cl; @@ -237,39 +238,43 @@ return llvm::UndefValue::get(getVoidPtrType()); } if (nestedCtx == NCHybrid) { - // If sym is a nested function, and it's parent context is different than the - // one we got, adjust it. - - if (FuncDeclaration* fd = getParentFunc(sym->isFuncDeclaration(), true)) { + if (FuncDeclaration* symfd = sym->isFuncDeclaration()) { + // Make sure we've had a chance to analyze nested context usage + DtoDefineFunction(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 (fd->ir.irFunc->depth == 0) + if (symfd && symfd->ir.irFunc->depth == -1) return llvm::UndefValue::get(getVoidPtrType()); - 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; - - 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 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()); + + unsigned neededDepth = fd->ir.irFunc->depth; + unsigned ctxDepth = ctxfd->ir.irFunc->depth; + + 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()); + } } } } @@ -376,15 +381,15 @@ // start with adding all enclosing parent frames until a static parent is reached const LLStructType* innerFrameType = NULL; - unsigned depth = 0; + unsigned depth = -1; if (!fd->isStatic()) { if (FuncDeclaration* parfd = getParentFunc(fd, true)) { innerFrameType = parfd->ir.irFunc->frameType; if (innerFrameType) - depth = parfd->ir.irFunc->depth + 1; + depth = parfd->ir.irFunc->depth; } } - fd->ir.irFunc->depth = depth; + fd->ir.irFunc->depth = ++depth; Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n'; diff -r b6370749ec8d -r 5f340a6dc749 ir/irfunction.cpp --- a/ir/irfunction.cpp Fri Apr 17 03:47:56 2009 +0200 +++ b/ir/irfunction.cpp Fri Apr 17 13:50:01 2009 +0200 @@ -112,7 +112,7 @@ nestedVar = NULL; frameType = NULL; - depth = 0; + depth = -1; _arguments = NULL; _argptr = NULL; diff -r b6370749ec8d -r 5f340a6dc749 ir/irfunction.h --- a/ir/irfunction.h Fri Apr 17 03:47:56 2009 +0200 +++ b/ir/irfunction.h Fri Apr 17 13:50:01 2009 +0200 @@ -46,7 +46,9 @@ llvm::Value* nestedVar; // nested var alloca const llvm::StructType* frameType; // type of nested context (not for -nested-ctx=array) - unsigned depth; // number of enclosing functions with variables accessed by nested functions + // number of enclosing functions with variables accessed by nested functions + // (-1 if neither this function nor any enclosing ones access variables from enclosing functions) + int depth; llvm::Value* _arguments; llvm::Value* _argptr;