# HG changeset patch # User Frits van Bommel # Date 1240007660 -7200 # Node ID 919fafcc505c8abe8f43f6135a53193b2a3130b0 # Parent 5f340a6dc749091f804d485035b9157a6d341af1 Copy alloca'd parameters referenced by nested functions to the nesting frame. diff -r 5f340a6dc749 -r 919fafcc505c gen/nested.cpp --- a/gen/nested.cpp Fri Apr 17 13:50:01 2009 +0200 +++ b/gen/nested.cpp Sat Apr 18 00:34:20 2009 +0200 @@ -426,10 +426,14 @@ vd->ir.irLocal->nestedDepth = depth; if (vd->isParameter()) { // Parameters already have storage associated with them (to handle byref etc.), - // so handle specially for now by storing a pointer instead of a value. + // so handle those cases specially by storing a pointer instead of a value. assert(vd->ir.irLocal->value); - // FIXME: don't do this for normal parameters? - types.push_back(vd->ir.irLocal->value->getType()); + LLValue* value = vd->ir.irLocal->value; + const LLType* type = value->getType(); + if (llvm::isa(value->getUnderlyingObject())) + // This will be copied to the nesting frame. + type = type->getContainedType(0); + 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())); @@ -453,6 +457,8 @@ // Create frame for current function and append to frames list // FIXME: For D2, this should be a gc_malloc (or similar) call, not alloca + // (Note that it'd also require more aggressive copying of + // by-value parameters instead of just alloca'd ones) LLValue* frame = DtoAlloca(frameType, ".frame"); // copy parent frames into beginning @@ -491,8 +497,26 @@ LLValue* gep = DtoGEPi(frame, 0, vd->ir.irLocal->nestedIndex, vd->toChars()); if (vd->isParameter()) { Logger::println("nested param: %s", vd->toChars()); - DtoAlignedStore(vd->ir.irLocal->value, gep); - vd->ir.irLocal->byref = true; + LOG_SCOPE + LLValue* value = vd->ir.irLocal->value; + if (llvm::isa(value->getUnderlyingObject())) { + 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(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. + DtoAlignedStore(vd->ir.irLocal->value, 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.