Mercurial > projects > ldc
changeset 1223:5f340a6dc749
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.
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Fri, 17 Apr 2009 13:50:01 +0200 |
parents | b6370749ec8d |
children | 919fafcc505c 6ef97d65ca60 |
files | gen/nested.cpp ir/irfunction.cpp ir/irfunction.h |
diffstat | 3 files changed, 40 insertions(+), 33 deletions(-) [+] |
line wrap: on
line diff
--- 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';
--- 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;
--- 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;