Removed obsolete nested context styles.

NChybrid was the only one that didn't instantly trigger a "not
implemented" assertion on any code using nested function for a long
time, and removing the cruft greatly improves code readability
(maintainability is a moot point anyway given its current state).
This commit is contained in:
David Nadlinger 2012-09-04 01:58:19 +02:00
parent ee4285f934
commit d4eafe53e0
4 changed files with 272 additions and 455 deletions

View file

@ -807,14 +807,14 @@ void DtoDefineFunction(FuncDeclaration* fd)
DtoCreateNestedContext(fd);
if (fd->vresult && !
#if DMDV2
if (fd->vresult && fd->vresult->nestedrefs.dim) // FIXME: not sure here :/
fd->vresult->nestedrefs.dim // FIXME: not sure here :/
#else
if (fd->vresult && fd->vresult->nestedref)
fd->vresult->nestedref
#endif
)
{
DtoNestedInit(fd->vresult);
} else if (fd->vresult) {
DtoVarDeclaration(fd->vresult);
}

View file

@ -1029,10 +1029,10 @@ void DtoVarDeclaration(VarDeclaration* vd)
#endif
{
Logger::println("has nestedref set (referenced by nested function/delegate)");
assert(vd->ir.irLocal);
DtoNestedInit(vd);
assert(vd->ir.irLocal && "irLocal is expected to be already set by DtoCreateNestedContext");
}
else if(vd->ir.irLocal)
if(vd->ir.irLocal)
{
// Nothing to do if it has already been allocated.
}
@ -1265,8 +1265,6 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr)
}
else
assert(!addr || addr == var->ir.irLocal->value);
DtoNestedInit(var);
}
// normal local variable
else

View file

@ -12,42 +12,6 @@
#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.
// NOTE: This is what DMD seems to do.
NCStruct,
/// Context is a list of pointers to structs of variables, followed by the
/// variables of the inner-most function with variables accessed by nested
/// functions. The initial pointers point to similar structs for enclosing
/// functions.
/// Only functions whose variables are accessed by nested functions create
/// new frames, others just pass on what got passed in.
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", "List of pointers to structs of variables, one per level."),
clEnumValEnd),
cl::init(NCHybrid));
/****************************************************************************************/
/*////////////////////////////////////////////////////////////////////////////////////////
// NESTED VARIABLE HELPERS
@ -168,15 +132,6 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref)
////////////////////////////////////
// Extract variable from nested context
if (nestedCtx == NCArray) {
LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType()));
val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex);
val = DtoAlignedLoad(val);
assert(vd->ir.irLocal->value);
val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars());
return new DVarValue(astype, vd, val);
}
else if (nestedCtx == NCHybrid) {
LLValue* val = DtoBitCast(ctx, LLPointerType::getUnqual(irfunc->frameType));
Logger::cout() << "Context: " << *val << '\n';
Logger::cout() << "of type: " << *val->getType() << '\n';
@ -223,40 +178,6 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref)
return new DVarValue(astype, vd, val);
}
else {
assert(0 && "Not implemented yet");
}
}
void DtoNestedInit(VarDeclaration* vd)
{
Logger::println("DtoNestedInit for %s", vd->toChars());
LOG_SCOPE
IrFunction* irfunc = gIR->func()->decl->ir.irFunc;
LLValue* nestedVar = irfunc->nestedVar;
if (nestedCtx == NCArray) {
// alloca as usual if no value already
if (!vd->ir.irLocal->value)
vd->ir.irLocal->value = DtoAlloca(vd->type, vd->toChars());
// store the address into the nested vars array
assert(vd->ir.irLocal->nestedIndex >= 0);
LLValue* gep = DtoGEPi(nestedVar, 0, vd->ir.irLocal->nestedIndex);
assert(isaPointer(vd->ir.irLocal->value));
LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
DtoAlignedStore(val, gep);
}
else if (nestedCtx == NCHybrid) {
// Already initialized in DtoCreateNestedContext.
}
else {
assert(0 && "Not implemented yet");
}
}
#if DMDV2
void DtoResolveNestedContext(Loc loc, AggregateDeclaration *decl, LLValue *value)
@ -316,7 +237,7 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
{
return llvm::UndefValue::get(getVoidPtrType());
}
if (nestedCtx == NCHybrid) {
struct FuncDeclaration* fd = 0;
#if DMDV2
if (AggregateDeclaration *ad = sym->isAggregateDeclaration())
@ -369,7 +290,7 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
val = DtoAlignedLoad(val, (std::string(".frame.") + fd->toChars()).c_str());
}
}
}
Logger::cout() << "result = " << *val << '\n';
Logger::cout() << "of type " << *val->getType() << '\n';
return val;
@ -397,7 +318,6 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) {
}
#endif
if (nestedCtx == NCHybrid) {
// construct nested variables array
if (!fd->nestedVars.empty())
{
@ -500,10 +420,6 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) {
fd->ir.irFunc->depth = parFunc->ir.irFunc->depth;
}
}
else {
assert(0 && "Not implemented yet");
}
}
void DtoCreateNestedContext(FuncDeclaration* fd) {
@ -512,96 +428,6 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
DtoCreateNestedContextType(fd);
if (nestedCtx == NCArray) {
// 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())
{
Dsymbol* par = fd->toParent2();
while (par)
{
if (FuncDeclaration* parfd = par->isFuncDeclaration())
{
nparelems += parfd->nestedVars.size();
// stop at first static
if (parfd->isStatic())
break;
}
else if (par->isClassDeclaration())
{
// nothing needed
}
else
{
break;
}
par = par->toParent2();
}
}
int nelems = fd->nestedVars.size() + nparelems;
// make array type for nested vars
LLType* nestedVarsTy = LLArrayType::get(getVoidPtrType(), nelems);
// alloca it
// FIXME align ?
LLValue* nestedVars = DtoRawAlloca(nestedVarsTy, 0, ".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"));
} else {
src = DtoLoad(src);
}
DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE),
getABITypeAlign(getVoidPtrType()));
}
// store in IrFunction
irfunction->nestedVar = nestedVars;
// go through all nested vars and assign indices
int idx = nparelems;
for (std::set<VarDeclaration*>::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());
DtoAlignedStore(val, gep);
}
else
{
Logger::println("nested var: %s", vd->toChars());
}
vd->ir.irLocal->nestedIndex = idx++;
}
}
}
else if (nestedCtx == NCHybrid) {
// construct nested variables array
if (!fd->nestedVars.empty())
{
@ -702,7 +528,3 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
fd->ir.irFunc->depth = parFunc->ir.irFunc->depth;
}
}
else {
assert(0 && "Not implemented yet");
}
}

View file

@ -13,9 +13,6 @@
/// Creates the context value for a nested function.
void DtoCreateNestedContext(FuncDeclaration* fd);
/// Allocate space for variable accessed from nested function.
void DtoNestedInit(VarDeclaration* vd);
/// Resolves the nested context for classes and structs with arbitrary nesting.
#if DMDV2
void DtoResolveNestedContext(Loc loc, AggregateDeclaration *decl, LLValue *value);