# HG changeset patch # User Tomas Lindquist Olsen # Date 1239972517 -7200 # Node ID 6ef97d65ca605a4c35216f9ed0cea252e761e7b7 # Parent 465a77c904d4bd223ab103ee26c23fe21797d433# Parent 5f340a6dc749091f804d485035b9157a6d341af1 Merge. diff -r 465a77c904d4 -r 6ef97d65ca60 gen/nested.cpp --- a/gen/nested.cpp Fri Apr 17 14:38:29 2009 +0200 +++ b/gen/nested.cpp Fri Apr 17 14:48:37 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; @@ -228,42 +229,52 @@ { ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration(); if (!cd || !cd->vthis) - return getNullPtr(getVoidPtrType()); + return llvm::UndefValue::get(getVoidPtrType()); val = DtoLoad(irfunc->thisArg); val = DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis")); } else { - return getNullPtr(getVoidPtrType()); + 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)) { - 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()); + 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 (symfd && symfd->ir.irFunc->depth == -1) + return llvm::UndefValue::get(getVoidPtrType()); - 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()); + } } } } @@ -370,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 465a77c904d4 -r 6ef97d65ca60 ir/irfunction.cpp --- a/ir/irfunction.cpp Fri Apr 17 14:38:29 2009 +0200 +++ b/ir/irfunction.cpp Fri Apr 17 14:48:37 2009 +0200 @@ -112,7 +112,7 @@ nestedVar = NULL; frameType = NULL; - depth = 0; + depth = -1; _arguments = NULL; _argptr = NULL; diff -r 465a77c904d4 -r 6ef97d65ca60 ir/irfunction.h --- a/ir/irfunction.h Fri Apr 17 14:38:29 2009 +0200 +++ b/ir/irfunction.h Fri Apr 17 14:48:37 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;