changeset 1208:2a37f4745ddd

Add an option to change the way nested variables are handled. Only one value is implemented, which is the old way.
author Frits van Bommel <fvbommel wxs.nl>
date Sun, 12 Apr 2009 16:22:21 +0200
parents 83d3b25c2213
children 8699c450a1a0
files gen/nested.cpp
diffstat 1 files changed, 159 insertions(+), 100 deletions(-) [+]
line wrap: on
line diff
--- a/gen/nested.cpp	Sun Apr 12 13:08:24 2009 +0200
+++ b/gen/nested.cpp	Sun Apr 12 16:22:21 2009 +0200
@@ -6,6 +6,42 @@
 #include "gen/logger.h"
 #include "gen/tollvm.h"
 
+#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.
+    NCStruct,
+    
+    /// Context is an array of pointers to nested contexts. Each function with variables
+    /// accessed by nested functions puts them in a struct, and appends a pointer to that
+    /// struct to the array.
+    // FIXME: implement
+    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", "Array of pointers to structs of variables"),
+        clEnumValEnd),
+    cl::init(NCArray));
+
+
 /****************************************************************************************/
 /*////////////////////////////////////////////////////////////////////////////////////////
 // NESTED VARIABLE HELPERS
@@ -13,6 +49,9 @@
 
 DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
 {
+    ////////////////////////////////////
+    // Locate context value
+    
     Dsymbol* vdparent = vd->toParent2();
     assert(vdparent);
     
@@ -25,7 +64,7 @@
         return new DVarValue(astype, vd, val);
     }
     
-    // get it from the nested context
+    // get the nested context
     LLValue* ctx = 0;
     if (irfunc->decl->isMember2())
     {
@@ -38,28 +77,42 @@
     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);
+    
+    ////////////////////////////////////
+    // Extract variable from nested context
+    
+    if (nestedCtx == NCArray) {
+        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);
+    }
+    else {
+        assert(0 && "Not implemented yet");
+    }
 }
 
 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);
+    if (nestedCtx == NCArray) {
+        // 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);
+    }
+    else {
+        assert(0 && "Not implemented yet");
+    }
 }
 
 LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
@@ -92,99 +145,105 @@
 }
 
 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())
+    if (nestedCtx == NCArray) {
+        // construct nested variables array
+        if (!fd->nestedVars.empty())
         {
-            Dsymbol* par = fd->toParent2();
-            while (par)
+            Logger::println("has nested frame");
+            // start with adding all enclosing parent frames until a static parent is reached
+            int nparelems = 0;
+            if (!fd->isStatic())
             {
-                if (FuncDeclaration* parfd = par->isFuncDeclaration())
+                Dsymbol* par = fd->toParent2();
+                while (par)
                 {
-                    nparelems += parfd->nestedVars.size();
-                    // stop at first static
-                    if (parfd->isStatic())
+                    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();
                 }
-                else if (ClassDeclaration* parcd = par->isClassDeclaration())
+            }
+            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)
                 {
-                    // nothing needed
+                    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<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());
+                    DtoStore(val, gep);
                 }
                 else
                 {
-                    break;
+                    Logger::println("nested var:   %s", vd->toChars());
                 }
 
-                par = par->toParent2();
+                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);
             }
         }
-        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<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());
-                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);
-        }
+    }
+    else {
+        assert(0 && "Not implemented yet");
     }
 }