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.
This commit is contained in:
Frits van Bommel 2009-04-17 13:50:01 +02:00
parent 0262a6ec8f
commit 46565f1adc
3 changed files with 40 additions and 33 deletions

View file

@ -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,16 +238,19 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
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* symfd = sym->isFuncDeclaration()) {
// Make sure we've had a chance to analyze nested context usage
DtoDefineFunction(symfd);
if (FuncDeclaration* fd = getParentFunc(sym->isFuncDeclaration(), true)) {
// 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());
// 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());
@ -273,6 +277,7 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
}
}
}
}
Logger::cout() << "result = " << *val << '\n';
Logger::cout() << "of type " << *val->getType() << '\n';
return val;
@ -376,15 +381,15 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
// 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';

View file

@ -112,7 +112,7 @@ IrFunction::IrFunction(FuncDeclaration* fd)
nestedVar = NULL;
frameType = NULL;
depth = 0;
depth = -1;
_arguments = NULL;
_argptr = NULL;

View file

@ -46,7 +46,9 @@ struct IrFunction : IrBase
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;