changeset 1207:83d3b25c2213

Isolate all knowledge of what a function's nested context looks like in a single place. No functional change.
author Frits van Bommel <fvbommel wxs.nl>
date Sun, 12 Apr 2009 13:08:24 +0200
parents a5bfed1f6775
children 2a37f4745ddd
files gen/classes.cpp gen/functions.cpp gen/llvmhelpers.cpp gen/llvmhelpers.h gen/nested.cpp gen/nested.h gen/tocall.cpp gen/toir.cpp
diffstat 8 files changed, 226 insertions(+), 193 deletions(-) [+]
line wrap: on
line diff
--- 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"
 
--- 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<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);
-        }
-    }
+    DtoCreateNestedContext(fd);
 
     // copy _argptr and _arguments to a memory location
     if (f->linkage == LINKd && f->varargs == 1)
--- 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 <stack>
@@ -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
--- 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);
 
--- /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<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);
+        }
+    }
+}
--- /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
--- 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"
 
--- 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"