Mercurial > projects > ldc
comparison gen/nested.cpp @ 1213:9430d4959ab4
Fix a bug in nested context code that occured when calling a function nested in
the outermost scope with a context frame from a function using a more nested
context frame.
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Mon, 13 Apr 2009 12:19:18 +0200 |
parents | df2227fdc860 |
children | 033f18ec1371 |
comparison
equal
deleted
inserted
replaced
1212:df2227fdc860 | 1213:9430d4959ab4 |
---|---|
48 /*//////////////////////////////////////////////////////////////////////////////////////// | 48 /*//////////////////////////////////////////////////////////////////////////////////////// |
49 // NESTED VARIABLE HELPERS | 49 // NESTED VARIABLE HELPERS |
50 ////////////////////////////////////////////////////////////////////////////////////////*/ | 50 ////////////////////////////////////////////////////////////////////////////////////////*/ |
51 | 51 |
52 static FuncDeclaration* getParentFunc(Dsymbol* sym) { | 52 static FuncDeclaration* getParentFunc(Dsymbol* sym) { |
53 if (!sym) | |
54 return NULL; | |
53 Dsymbol* parent = sym->parent; | 55 Dsymbol* parent = sym->parent; |
54 assert(parent); | 56 assert(parent); |
55 while (parent && !parent->isFuncDeclaration()) | 57 while (parent && !parent->isFuncDeclaration()) |
56 parent = parent->parent; | 58 parent = parent->parent; |
57 | 59 |
176 { | 178 { |
177 Logger::println("DtoNestedContext for %s", sym->toPrettyChars()); | 179 Logger::println("DtoNestedContext for %s", sym->toPrettyChars()); |
178 LOG_SCOPE; | 180 LOG_SCOPE; |
179 | 181 |
180 IrFunction* irfunc = gIR->func(); | 182 IrFunction* irfunc = gIR->func(); |
181 | 183 bool fromParent = true; |
184 | |
185 LLValue* val; | |
182 // if this func has its own vars that are accessed by nested funcs | 186 // if this func has its own vars that are accessed by nested funcs |
183 // use its own context | 187 // use its own context |
184 if (irfunc->nestedVar) | 188 if (irfunc->nestedVar) { |
185 return irfunc->nestedVar; | 189 val = irfunc->nestedVar; |
190 fromParent = false; | |
191 } | |
186 // otherwise, it may have gotten a context from the caller | 192 // otherwise, it may have gotten a context from the caller |
187 else if (irfunc->nestArg) | 193 else if (irfunc->nestArg) |
188 return irfunc->nestArg; | 194 val = irfunc->nestArg; |
189 // or just have a this argument | 195 // or just have a this argument |
190 else if (irfunc->thisArg) | 196 else if (irfunc->thisArg) |
191 { | 197 { |
192 ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration(); | 198 ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration(); |
193 if (!cd || !cd->vthis) | 199 if (!cd || !cd->vthis) |
194 return getNullPtr(getVoidPtrType()); | 200 return getNullPtr(getVoidPtrType()); |
195 LLValue* val = DtoLoad(irfunc->thisArg); | 201 val = DtoLoad(irfunc->thisArg); |
196 return DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis")); | 202 val = DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis")); |
197 } | 203 } |
198 else | 204 else |
199 { | 205 { |
200 return getNullPtr(getVoidPtrType()); | 206 return getNullPtr(getVoidPtrType()); |
201 } | 207 } |
208 if (nestedCtx == NCHybrid) { | |
209 // If sym is a nested function, and its parent elided the context list but the | |
210 // context we got didn't, we need to index to the first frame. | |
211 if (FuncDeclaration* fd = getParentFunc(sym->isFuncDeclaration())) { | |
212 Logger::println("For nested function, parent is %s", fd->toChars()); | |
213 FuncDeclaration* ctxfd = irfunc->decl; | |
214 Logger::println("Current function is %s", ctxfd->toChars()); | |
215 if (fromParent) { | |
216 ctxfd = getParentFunc(ctxfd); | |
217 assert(ctxfd && "Context from outer function, but no outer function?"); | |
218 } | |
219 Logger::println("Context is from %s", ctxfd->toChars()); | |
220 if (fd->ir.irFunc->elidedCtxList && !ctxfd->ir.irFunc->elidedCtxList) { | |
221 Logger::println("Adjusting to remove context frame list", ctxfd->toChars()); | |
222 val = DtoBitCast(val, LLPointerType::getUnqual(ctxfd->ir.irFunc->framesType)); | |
223 val = DtoGEPi(val, 0, 0); | |
224 val = DtoAlignedLoad(val, (std::string(".frame.") + fd->toChars()).c_str()); | |
225 } | |
226 } | |
227 } | |
228 Logger::cout() << "result = " << *val << '\n'; | |
229 Logger::cout() << "of type " << *val->getType() << '\n'; | |
230 return val; | |
202 } | 231 } |
203 | 232 |
204 void DtoCreateNestedContext(FuncDeclaration* fd) { | 233 void DtoCreateNestedContext(FuncDeclaration* fd) { |
205 Logger::println("DtoCreateNestedContext for %s", fd->toChars()); | 234 Logger::println("DtoCreateNestedContext for %s", fd->toChars()); |
206 LOG_SCOPE | 235 LOG_SCOPE |