# HG changeset patch # User Frits van Bommel # Date 1239546141 -7200 # Node ID 2a37f4745ddd2b0cae97dd48c72a571080c1b813 # Parent 83d3b25c221383044d27d6e4f4730e3b8c157de4 Add an option to change the way nested variables are handled. Only one value is implemented, which is the old way. diff -r 83d3b25c2213 -r 2a37f4745ddd gen/nested.cpp --- a/gen/nested.cpp Sun Apr 12 13:08:24 2009 +0200 +++ b/gen/nested.cpp Sun Apr 12 16:22:21 2009 +0200 @@ -6,6 +6,42 @@ #include "gen/logger.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 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 @@ -13,6 +49,9 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd) { + //////////////////////////////////// + // Locate context value + Dsymbol* vdparent = vd->toParent2(); assert(vdparent); @@ -25,7 +64,7 @@ return new DVarValue(astype, vd, val); } - // get it from the nested context + // get the nested context LLValue* ctx = 0; if (irfunc->decl->isMember2()) { @@ -38,28 +77,42 @@ assert(ctx); assert(vd->ir.irLocal); - LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType())); - val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex); - val = DtoLoad(val); - assert(vd->ir.irLocal->value); - val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars()); - return new DVarValue(astype, vd, val); + + //////////////////////////////////// + // Extract variable from nested context + + if (nestedCtx == NCArray) { + LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType())); + val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex); + val = DtoLoad(val); + assert(vd->ir.irLocal->value); + val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars()); + return new DVarValue(astype, vd, val); + } + else { + assert(0 && "Not implemented yet"); + } } void DtoNestedInit(VarDeclaration* vd) { - // alloca as usual if no value already - if (!vd->ir.irLocal->value) - vd->ir.irLocal->value = DtoAlloca(DtoType(vd->type), vd->toChars()); - - // store the address into the nested vars array - assert(vd->ir.irLocal->nestedIndex >= 0); - LLValue* gep = DtoGEPi(gIR->func()->decl->ir.irFunc->nestedVar, 0, vd->ir.irLocal->nestedIndex); - - assert(isaPointer(vd->ir.irLocal->value)); - LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType()); - - DtoStore(val, gep); + if (nestedCtx == NCArray) { + // alloca as usual if no value already + if (!vd->ir.irLocal->value) + vd->ir.irLocal->value = DtoAlloca(DtoType(vd->type), vd->toChars()); + + // store the address into the nested vars array + assert(vd->ir.irLocal->nestedIndex >= 0); + LLValue* gep = DtoGEPi(gIR->func()->decl->ir.irFunc->nestedVar, 0, vd->ir.irLocal->nestedIndex); + + assert(isaPointer(vd->ir.irLocal->value)); + LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType()); + + DtoStore(val, gep); + } + else { + assert(0 && "Not implemented yet"); + } } LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) @@ -92,99 +145,105 @@ } void DtoCreateNestedContext(FuncDeclaration* fd) { - // construct nested variables array - if (!fd->nestedVars.empty()) - { - Logger::println("has nested frame"); - // start with adding all enclosing parent frames until a static parent is reached - int nparelems = 0; - if (!fd->isStatic()) + if (nestedCtx == NCArray) { + // construct nested variables array + if (!fd->nestedVars.empty()) { - Dsymbol* par = fd->toParent2(); - while (par) + Logger::println("has nested frame"); + // start with adding all enclosing parent frames until a static parent is reached + int nparelems = 0; + if (!fd->isStatic()) { - if (FuncDeclaration* parfd = par->isFuncDeclaration()) + Dsymbol* par = fd->toParent2(); + while (par) { - nparelems += parfd->nestedVars.size(); - // stop at first static - if (parfd->isStatic()) + if (FuncDeclaration* parfd = par->isFuncDeclaration()) + { + nparelems += parfd->nestedVars.size(); + // stop at first static + if (parfd->isStatic()) + break; + } + else if (ClassDeclaration* parcd = par->isClassDeclaration()) + { + // nothing needed + } + else + { break; + } + + par = par->toParent2(); } - else if (ClassDeclaration* parcd = par->isClassDeclaration()) + } + int nelems = fd->nestedVars.size() + nparelems; + + // make array type for nested vars + const LLType* nestedVarsTy = LLArrayType::get(getVoidPtrType(), nelems); + + // alloca it + LLValue* nestedVars = DtoAlloca(nestedVarsTy, ".nested_vars"); + + IrFunction* irfunction = fd->ir.irFunc; + + // copy parent frame into beginning + if (nparelems) + { + LLValue* src = irfunction->nestArg; + if (!src) { - // nothing needed + assert(irfunction->thisArg); + assert(fd->isMember2()); + LLValue* thisval = DtoLoad(irfunction->thisArg); + ClassDeclaration* cd = fd->isMember2()->isClassDeclaration(); + assert(cd); + assert(cd->vthis); + src = DtoLoad(DtoGEPi(thisval, 0,cd->vthis->ir.irField->index, ".vthis")); + } + DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE)); + } + + // store in IrFunction + irfunction->nestedVar = nestedVars; + + // go through all nested vars and assign indices + int idx = nparelems; + for (std::set::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) + { + VarDeclaration* vd = *i; + if (!vd->ir.irLocal) + vd->ir.irLocal = new IrLocal(vd); + + if (vd->isParameter()) + { + Logger::println("nested param: %s", vd->toChars()); + LLValue* gep = DtoGEPi(nestedVars, 0, idx); + LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType()); + DtoStore(val, gep); } else { - break; + Logger::println("nested var: %s", vd->toChars()); } - par = par->toParent2(); + vd->ir.irLocal->nestedIndex = idx++; + } + + // fixup nested result variable + #if DMDV2 + if (fd->vresult && fd->vresult->nestedrefs.dim) + #else + if (fd->vresult && fd->vresult->nestedref) + #endif + { + Logger::println("nested vresult value: %s", fd->vresult->toChars()); + LLValue* gep = DtoGEPi(nestedVars, 0, fd->vresult->ir.irLocal->nestedIndex); + LLValue* val = DtoBitCast(fd->vresult->ir.irLocal->value, getVoidPtrType()); + DtoStore(val, gep); } } - int nelems = fd->nestedVars.size() + nparelems; - - // make array type for nested vars - const LLType* nestedVarsTy = LLArrayType::get(getVoidPtrType(), nelems); - - // alloca it - LLValue* nestedVars = DtoAlloca(nestedVarsTy, ".nested_vars"); - - IrFunction* irfunction = fd->ir.irFunc; - - // copy parent frame into beginning - if (nparelems) - { - LLValue* src = irfunction->nestArg; - if (!src) - { - assert(irfunction->thisArg); - assert(fd->isMember2()); - LLValue* thisval = DtoLoad(irfunction->thisArg); - ClassDeclaration* cd = fd->isMember2()->isClassDeclaration(); - assert(cd); - assert(cd->vthis); - src = DtoLoad(DtoGEPi(thisval, 0,cd->vthis->ir.irField->index, ".vthis")); - } - DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE)); - } - - // store in IrFunction - irfunction->nestedVar = nestedVars; - - // go through all nested vars and assign indices - int idx = nparelems; - for (std::set::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) - { - VarDeclaration* vd = *i; - if (!vd->ir.irLocal) - vd->ir.irLocal = new IrLocal(vd); - - if (vd->isParameter()) - { - Logger::println("nested param: %s", vd->toChars()); - LLValue* gep = DtoGEPi(nestedVars, 0, idx); - LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType()); - DtoStore(val, gep); - } - else - { - Logger::println("nested var: %s", vd->toChars()); - } - - vd->ir.irLocal->nestedIndex = idx++; - } - - // fixup nested result variable - #if DMDV2 - if (fd->vresult && fd->vresult->nestedrefs.dim) { - #else - if (fd->vresult && fd->vresult->nestedref) { - #endif - Logger::println("nested vresult value: %s", fd->vresult->toChars()); - LLValue* gep = DtoGEPi(nestedVars, 0, fd->vresult->ir.irLocal->nestedIndex); - LLValue* val = DtoBitCast(fd->vresult->ir.irLocal->value, getVoidPtrType()); - DtoStore(val, gep); - } + } + else { + assert(0 && "Not implemented yet"); } }