diff --git a/gen/functions.cpp b/gen/functions.cpp index fc17abeb..d1115f15 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -597,17 +597,15 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) { if (fdecl->parameters && fdecl->parameters->dim > k) { - Dsymbol* argsym; - if (f->fty.reverseParams) - argsym = (Dsymbol*)fdecl->parameters->data[fdecl->parameters->dim-k-1]; - else - argsym = (Dsymbol*)fdecl->parameters->data[k]; + int paramIndex = f->fty.reverseParams ? fdecl->parameters->dim-k-1 : k; + Dsymbol* argsym = (Dsymbol*)fdecl->parameters->data[paramIndex]; VarDeclaration* argvd = argsym->isVarDeclaration(); assert(argvd); assert(!argvd->ir.irLocal); - argvd->ir.irLocal = new IrLocal(argvd); - argvd->ir.irLocal->value = iarg; + argvd->ir.irParam = new IrParameter(argvd); + argvd->ir.irParam->value = iarg; + argvd->ir.irParam->arg = f->fty.args[paramIndex]; str = argvd->ident->toChars(); str.append("_arg"); @@ -720,9 +718,10 @@ void DtoDefineFunction(FuncDeclaration* fd) irfunction->thisArg = thismem; } - assert(!fd->vthis->ir.irLocal); - fd->vthis->ir.irLocal = new IrLocal(fd->vthis); - fd->vthis->ir.irLocal->value = thismem; + assert(!fd->vthis->ir.irParam); + fd->vthis->ir.irParam = new IrParameter(fd->vthis); + fd->vthis->ir.irParam->value = thismem; + fd->vthis->ir.irParam->arg = f->fty.arg_this; DtoDwarfLocalVariable(thismem, fd->vthis); @@ -755,8 +754,8 @@ void DtoDefineFunction(FuncDeclaration* fd) VarDeclaration* vd = argsym->isVarDeclaration(); assert(vd); - IrLocal* irloc = vd->ir.irLocal; - assert(irloc); + IrParameter* irparam = vd->ir.irParam; + assert(irparam); #if DMDV1 if (vd->nestedref) @@ -767,26 +766,26 @@ void DtoDefineFunction(FuncDeclaration* fd) bool refout = vd->storage_class & (STCref | STCout); bool lazy = vd->storage_class & STClazy; - if (!refout && (!f->fty.args[i]->byref || lazy)) + if (!refout && (!irparam->arg->byref || lazy)) { // alloca a stack slot for this first class value arg LLType* argt; if (lazy) - argt = irloc->value->getType(); + argt = irparam->value->getType(); else argt = DtoType(vd->type); LLValue* mem = DtoRawAlloca(argt, 0, vd->ident->toChars()); // let the abi transform the argument back first - DImValue arg_dval(vd->type, irloc->value); + DImValue arg_dval(vd->type, irparam->value); f->fty.getParam(vd->type, i, &arg_dval, mem); // set the arg var value to the alloca - irloc->value = mem; + irparam->value = mem; } - if (global.params.symdebug && !(isaArgument(irloc->value) && isaArgument(irloc->value)->hasByValAttr()) && !refout) - DtoDwarfLocalVariable(irloc->value, vd); + if (global.params.symdebug && !(isaArgument(irparam->value) && isaArgument(irparam->value)->hasByValAttr()) && !refout) + DtoDwarfLocalVariable(irparam->value, vd); } } diff --git a/gen/nested.cpp b/gen/nested.cpp index cafb9fb6..6804238e 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -461,20 +461,31 @@ static void DtoCreateNestedContextType(FuncDeclaration* fd) { vd->ir.irLocal->nestedIndex = types.size(); vd->ir.irLocal->nestedDepth = depth; if (vd->isParameter()) { - // Parameters already have storage associated with them (to handle byref etc.), + // Parameters will have storage associated with them (to handle byref etc.), // so handle those cases specially by storing a pointer instead of a value. - assert(vd->ir.irLocal->value); - LLValue* value = vd->ir.irLocal->value; + assert(vd->ir.irParam->value); + LLValue* value = vd->ir.irParam->value; LLType* type = value->getType(); - if (llvm::isa(llvm::GetUnderlyingObject(value))) + bool refout = vd->storage_class & (STCref | STCout); + bool lazy = vd->storage_class & STClazy; + if (!refout && (!vd->ir.irParam->arg->byref || lazy)) { // This will be copied to the nesting frame. - type = type->getContainedType(0); + if (lazy) + type = type->getContainedType(0); + else + type = DtoType(vd->type); + vd->ir.irParam->byref = false; + } else { + vd->ir.irParam->byref = true; + } types.push_back(type); } else if (vd->isRef() || vd->isOut()) { // Foreach variables can also be by reference, for instance. types.push_back(DtoType(vd->type->pointerTo())); + vd->ir.irLocal->byref = true; } else { types.push_back(DtoType(vd->type)); + vd->ir.irLocal->byref = false; } if (Logger::enabled()) { Logger::println("Nested var: %s", vd->toChars()); @@ -669,30 +680,30 @@ void DtoCreateNestedContext(FuncDeclaration* fd) { // The parameter value is an alloca'd stack slot. // Copy to the nesting frame and leave the alloca for // the optimizers to clean up. + assert(!vd->ir.irLocal->byref); DtoStore(DtoLoad(value), gep); gep->takeName(value); vd->ir.irLocal->value = gep; - vd->ir.irLocal->byref = false; } else { Logger::println("Adding pointer to nested frame"); // The parameter value is something else, such as a // passed-in pointer (for 'ref' or 'out' parameters) or // a pointer arg with byval attribute. - // Store the address into the frame and set the byref flag. + // Store the address into the frame. + assert(vd->ir.irLocal->byref); storeVariable(vd, gep); - vd->ir.irLocal->byref = true; } } else if (vd->isRef() || vd->isOut()) { // This slot is initialized in DtoNestedInit, to handle things like byref foreach variables // which move around in memory. - vd->ir.irLocal->byref = true; + assert(vd->ir.irLocal->byref); } else { Logger::println("nested var: %s", vd->toChars()); if (vd->ir.irLocal->value) Logger::cout() << "Pre-existing value: " << *vd->ir.irLocal->value << '\n'; assert(!vd->ir.irLocal->value); vd->ir.irLocal->value = gep; - vd->ir.irLocal->byref = false; + assert(!vd->ir.irLocal->byref); } if (global.params.symdebug) { diff --git a/ir/irdsymbol.h b/ir/irdsymbol.h index 574dcc5a..f7bf4f13 100644 --- a/ir/irdsymbol.h +++ b/ir/irdsymbol.h @@ -8,6 +8,7 @@ struct IrFunction; struct IrStruct; struct IrGlobal; struct IrLocal; +struct IrParameter; struct IrField; struct IrVar; struct Dsymbol; @@ -43,7 +44,10 @@ struct IrDsymbol IrFunction* irFunc; IrGlobal* irGlobal; - IrLocal* irLocal; + union { + IrLocal* irLocal; + IrParameter *irParam; + }; IrField* irField; IrVar* getIrVar(); llvm::Value*& getIrValue(); diff --git a/ir/irvar.cpp b/ir/irvar.cpp index dabf0382..24184529 100644 --- a/ir/irvar.cpp +++ b/ir/irvar.cpp @@ -38,6 +38,14 @@ IrLocal::IrLocal(VarDeclaration* v) : IrVar(v) ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// +IrParameter::IrParameter(VarDeclaration* v) : IrLocal(v), arg(0) +{ +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + IrField::IrField(VarDeclaration* v) : IrVar(v) { assert(V->ir.irField == NULL && "field for this variable already exists"); diff --git a/ir/irvar.h b/ir/irvar.h index 471442e7..8d5934d8 100644 --- a/ir/irvar.h +++ b/ir/irvar.h @@ -4,6 +4,8 @@ #include "ir/ir.h" #include "llvm/Type.h" +struct IrFuncTyArg; + struct IrVar : IrBase { IrVar(VarDeclaration* var); @@ -31,6 +33,13 @@ struct IrLocal : IrVar int nestedIndex; }; +// represents a function parameter +struct IrParameter : IrLocal +{ + IrParameter(VarDeclaration* v); + IrFuncTyArg *arg; +}; + // represents an aggregate field variable struct IrField : IrVar {