Skip to content
Browse files

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).
  • Loading branch information...
1 parent ee4285f commit d4eafe53e05d7ec6537653f98161f83eddb5ff7f @klickverbot klickverbot committed
Showing with 260 additions and 443 deletions.
  1. +4 −4 gen/functions.cpp
  2. +3 −5 gen/llvmhelpers.cpp
  3. +253 −431 gen/nested.cpp
  4. +0 −3 gen/nested.h
View
8 gen/functions.cpp
@@ -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
8 gen/llvmhelpers.cpp
@@ -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
684 gen/nested.cpp
@@ -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,94 +132,51 @@ 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';
+ LLValue* val = DtoBitCast(ctx, LLPointerType::getUnqual(irfunc->frameType));
+ Logger::cout() << "Context: " << *val << '\n';
+ Logger::cout() << "of type: " << *val->getType() << '\n';
- unsigned vardepth = vd->ir.irLocal->nestedDepth;
- unsigned funcdepth = irfunc->depth;
+ unsigned vardepth = vd->ir.irLocal->nestedDepth;
+ unsigned funcdepth = irfunc->depth;
- Logger::cout() << "Variable: " << vd->toChars() << '\n';
- Logger::cout() << "Variable depth: " << vardepth << '\n';
- Logger::cout() << "Function: " << irfunc->decl->toChars() << '\n';
- Logger::cout() << "Function depth: " << funcdepth << '\n';
+ Logger::cout() << "Variable: " << vd->toChars() << '\n';
+ Logger::cout() << "Variable depth: " << vardepth << '\n';
+ Logger::cout() << "Function: " << irfunc->decl->toChars() << '\n';
+ Logger::cout() << "Function depth: " << funcdepth << '\n';
- if (vardepth == funcdepth) {
- // This is not always handled above because functions without
- // variables accessed by nested functions don't create new frames.
- Logger::println("Same depth");
- } else {
- // Load frame pointer and index that...
- if (dwarfValue && global.params.symdebug) {
- dwarfOpOffset(dwarfAddr, val, vd->ir.irLocal->nestedDepth);
- dwarfOpDeref(dwarfAddr);
- }
- Logger::println("Lower depth");
- val = DtoGEPi(val, 0, vd->ir.irLocal->nestedDepth);
- Logger::cout() << "Frame index: " << *val << '\n';
- val = DtoAlignedLoad(val, (std::string(".frame.") + vdparent->toChars()).c_str());
- Logger::cout() << "Frame: " << *val << '\n';
+ if (vardepth == funcdepth) {
+ // This is not always handled above because functions without
+ // variables accessed by nested functions don't create new frames.
+ Logger::println("Same depth");
+ } else {
+ // Load frame pointer and index that...
+ if (dwarfValue && global.params.symdebug) {
+ dwarfOpOffset(dwarfAddr, val, vd->ir.irLocal->nestedDepth);
+ dwarfOpDeref(dwarfAddr);
}
+ Logger::println("Lower depth");
+ val = DtoGEPi(val, 0, vd->ir.irLocal->nestedDepth);
+ Logger::cout() << "Frame index: " << *val << '\n';
+ val = DtoAlignedLoad(val, (std::string(".frame.") + vdparent->toChars()).c_str());
+ Logger::cout() << "Frame: " << *val << '\n';
+ }
- if (dwarfValue && global.params.symdebug)
- dwarfOpOffset(dwarfAddr, val, vd->ir.irLocal->nestedIndex);
- val = DtoGEPi(val, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
- Logger::cout() << "Addr: " << *val << '\n';
+ if (dwarfValue && global.params.symdebug)
+ dwarfOpOffset(dwarfAddr, val, vd->ir.irLocal->nestedIndex);
+ val = DtoGEPi(val, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
+ Logger::cout() << "Addr: " << *val << '\n';
+ Logger::cout() << "of type: " << *val->getType() << '\n';
+ if (byref || (vd->isParameter() && vd->ir.irParam->arg->byref)) {
+ val = DtoAlignedLoad(val);
+ //dwarfOpDeref(dwarfAddr);
+ Logger::cout() << "Was byref, now: " << *val << '\n';
Logger::cout() << "of type: " << *val->getType() << '\n';
- if (byref || (vd->isParameter() && vd->ir.irParam->arg->byref)) {
- val = DtoAlignedLoad(val);
- //dwarfOpDeref(dwarfAddr);
- Logger::cout() << "Was byref, now: " << *val << '\n';
- Logger::cout() << "of type: " << *val->getType() << '\n';
- }
-
- if (dwarfValue && global.params.symdebug)
- DtoDwarfLocalVariable(dwarfValue, vd, dwarfAddr);
-
- 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());
+ if (dwarfValue && global.params.symdebug)
+ DtoDwarfLocalVariable(dwarfValue, vd, dwarfAddr);
- // 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");
- }
+ return new DVarValue(astype, vd, val);
}
#if DMDV2
@@ -316,60 +237,60 @@ 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())
- // If sym is a nested struct or a nested class, pass the frame
- // of the function where sym is declared.
- fd = ad->toParent()->isFuncDeclaration();
- else
- #endif
- if (FuncDeclaration* symfd = sym->isFuncDeclaration()) {
- // Make sure we've had a chance to analyze nested context usage
- #if DMDV2
- DtoCreateNestedContextType(symfd);
- #else
- DtoDefineFunction(symfd);
- #endif
-
- // 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());
-
- // If sym is a nested function, and it's parent context is different than the
- // one we got, adjust it.
- fd = getParentFunc(symfd, true);
+
+ struct FuncDeclaration* fd = 0;
+#if DMDV2
+ if (AggregateDeclaration *ad = sym->isAggregateDeclaration())
+ // If sym is a nested struct or a nested class, pass the frame
+ // of the function where sym is declared.
+ fd = ad->toParent()->isFuncDeclaration();
+ else
+#endif
+ if (FuncDeclaration* symfd = sym->isFuncDeclaration()) {
+ // Make sure we've had a chance to analyze nested context usage
+#if DMDV2
+ DtoCreateNestedContextType(symfd);
+#else
+ DtoDefineFunction(symfd);
+#endif
+
+ // 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());
+
+ // If sym is a nested function, and it's parent context is different than the
+ // one we got, adjust it.
+ fd = getParentFunc(symfd, true);
+ }
+ if (fd) {
+ 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?");
}
- if (fd) {
- 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());
+ Logger::println("Context is from %s", ctxfd->toChars());
- unsigned neededDepth = fd->ir.irFunc->depth;
- unsigned ctxDepth = ctxfd->ir.irFunc->depth;
+ unsigned neededDepth = fd->ir.irFunc->depth;
+ unsigned ctxDepth = ctxfd->ir.irFunc->depth;
- Logger::cout() << "Needed depth: " << neededDepth << '\n';
- Logger::cout() << "Context depth: " << ctxDepth << '\n';
+ 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 (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());
}
}
+
Logger::cout() << "result = " << *val << '\n';
Logger::cout() << "of type " << *val->getType() << '\n';
return val;
@@ -397,111 +318,106 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) {
}
#endif
- if (nestedCtx == NCHybrid) {
- // 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
-
- LLStructType* innerFrameType = NULL;
- unsigned depth = -1;
- if (!fd->isStatic()) {
- if (FuncDeclaration* parfd = getParentFunc(fd, true)) {
- // Make sure the parent has already been analyzed.
- DtoCreateNestedContextType(parfd);
-
- innerFrameType = parfd->ir.irFunc->frameType;
- if (innerFrameType)
- depth = parfd->ir.irFunc->depth;
- }
+ // 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
+
+ LLStructType* innerFrameType = NULL;
+ unsigned depth = -1;
+ if (!fd->isStatic()) {
+ if (FuncDeclaration* parfd = getParentFunc(fd, true)) {
+ // Make sure the parent has already been analyzed.
+ DtoCreateNestedContextType(parfd);
+
+ innerFrameType = parfd->ir.irFunc->frameType;
+ if (innerFrameType)
+ depth = parfd->ir.irFunc->depth;
}
- fd->ir.irFunc->depth = ++depth;
-
- Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n';
-
- typedef std::vector<LLType*> TypeVec;
- TypeVec types;
- if (depth != 0) {
- assert(innerFrameType);
- // Add frame pointer types for all but last frame
- if (depth > 1) {
- for (unsigned i = 0; i < (depth - 1); ++i) {
- types.push_back(innerFrameType->getElementType(i));
- }
+ }
+ fd->ir.irFunc->depth = ++depth;
+
+ Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n';
+
+ typedef std::vector<LLType*> TypeVec;
+ TypeVec types;
+ if (depth != 0) {
+ assert(innerFrameType);
+ // Add frame pointer types for all but last frame
+ if (depth > 1) {
+ for (unsigned i = 0; i < (depth - 1); ++i) {
+ types.push_back(innerFrameType->getElementType(i));
}
- // Add frame pointer type for last frame
- types.push_back(LLPointerType::getUnqual(innerFrameType));
}
+ // Add frame pointer type for last frame
+ types.push_back(LLPointerType::getUnqual(innerFrameType));
+ }
- if (Logger::enabled()) {
- Logger::println("Frame types: ");
- LOG_SCOPE;
- for (TypeVec::iterator i = types.begin(); i != types.end(); ++i)
- Logger::cout() << **i << '\n';
- }
+ if (Logger::enabled()) {
+ Logger::println("Frame types: ");
+ LOG_SCOPE;
+ for (TypeVec::iterator i = types.begin(); i != types.end(); ++i)
+ Logger::cout() << **i << '\n';
+ }
- // Add the direct nested variables of this function, and update their indices to match.
- // TODO: optimize ordering for minimal space usage?
- 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);
-
- vd->ir.irLocal->nestedIndex = types.size();
- vd->ir.irLocal->nestedDepth = depth;
- if (vd->isParameter()) {
- // Parameters will have storage associated with them (to handle byref etc.),
- // so handle those cases specially by storing a pointer instead of a value.
- IrParameter * irparam = vd->ir.irParam;
- LLValue* value = irparam->value;
- assert(value);
- LLType* type = value->getType();
- bool refout = vd->storage_class & (STCref | STCout);
- bool lazy = vd->storage_class & STClazy;
- bool byref = irparam->arg->byref;
- #if STRUCTTHISREF
- bool isVthisPtr = irparam->isVthis && !byref;
- #else
- bool isVthisPtr = irparam->isVthis;
- #endif
- if ((!refout && (!byref || lazy)) || isVthisPtr) {
- // This will be copied to the nesting frame.
- if (lazy)
- type = type->getContainedType(0);
- else
- type = DtoType(vd->type);
- } else {
- }
- types.push_back(type);
- } else if (isSpecialRefVar(vd)) {
- types.push_back(DtoType(vd->type->pointerTo()));
+ // Add the direct nested variables of this function, and update their indices to match.
+ // TODO: optimize ordering for minimal space usage?
+ 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);
+
+ vd->ir.irLocal->nestedIndex = types.size();
+ vd->ir.irLocal->nestedDepth = depth;
+ if (vd->isParameter()) {
+ // Parameters will have storage associated with them (to handle byref etc.),
+ // so handle those cases specially by storing a pointer instead of a value.
+ IrParameter * irparam = vd->ir.irParam;
+ LLValue* value = irparam->value;
+ assert(value);
+ LLType* type = value->getType();
+ bool refout = vd->storage_class & (STCref | STCout);
+ bool lazy = vd->storage_class & STClazy;
+ bool byref = irparam->arg->byref;
+#if STRUCTTHISREF
+ bool isVthisPtr = irparam->isVthis && !byref;
+#else
+ bool isVthisPtr = irparam->isVthis;
+#endif
+ if ((!refout && (!byref || lazy)) || isVthisPtr) {
+ // This will be copied to the nesting frame.
+ if (lazy)
+ type = type->getContainedType(0);
+ else
+ type = DtoType(vd->type);
} else {
- types.push_back(DtoType(vd->type));
- }
- if (Logger::enabled()) {
- Logger::println("Nested var: %s", vd->toChars());
- Logger::cout() << "of type: " << *types.back() << '\n';
}
+ types.push_back(type);
+ } else if (isSpecialRefVar(vd)) {
+ types.push_back(DtoType(vd->type->pointerTo()));
+ } else {
+ types.push_back(DtoType(vd->type));
+ }
+ if (Logger::enabled()) {
+ Logger::println("Nested var: %s", vd->toChars());
+ Logger::cout() << "of type: " << *types.back() << '\n';
}
+ }
- LLStructType* frameType = LLStructType::create(gIR->context(), types,
- std::string("nest.") + fd->toChars());
+ LLStructType* frameType = LLStructType::create(gIR->context(), types,
+ std::string("nest.") + fd->toChars());
- Logger::cout() << "frameType = " << *frameType << '\n';
+ Logger::cout() << "frameType = " << *frameType << '\n';
- // Store type in IrFunction
- fd->ir.irFunc->frameType = frameType;
- } else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) {
- // Propagate context arg properties if the context arg is passed on unmodified.
- DtoCreateNestedContextType(parFunc);
- fd->ir.irFunc->frameType = parFunc->ir.irFunc->frameType;
- fd->ir.irFunc->depth = parFunc->ir.irFunc->depth;
- }
- }
- else {
- assert(0 && "Not implemented yet");
+ // Store type in IrFunction
+ fd->ir.irFunc->frameType = frameType;
+ } else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) {
+ // Propagate context arg properties if the context arg is passed on unmodified.
+ DtoCreateNestedContextType(parFunc);
+ fd->ir.irFunc->frameType = parFunc->ir.irFunc->frameType;
+ fd->ir.irFunc->depth = parFunc->ir.irFunc->depth;
}
}
@@ -512,197 +428,103 @@ 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())
- {
- IrFunction* irfunction = fd->ir.irFunc;
- unsigned depth = irfunction->depth;
- LLStructType *frameType = irfunction->frameType;
- // Create frame for current function and append to frames list
- // FIXME: alignment ?
- LLValue* frame = 0;
+ // construct nested variables array
+ if (!fd->nestedVars.empty())
+ {
+ IrFunction* irfunction = fd->ir.irFunc;
+ unsigned depth = irfunction->depth;
+ LLStructType *frameType = irfunction->frameType;
+ // Create frame for current function and append to frames list
+ // FIXME: alignment ?
+ LLValue* frame = 0;
#if DMDV2
- if (fd->needsClosure())
- frame = DtoGcMalloc(frameType, ".frame");
- else
+ if (fd->needsClosure())
+ frame = DtoGcMalloc(frameType, ".frame");
+ else
#endif
- frame = DtoRawAlloca(frameType, 0, ".frame");
+ frame = DtoRawAlloca(frameType, 0, ".frame");
- // copy parent frames into beginning
- if (depth != 0) {
- LLValue* src = irfunction->nestArg;
- if (!src) {
- assert(irfunction->thisArg);
- assert(fd->isMember2());
- LLValue* thisval = DtoLoad(irfunction->thisArg);
+ // copy parent frames into beginning
+ if (depth != 0) {
+ LLValue* src = irfunction->nestArg;
+ if (!src) {
+ assert(irfunction->thisArg);
+ assert(fd->isMember2());
+ LLValue* thisval = DtoLoad(irfunction->thisArg);
#if DMDV2
- AggregateDeclaration* cd = fd->isMember2();
+ AggregateDeclaration* cd = fd->isMember2();
#else
- ClassDeclaration* cd = fd->isMember2()->isClassDeclaration();
+ ClassDeclaration* cd = fd->isMember2()->isClassDeclaration();
#endif
- assert(cd);
- assert(cd->vthis);
- Logger::println("Indexing to 'this'");
+ assert(cd);
+ assert(cd->vthis);
+ Logger::println("Indexing to 'this'");
#if DMDV2
- if (cd->isStructDeclaration())
- src = DtoExtractValue(thisval, cd->vthis->ir.irField->index, ".vthis");
- else
+ if (cd->isStructDeclaration())
+ src = DtoExtractValue(thisval, cd->vthis->ir.irField->index, ".vthis");
+ else
#endif
- src = DtoLoad(DtoGEPi(thisval, 0, cd->vthis->ir.irField->index, ".vthis"));
- } else {
- src = DtoLoad(src);
- }
- if (depth > 1) {
- src = DtoBitCast(src, getVoidPtrType());
- LLValue* dst = DtoBitCast(frame, getVoidPtrType());
- DtoMemCpy(dst, src, DtoConstSize_t((depth-1) * PTRSIZE),
- getABITypeAlign(getVoidPtrType()));
- }
- // Copy nestArg into framelist; the outer frame is not in the list of pointers
- src = DtoBitCast(src, frameType->getContainedType(depth-1));
- LLValue* gep = DtoGEPi(frame, 0, depth-1);
- DtoAlignedStore(src, gep);
+ src = DtoLoad(DtoGEPi(thisval, 0, cd->vthis->ir.irField->index, ".vthis"));
+ } else {
+ src = DtoLoad(src);
}
+ if (depth > 1) {
+ src = DtoBitCast(src, getVoidPtrType());
+ LLValue* dst = DtoBitCast(frame, getVoidPtrType());
+ DtoMemCpy(dst, src, DtoConstSize_t((depth-1) * PTRSIZE),
+ getABITypeAlign(getVoidPtrType()));
+ }
+ // Copy nestArg into framelist; the outer frame is not in the list of pointers
+ src = DtoBitCast(src, frameType->getContainedType(depth-1));
+ LLValue* gep = DtoGEPi(frame, 0, depth-1);
+ DtoAlignedStore(src, gep);
+ }
- // store context in IrFunction
- irfunction->nestedVar = frame;
+ // store context in IrFunction
+ irfunction->nestedVar = frame;
- // go through all nested vars and assign addresses where possible.
- for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
- {
- VarDeclaration* vd = *i;
+ // go through all nested vars and assign addresses where possible.
+ for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
+ {
+ VarDeclaration* vd = *i;
- LLValue* gep = DtoGEPi(frame, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
- if (vd->isParameter()) {
- Logger::println("nested param: %s", vd->toChars());
- LOG_SCOPE
- IrParameter* parm = vd->ir.irParam;
+ LLValue* gep = DtoGEPi(frame, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
+ if (vd->isParameter()) {
+ Logger::println("nested param: %s", vd->toChars());
+ LOG_SCOPE
+ IrParameter* parm = vd->ir.irParam;
- if (parm->arg->byref)
- {
- storeVariable(vd, gep);
- }
- else
- {
- Logger::println("Copying to nested frame");
- // The parameter value is an alloca'd stack slot.
- // Copy to the nesting frame and leave the alloca for
- // the optimizers to clean up.
- DtoStore(DtoLoad(parm->value), gep);
- gep->takeName(parm->value);
- parm->value = gep;
- }
- } else {
- Logger::println("nested var: %s", vd->toChars());
- assert(!vd->ir.irLocal->value);
- vd->ir.irLocal->value = gep;
+ if (parm->arg->byref)
+ {
+ storeVariable(vd, gep);
}
-
- if (global.params.symdebug) {
- LLSmallVector<LLValue*, 2> addr;
- dwarfOpOffset(addr, frameType, vd->ir.irLocal->nestedIndex);
- DtoDwarfLocalVariable(frame, vd, addr);
+ else
+ {
+ Logger::println("Copying to nested frame");
+ // The parameter value is an alloca'd stack slot.
+ // Copy to the nesting frame and leave the alloca for
+ // the optimizers to clean up.
+ DtoStore(DtoLoad(parm->value), gep);
+ gep->takeName(parm->value);
+ parm->value = gep;
}
+ } else {
+ Logger::println("nested var: %s", vd->toChars());
+ assert(!vd->ir.irLocal->value);
+ vd->ir.irLocal->value = gep;
+ }
+
+ if (global.params.symdebug) {
+ LLSmallVector<LLValue*, 2> addr;
+ dwarfOpOffset(addr, frameType, vd->ir.irLocal->nestedIndex);
+ DtoDwarfLocalVariable(frame, vd, addr);
}
- } else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) {
- // Propagate context arg properties if the context arg is passed on unmodified.
- DtoDeclareFunction(parFunc);
- fd->ir.irFunc->frameType = parFunc->ir.irFunc->frameType;
- fd->ir.irFunc->depth = parFunc->ir.irFunc->depth;
}
- }
- else {
- assert(0 && "Not implemented yet");
+ } else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) {
+ // Propagate context arg properties if the context arg is passed on unmodified.
+ DtoDeclareFunction(parFunc);
+ fd->ir.irFunc->frameType = parFunc->ir.irFunc->frameType;
+ fd->ir.irFunc->depth = parFunc->ir.irFunc->depth;
}
}
View
3 gen/nested.h
@@ -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);

0 comments on commit d4eafe5

Please sign in to comment.
Something went wrong with that request. Please try again.