comparison gen/nested.cpp @ 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
comparison
equal deleted inserted replaced
1207:83d3b25c2213 1208:2a37f4745ddd
4 #include "gen/irstate.h" 4 #include "gen/irstate.h"
5 #include "gen/llvmhelpers.h" 5 #include "gen/llvmhelpers.h"
6 #include "gen/logger.h" 6 #include "gen/logger.h"
7 #include "gen/tollvm.h" 7 #include "gen/tollvm.h"
8 8
9 #include "llvm/Support/CommandLine.h"
10 namespace cl = llvm::cl;
11
12 /// What the context pointer for a nested function looks like
13 enum NestedCtxType {
14 /// Context is void*[] of pointers to variables.
15 /// Variables from higher levels are at the front.
16 NCArray,
17
18 /// Context is a struct containing variables belonging to the parent function.
19 /// If the parent function itself has a parent function, one of the members is
20 /// a pointer to its context. (linked-list style)
21 // FIXME: implement
22 // TODO: Functions without any variables accessed by nested functions, but
23 // with a parent whose variables are accessed, can use the parent's
24 // context.
25 NCStruct,
26
27 /// Context is an array of pointers to nested contexts. Each function with variables
28 /// accessed by nested functions puts them in a struct, and appends a pointer to that
29 /// struct to the array.
30 // FIXME: implement
31 NCHybrid
32 };
33
34 static cl::opt<NestedCtxType> nestedCtx("nested-ctx",
35 cl::desc("How to construct a nested function's context:"),
36 cl::ZeroOrMore,
37 cl::values(
38 clEnumValN(NCArray, "array", "Array of pointers to variables (including multi-level)"),
39 //clEnumValN(NCStruct, "struct", "Struct of variables (with multi-level via linked list)"),
40 //clEnumValN(NCHybrid, "hybrid", "Array of pointers to structs of variables"),
41 clEnumValEnd),
42 cl::init(NCArray));
43
44
9 /****************************************************************************************/ 45 /****************************************************************************************/
10 /*//////////////////////////////////////////////////////////////////////////////////////// 46 /*////////////////////////////////////////////////////////////////////////////////////////
11 // NESTED VARIABLE HELPERS 47 // NESTED VARIABLE HELPERS
12 ////////////////////////////////////////////////////////////////////////////////////////*/ 48 ////////////////////////////////////////////////////////////////////////////////////////*/
13 49
14 DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd) 50 DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
15 { 51 {
52 ////////////////////////////////////
53 // Locate context value
54
16 Dsymbol* vdparent = vd->toParent2(); 55 Dsymbol* vdparent = vd->toParent2();
17 assert(vdparent); 56 assert(vdparent);
18 57
19 IrFunction* irfunc = gIR->func(); 58 IrFunction* irfunc = gIR->func();
20 59
23 { 62 {
24 LLValue* val = vd->ir.getIrValue(); 63 LLValue* val = vd->ir.getIrValue();
25 return new DVarValue(astype, vd, val); 64 return new DVarValue(astype, vd, val);
26 } 65 }
27 66
28 // get it from the nested context 67 // get the nested context
29 LLValue* ctx = 0; 68 LLValue* ctx = 0;
30 if (irfunc->decl->isMember2()) 69 if (irfunc->decl->isMember2())
31 { 70 {
32 ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration(); 71 ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
33 LLValue* val = DtoLoad(irfunc->thisArg); 72 LLValue* val = DtoLoad(irfunc->thisArg);
36 else 75 else
37 ctx = irfunc->nestArg; 76 ctx = irfunc->nestArg;
38 assert(ctx); 77 assert(ctx);
39 78
40 assert(vd->ir.irLocal); 79 assert(vd->ir.irLocal);
41 LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType())); 80
42 val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex); 81 ////////////////////////////////////
43 val = DtoLoad(val); 82 // Extract variable from nested context
44 assert(vd->ir.irLocal->value); 83
45 val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars()); 84 if (nestedCtx == NCArray) {
46 return new DVarValue(astype, vd, val); 85 LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType()));
86 val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex);
87 val = DtoLoad(val);
88 assert(vd->ir.irLocal->value);
89 val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars());
90 return new DVarValue(astype, vd, val);
91 }
92 else {
93 assert(0 && "Not implemented yet");
94 }
47 } 95 }
48 96
49 void DtoNestedInit(VarDeclaration* vd) 97 void DtoNestedInit(VarDeclaration* vd)
50 { 98 {
51 // alloca as usual if no value already 99 if (nestedCtx == NCArray) {
52 if (!vd->ir.irLocal->value) 100 // alloca as usual if no value already
53 vd->ir.irLocal->value = DtoAlloca(DtoType(vd->type), vd->toChars()); 101 if (!vd->ir.irLocal->value)
54 102 vd->ir.irLocal->value = DtoAlloca(DtoType(vd->type), vd->toChars());
55 // store the address into the nested vars array 103
56 assert(vd->ir.irLocal->nestedIndex >= 0); 104 // store the address into the nested vars array
57 LLValue* gep = DtoGEPi(gIR->func()->decl->ir.irFunc->nestedVar, 0, vd->ir.irLocal->nestedIndex); 105 assert(vd->ir.irLocal->nestedIndex >= 0);
58 106 LLValue* gep = DtoGEPi(gIR->func()->decl->ir.irFunc->nestedVar, 0, vd->ir.irLocal->nestedIndex);
59 assert(isaPointer(vd->ir.irLocal->value)); 107
60 LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType()); 108 assert(isaPointer(vd->ir.irLocal->value));
61 109 LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
62 DtoStore(val, gep); 110
111 DtoStore(val, gep);
112 }
113 else {
114 assert(0 && "Not implemented yet");
115 }
63 } 116 }
64 117
65 LLValue* DtoNestedContext(Loc loc, Dsymbol* sym) 118 LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
66 { 119 {
67 Logger::println("DtoNestedContext for %s", sym->toPrettyChars()); 120 Logger::println("DtoNestedContext for %s", sym->toPrettyChars());
90 return getNullPtr(getVoidPtrType()); 143 return getNullPtr(getVoidPtrType());
91 } 144 }
92 } 145 }
93 146
94 void DtoCreateNestedContext(FuncDeclaration* fd) { 147 void DtoCreateNestedContext(FuncDeclaration* fd) {
95 // construct nested variables array 148 if (nestedCtx == NCArray) {
96 if (!fd->nestedVars.empty()) 149 // construct nested variables array
97 { 150 if (!fd->nestedVars.empty())
98 Logger::println("has nested frame");
99 // start with adding all enclosing parent frames until a static parent is reached
100 int nparelems = 0;
101 if (!fd->isStatic())
102 { 151 {
103 Dsymbol* par = fd->toParent2(); 152 Logger::println("has nested frame");
104 while (par) 153 // start with adding all enclosing parent frames until a static parent is reached
105 { 154 int nparelems = 0;
106 if (FuncDeclaration* parfd = par->isFuncDeclaration()) 155 if (!fd->isStatic())
107 { 156 {
108 nparelems += parfd->nestedVars.size(); 157 Dsymbol* par = fd->toParent2();
109 // stop at first static 158 while (par)
110 if (parfd->isStatic()) 159 {
160 if (FuncDeclaration* parfd = par->isFuncDeclaration())
161 {
162 nparelems += parfd->nestedVars.size();
163 // stop at first static
164 if (parfd->isStatic())
165 break;
166 }
167 else if (ClassDeclaration* parcd = par->isClassDeclaration())
168 {
169 // nothing needed
170 }
171 else
172 {
111 break; 173 break;
112 } 174 }
113 else if (ClassDeclaration* parcd = par->isClassDeclaration()) 175
114 { 176 par = par->toParent2();
115 // nothing needed 177 }
178 }
179 int nelems = fd->nestedVars.size() + nparelems;
180
181 // make array type for nested vars
182 const LLType* nestedVarsTy = LLArrayType::get(getVoidPtrType(), nelems);
183
184 // alloca it
185 LLValue* nestedVars = DtoAlloca(nestedVarsTy, ".nested_vars");
186
187 IrFunction* irfunction = fd->ir.irFunc;
188
189 // copy parent frame into beginning
190 if (nparelems)
191 {
192 LLValue* src = irfunction->nestArg;
193 if (!src)
194 {
195 assert(irfunction->thisArg);
196 assert(fd->isMember2());
197 LLValue* thisval = DtoLoad(irfunction->thisArg);
198 ClassDeclaration* cd = fd->isMember2()->isClassDeclaration();
199 assert(cd);
200 assert(cd->vthis);
201 src = DtoLoad(DtoGEPi(thisval, 0,cd->vthis->ir.irField->index, ".vthis"));
202 }
203 DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE));
204 }
205
206 // store in IrFunction
207 irfunction->nestedVar = nestedVars;
208
209 // go through all nested vars and assign indices
210 int idx = nparelems;
211 for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
212 {
213 VarDeclaration* vd = *i;
214 if (!vd->ir.irLocal)
215 vd->ir.irLocal = new IrLocal(vd);
216
217 if (vd->isParameter())
218 {
219 Logger::println("nested param: %s", vd->toChars());
220 LLValue* gep = DtoGEPi(nestedVars, 0, idx);
221 LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
222 DtoStore(val, gep);
116 } 223 }
117 else 224 else
118 { 225 {
119 break; 226 Logger::println("nested var: %s", vd->toChars());
120 } 227 }
121 228
122 par = par->toParent2(); 229 vd->ir.irLocal->nestedIndex = idx++;
230 }
231
232 // fixup nested result variable
233 #if DMDV2
234 if (fd->vresult && fd->vresult->nestedrefs.dim)
235 #else
236 if (fd->vresult && fd->vresult->nestedref)
237 #endif
238 {
239 Logger::println("nested vresult value: %s", fd->vresult->toChars());
240 LLValue* gep = DtoGEPi(nestedVars, 0, fd->vresult->ir.irLocal->nestedIndex);
241 LLValue* val = DtoBitCast(fd->vresult->ir.irLocal->value, getVoidPtrType());
242 DtoStore(val, gep);
123 } 243 }
124 } 244 }
125 int nelems = fd->nestedVars.size() + nparelems; 245 }
126 246 else {
127 // make array type for nested vars 247 assert(0 && "Not implemented yet");
128 const LLType* nestedVarsTy = LLArrayType::get(getVoidPtrType(), nelems); 248 }
129 249 }
130 // alloca it
131 LLValue* nestedVars = DtoAlloca(nestedVarsTy, ".nested_vars");
132
133 IrFunction* irfunction = fd->ir.irFunc;
134
135 // copy parent frame into beginning
136 if (nparelems)
137 {
138 LLValue* src = irfunction->nestArg;
139 if (!src)
140 {
141 assert(irfunction->thisArg);
142 assert(fd->isMember2());
143 LLValue* thisval = DtoLoad(irfunction->thisArg);
144 ClassDeclaration* cd = fd->isMember2()->isClassDeclaration();
145 assert(cd);
146 assert(cd->vthis);
147 src = DtoLoad(DtoGEPi(thisval, 0,cd->vthis->ir.irField->index, ".vthis"));
148 }
149 DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE));
150 }
151
152 // store in IrFunction
153 irfunction->nestedVar = nestedVars;
154
155 // go through all nested vars and assign indices
156 int idx = nparelems;
157 for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
158 {
159 VarDeclaration* vd = *i;
160 if (!vd->ir.irLocal)
161 vd->ir.irLocal = new IrLocal(vd);
162
163 if (vd->isParameter())
164 {
165 Logger::println("nested param: %s", vd->toChars());
166 LLValue* gep = DtoGEPi(nestedVars, 0, idx);
167 LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
168 DtoStore(val, gep);
169 }
170 else
171 {
172 Logger::println("nested var: %s", vd->toChars());
173 }
174
175 vd->ir.irLocal->nestedIndex = idx++;
176 }
177
178 // fixup nested result variable
179 #if DMDV2
180 if (fd->vresult && fd->vresult->nestedrefs.dim) {
181 #else
182 if (fd->vresult && fd->vresult->nestedref) {
183 #endif
184 Logger::println("nested vresult value: %s", fd->vresult->toChars());
185 LLValue* gep = DtoGEPi(nestedVars, 0, fd->vresult->ir.irLocal->nestedIndex);
186 LLValue* val = DtoBitCast(fd->vresult->ir.irLocal->value, getVoidPtrType());
187 DtoStore(val, gep);
188 }
189 }
190 }