Add an option to change the way nested variables are handled.

Only one value is implemented, which is the old way.
This commit is contained in:
Frits van Bommel 2009-04-12 16:22:21 +02:00
parent b5af30636e
commit 8820024070

View file

@ -6,6 +6,42 @@
#include "gen/logger.h" #include "gen/logger.h"
#include "gen/tollvm.h" #include "gen/tollvm.h"
#include "llvm/Support/CommandLine.h"
namespace cl = llvm::cl;
/// What the context pointer for a nested function looks like
enum NestedCtxType {
/// Context is void*[] of pointers to variables.
/// Variables from higher levels are at the front.
NCArray,
/// Context is a struct containing variables belonging to the parent function.
/// If the parent function itself has a parent function, one of the members is
/// a pointer to its context. (linked-list style)
// FIXME: implement
// TODO: Functions without any variables accessed by nested functions, but
// with a parent whose variables are accessed, can use the parent's
// context.
NCStruct,
/// Context is an array of pointers to nested contexts. Each function with variables
/// accessed by nested functions puts them in a struct, and appends a pointer to that
/// struct to the array.
// FIXME: implement
NCHybrid
};
static cl::opt<NestedCtxType> nestedCtx("nested-ctx",
cl::desc("How to construct a nested function's context:"),
cl::ZeroOrMore,
cl::values(
clEnumValN(NCArray, "array", "Array of pointers to variables (including multi-level)"),
//clEnumValN(NCStruct, "struct", "Struct of variables (with multi-level via linked list)"),
//clEnumValN(NCHybrid, "hybrid", "Array of pointers to structs of variables"),
clEnumValEnd),
cl::init(NCArray));
/****************************************************************************************/ /****************************************************************************************/
/*//////////////////////////////////////////////////////////////////////////////////////// /*////////////////////////////////////////////////////////////////////////////////////////
// NESTED VARIABLE HELPERS // NESTED VARIABLE HELPERS
@ -13,6 +49,9 @@
DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd) DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
{ {
////////////////////////////////////
// Locate context value
Dsymbol* vdparent = vd->toParent2(); Dsymbol* vdparent = vd->toParent2();
assert(vdparent); assert(vdparent);
@ -25,7 +64,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
return new DVarValue(astype, vd, val); return new DVarValue(astype, vd, val);
} }
// get it from the nested context // get the nested context
LLValue* ctx = 0; LLValue* ctx = 0;
if (irfunc->decl->isMember2()) if (irfunc->decl->isMember2())
{ {
@ -38,16 +77,26 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
assert(ctx); assert(ctx);
assert(vd->ir.irLocal); assert(vd->ir.irLocal);
////////////////////////////////////
// Extract variable from nested context
if (nestedCtx == NCArray) {
LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType())); LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType()));
val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex); val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex);
val = DtoLoad(val); val = DtoLoad(val);
assert(vd->ir.irLocal->value); assert(vd->ir.irLocal->value);
val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars()); val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars());
return new DVarValue(astype, vd, val); return new DVarValue(astype, vd, val);
}
else {
assert(0 && "Not implemented yet");
}
} }
void DtoNestedInit(VarDeclaration* vd) void DtoNestedInit(VarDeclaration* vd)
{ {
if (nestedCtx == NCArray) {
// alloca as usual if no value already // alloca as usual if no value already
if (!vd->ir.irLocal->value) if (!vd->ir.irLocal->value)
vd->ir.irLocal->value = DtoAlloca(DtoType(vd->type), vd->toChars()); vd->ir.irLocal->value = DtoAlloca(DtoType(vd->type), vd->toChars());
@ -60,6 +109,10 @@ void DtoNestedInit(VarDeclaration* vd)
LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType()); LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
DtoStore(val, gep); DtoStore(val, gep);
}
else {
assert(0 && "Not implemented yet");
}
} }
LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
@ -92,6 +145,7 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
} }
void DtoCreateNestedContext(FuncDeclaration* fd) { void DtoCreateNestedContext(FuncDeclaration* fd) {
if (nestedCtx == NCArray) {
// construct nested variables array // construct nested variables array
if (!fd->nestedVars.empty()) if (!fd->nestedVars.empty())
{ {
@ -177,14 +231,19 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
// fixup nested result variable // fixup nested result variable
#if DMDV2 #if DMDV2
if (fd->vresult && fd->vresult->nestedrefs.dim) { if (fd->vresult && fd->vresult->nestedrefs.dim)
#else #else
if (fd->vresult && fd->vresult->nestedref) { if (fd->vresult && fd->vresult->nestedref)
#endif #endif
{
Logger::println("nested vresult value: %s", fd->vresult->toChars()); Logger::println("nested vresult value: %s", fd->vresult->toChars());
LLValue* gep = DtoGEPi(nestedVars, 0, fd->vresult->ir.irLocal->nestedIndex); LLValue* gep = DtoGEPi(nestedVars, 0, fd->vresult->ir.irLocal->nestedIndex);
LLValue* val = DtoBitCast(fd->vresult->ir.irLocal->value, getVoidPtrType()); LLValue* val = DtoBitCast(fd->vresult->ir.irLocal->value, getVoidPtrType());
DtoStore(val, gep); DtoStore(val, gep);
} }
} }
}
else {
assert(0 && "Not implemented yet");
}
} }