# HG changeset patch # User Frits van Bommel # Date 1239534504 -7200 # Node ID 83d3b25c221383044d27d6e4f4730e3b8c157de4 # Parent a5bfed1f677541e213c79a2e514984a7691ce908 Isolate all knowledge of what a function's nested context looks like in a single place. No functional change. diff -r a5bfed1f6775 -r 83d3b25c2213 gen/classes.cpp --- a/gen/classes.cpp Sun Apr 12 12:52:01 2009 +0200 +++ b/gen/classes.cpp Sun Apr 12 13:08:24 2009 +0200 @@ -15,6 +15,7 @@ #include "gen/functions.h" #include "gen/runtime.h" #include "gen/dvalue.h" +#include "gen/nested.h" #include "ir/irstruct.h" diff -r a5bfed1f6775 -r 83d3b25c2213 gen/functions.cpp --- a/gen/functions.cpp Sun Apr 12 12:52:01 2009 +0200 +++ b/gen/functions.cpp Sun Apr 12 13:08:24 2009 +0200 @@ -21,6 +21,7 @@ #include "gen/classes.h" #include "gen/dvalue.h" #include "gen/abi.h" +#include "gen/nested.h" using namespace llvm::Attribute; @@ -775,99 +776,7 @@ fd->nestedVars.insert(fd->vresult); } - // 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 (ClassDeclaration* parcd = par->isClassDeclaration()) - { - // nothing needed - } - else - { - break; - } - - par = par->toParent2(); - } - } - 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"); - - // 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); - } - } + DtoCreateNestedContext(fd); // copy _argptr and _arguments to a memory location if (f->linkage == LINKd && f->varargs == 1) diff -r a5bfed1f6775 -r 83d3b25c2213 gen/llvmhelpers.cpp --- a/gen/llvmhelpers.cpp Sun Apr 12 12:52:01 2009 +0200 +++ b/gen/llvmhelpers.cpp Sun Apr 12 13:08:24 2009 +0200 @@ -21,6 +21,7 @@ #include "gen/typeinf.h" #include "gen/todebug.h" #include "gen/cl_options.h" +#include "gen/nested.h" #include "ir/irmodule.h" #include @@ -313,75 +314,6 @@ /****************************************************************************************/ /*//////////////////////////////////////////////////////////////////////////////////////// -// NESTED VARIABLE HELPERS -////////////////////////////////////////////////////////////////////////////////////////*/ - -DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd) -{ - Dsymbol* vdparent = vd->toParent2(); - assert(vdparent); - - IrFunction* irfunc = gIR->func(); - - // is the nested variable in this scope? - if (vdparent == irfunc->decl) - { - LLValue* val = vd->ir.getIrValue(); - return new DVarValue(astype, vd, val); - } - - // get it from the nested context - LLValue* ctx = 0; - if (irfunc->decl->isMember2()) - { - ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration(); - LLValue* val = DtoLoad(irfunc->thisArg); - ctx = DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis")); - } - else - ctx = irfunc->nestArg; - 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); -} - -LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) -{ - Logger::println("DtoNestedContext for %s", sym->toPrettyChars()); - LOG_SCOPE; - - IrFunction* irfunc = gIR->func(); - - // if this func has its own vars that are accessed by nested funcs - // use its own context - if (irfunc->nestedVar) - return irfunc->nestedVar; - // otherwise, it may have gotten a context from the caller - else if (irfunc->nestArg) - return irfunc->nestArg; - // or just have a this argument - else if (irfunc->thisArg) - { - ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration(); - if (!cd || !cd->vthis) - return getNullPtr(getVoidPtrType()); - LLValue* val = DtoLoad(irfunc->thisArg); - return DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis")); - } - else - { - return getNullPtr(getVoidPtrType()); - } -} - -/****************************************************************************************/ -/*//////////////////////////////////////////////////////////////////////////////////////// // ASSIGNMENT HELPER (store this in that) ////////////////////////////////////////////////////////////////////////////////////////*/ @@ -946,22 +878,7 @@ Logger::println("has nestedref set"); assert(vd->ir.irLocal); - // 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); - + DtoNestedInit(vd); } // normal stack variable, allocate storage on the stack if it has not already been done else if(!vd->ir.irLocal) { @@ -1110,12 +1027,7 @@ else assert(!addr || addr == var->ir.irLocal->value); - // store the address into the nested vars array - assert(var->ir.irLocal->nestedIndex >= 0); - LLValue* gep = DtoGEPi(gIR->func()->decl->ir.irFunc->nestedVar, 0, var->ir.irLocal->nestedIndex); - assert(isaPointer(var->ir.irLocal->value)); - LLValue* val = DtoBitCast(var->ir.irLocal->value, getVoidPtrType()); - DtoStore(val, gep); + DtoNestedInit(var); } // normal local variable else diff -r a5bfed1f6775 -r 83d3b25c2213 gen/llvmhelpers.h --- a/gen/llvmhelpers.h Sun Apr 12 12:52:01 2009 +0200 +++ b/gen/llvmhelpers.h Sun Apr 12 13:08:24 2009 +0200 @@ -2,7 +2,10 @@ #define LDC_GEN_LLVMHELPERS_H #include "gen/llvm.h" +#include "gen/dvalue.h" + #include "statement.h" +#include "mtype.h" // this is used for tracking try-finally, synchronized and volatile scopes struct EnclosingHandler @@ -64,15 +67,6 @@ /// Leaves a monitor lock. void DtoLeaveMonitor(LLValue* v); -// nested variable and context helpers - -/// Gets the context value for a call to a nested function or newing a nested -/// class with arbitrary nesting. -LLValue* DtoNestedContext(Loc loc, Dsymbol* sym); - -/// Gets the DValue of a nested variable with arbitrary nesting. -DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd); - // basic operations void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs); diff -r a5bfed1f6775 -r 83d3b25c2213 gen/nested.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/nested.cpp Sun Apr 12 13:08:24 2009 +0200 @@ -0,0 +1,190 @@ +#include "gen/nested.h" + +#include "gen/dvalue.h" +#include "gen/irstate.h" +#include "gen/llvmhelpers.h" +#include "gen/logger.h" +#include "gen/tollvm.h" + +/****************************************************************************************/ +/*//////////////////////////////////////////////////////////////////////////////////////// +// NESTED VARIABLE HELPERS +////////////////////////////////////////////////////////////////////////////////////////*/ + +DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd) +{ + Dsymbol* vdparent = vd->toParent2(); + assert(vdparent); + + IrFunction* irfunc = gIR->func(); + + // is the nested variable in this scope? + if (vdparent == irfunc->decl) + { + LLValue* val = vd->ir.getIrValue(); + return new DVarValue(astype, vd, val); + } + + // get it from the nested context + LLValue* ctx = 0; + if (irfunc->decl->isMember2()) + { + ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration(); + LLValue* val = DtoLoad(irfunc->thisArg); + ctx = DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis")); + } + else + ctx = irfunc->nestArg; + 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); +} + +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); +} + +LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) +{ + Logger::println("DtoNestedContext for %s", sym->toPrettyChars()); + LOG_SCOPE; + + IrFunction* irfunc = gIR->func(); + + // if this func has its own vars that are accessed by nested funcs + // use its own context + if (irfunc->nestedVar) + return irfunc->nestedVar; + // otherwise, it may have gotten a context from the caller + else if (irfunc->nestArg) + return irfunc->nestArg; + // or just have a this argument + else if (irfunc->thisArg) + { + ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration(); + if (!cd || !cd->vthis) + return getNullPtr(getVoidPtrType()); + LLValue* val = DtoLoad(irfunc->thisArg); + return DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis")); + } + else + { + return getNullPtr(getVoidPtrType()); + } +} + +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()) + { + 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 (ClassDeclaration* parcd = par->isClassDeclaration()) + { + // nothing needed + } + else + { + break; + } + + par = par->toParent2(); + } + } + 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); + } + } +} diff -r a5bfed1f6775 -r 83d3b25c2213 gen/nested.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/nested.h Sun Apr 12 13:08:24 2009 +0200 @@ -0,0 +1,25 @@ +#ifndef LDC_GEN_NESTED_H +#define LDC_GEN_NESTED_H + +#include "declaration.h" +#include "mtype.h" +#include "gen/dvalue.h" + +/////////////////////////////////////////////////////////// +// Nested variable and context helpers +/////////////////////////////////////////////////////////// + +/// Creates the context value for a nested function. +void DtoCreateNestedContext(FuncDeclaration* fd); + +/// Allocate space for variable accessed from nested function. +void DtoNestedInit(VarDeclaration* vd); + +/// Gets the context value for a call to a nested function or newing a nested +/// class with arbitrary nesting. +llvm::Value* DtoNestedContext(Loc loc, Dsymbol* sym); + +/// Gets the DValue of a nested variable with arbitrary nesting. +DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd); + +#endif diff -r a5bfed1f6775 -r 83d3b25c2213 gen/tocall.cpp --- a/gen/tocall.cpp Sun Apr 12 12:52:01 2009 +0200 +++ b/gen/tocall.cpp Sun Apr 12 13:08:24 2009 +0200 @@ -9,6 +9,7 @@ #include "gen/dvalue.h" #include "gen/functions.h" #include "gen/abi.h" +#include "gen/nested.h" #include "gen/logger.h" diff -r a5bfed1f6775 -r 83d3b25c2213 gen/toir.cpp --- a/gen/toir.cpp Sun Apr 12 12:52:01 2009 +0200 +++ b/gen/toir.cpp Sun Apr 12 13:08:24 2009 +0200 @@ -36,6 +36,7 @@ #include "gen/aa.h" #include "gen/functions.h" #include "gen/todebug.h" +#include "gen/nested.h" #include "llvm/Support/ManagedStatic.h"