changeset 1224:919fafcc505c

Copy alloca'd parameters referenced by nested functions to the nesting frame.
author Frits van Bommel <fvbommel wxs.nl>
date Sat, 18 Apr 2009 00:34:20 +0200
parents 5f340a6dc749
children 837f48560863
files gen/nested.cpp
diffstat 1 files changed, 29 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- 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<llvm::AllocaInst>(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<llvm::AllocaInst>(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.