Mercurial > projects > ldc
changeset 1185:8baf611f0009
Fix nested references to 'ref' foreach variables.
These "walk around" the array being iterated over, so they're a bit trickier
than other variables to get right.
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Wed, 01 Apr 2009 00:01:44 +0200 |
parents | df386fd4030e |
children | 7562457bb7f3 |
files | gen/llvmhelpers.cpp gen/llvmhelpers.h gen/statements.cpp tests/mini/compile_rawvardeclinfinally.d tests/mini/foreach10.d tests/mini/foreach11.d |
diffstat | 6 files changed, 68 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/gen/llvmhelpers.cpp Tue Mar 31 03:06:19 2009 +0200 +++ b/gen/llvmhelpers.cpp Wed Apr 01 00:01:44 2009 +0200 @@ -1075,7 +1075,7 @@ } // does pretty much the same as DtoDeclarationExp, except it doesn't initialize, and only handles var declarations -LLValue* DtoRawVarDeclaration(VarDeclaration* var) +LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr) { // we don't handle globals with this one assert(!var->isDataseg()); @@ -1083,10 +1083,6 @@ // we don't handle aliases either assert(!var->aliassym); - // if this already has storage, it must've been handled already - if (var->ir.irLocal && var->ir.irLocal->value) - return var->ir.irLocal->value; - // referenced by nested function? #if DMDV2 if (var->nestedrefs.dim) @@ -1095,10 +1091,10 @@ #endif { assert(var->ir.irLocal); - assert(!var->ir.irLocal->value); - - // alloca - var->ir.irLocal->value = DtoAlloca(DtoType(var->type), var->toChars()); + if(!var->ir.irLocal->value) + var->ir.irLocal->value = addr ? addr : DtoAlloca(DtoType(var->type), var->toChars()); + else + assert(!addr || addr == var->ir.irLocal->value); // store the address into the nested vars array assert(var->ir.irLocal->nestedIndex >= 0); @@ -1110,9 +1106,15 @@ // normal local variable else { + // if this already has storage, it must've been handled already + if (var->ir.irLocal && var->ir.irLocal->value) { + assert(!addr || addr == var->ir.irLocal->value); + return var->ir.irLocal->value; + } + assert(!var->ir.isSet()); var->ir.irLocal = new IrLocal(var); - var->ir.irLocal->value = DtoAlloca(DtoType(var->type), var->toChars()); + var->ir.irLocal->value = addr ? addr : DtoAlloca(DtoType(var->type), var->toChars()); } // add debug info
--- a/gen/llvmhelpers.h Tue Mar 31 03:06:19 2009 +0200 +++ b/gen/llvmhelpers.h Wed Apr 01 00:01:44 2009 +0200 @@ -101,7 +101,7 @@ // declaration inside a declarationexp DValue* DtoDeclarationExp(Dsymbol* declaration); -LLValue* DtoRawVarDeclaration(VarDeclaration* var); +LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr = 0); // initializer helpers LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init);
--- a/gen/statements.cpp Tue Mar 31 03:06:19 2009 +0200 +++ b/gen/statements.cpp Wed Apr 01 00:01:44 2009 +0200 @@ -1030,11 +1030,12 @@ // value Logger::println("value = %s", value->toPrettyChars()); - DtoRawVarDeclaration(value); - const LLType* valtype = DtoType(value->type); LLValue* valvar = NULL; - if (!value->isRef() && !value->isOut()) + if (!value->isRef() && !value->isOut()) { + // Create a local variable to serve as the value. + DtoRawVarDeclaration(value); valvar = value->ir.irLocal->value; + } // what to iterate DValue* aggrval = aggr->toElem(p); @@ -1093,13 +1094,17 @@ // get value for this iteration LLConstant* zero = llvm::ConstantInt::get(keytype,0,false); LLValue* loadedKey = p->ir->CreateLoad(keyvar,"tmp"); - value->ir.irLocal->value = DtoGEP1(val,loadedKey); + LLValue* gep = DtoGEP1(val,loadedKey); if (!value->isRef() && !value->isOut()) { + // Copy value to local variable, and use it as the value variable. DVarValue dst(value->type, valvar); - DVarValue src(value->type, value->ir.irLocal->value); + DVarValue src(value->type, gep); DtoAssign(loc, &dst, &src); value->ir.irLocal->value = valvar; + } else { + // Use the GEP as the address of the value variable. + DtoRawVarDeclaration(value, gep); } // emit body
--- a/tests/mini/compile_rawvardeclinfinally.d Tue Mar 31 03:06:19 2009 +0200 +++ b/tests/mini/compile_rawvardeclinfinally.d Wed Apr 01 00:01:44 2009 +0200 @@ -1,1 +1,8 @@ -void foo() { void delegate()[] bar; try {} finally { foreach (dg; bar) dg(); } } +void foo() { + void delegate()[] bar; + try { + } finally { + foreach (dg; bar) + dg(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/mini/foreach10.d Wed Apr 01 00:01:44 2009 +0200 @@ -0,0 +1,19 @@ +module foreach10; + +extern(C) int printf(char*, ...); + +void main() { + char* last = null; + printf("The addresses should increment:\n"); + foreach (ref c; "bar") { + auto a = { + printf("%x '%c'\n", c, c); + return &c; + }; + auto nw = a(); + printf("ptr = %p\n", nw); + if (last != null) + assert(nw == last+1); + last = nw; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/mini/foreach11.d Wed Apr 01 00:01:44 2009 +0200 @@ -0,0 +1,18 @@ +module foreach11; + +extern(C) int printf(char*, ...); + +void main() { + char* last = null; + printf("The addresses should remain constant:\n"); + foreach (c; "bar") { + auto a = { + printf("%x '%c'\n", c, c); + printf("ptr = %p\n", &c); + if (last) + assert(last == &c); + }; + a(); + last = &c; + } +}