From 929c62019c2c38d1f7defd648ff3536048a82496 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 15 Dec 2018 00:36:50 +0100 Subject: [PATCH 1/2] Fix issue #2932 (allow speculative nested variables) --- gen/nested.cpp | 24 ++++++++++++++++++------ tests/compilable/gh2932.d | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 tests/compilable/gh2932.d diff --git a/gen/nested.cpp b/gen/nested.cpp index 61e56e3761a..809bf617cea 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -57,6 +57,22 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd, return makeVarDValue(astype, vd); } + assert(isIrLocalCreated(vd)); + IrLocal *const irLocal = getIrLocal(vd); + + // The variable may not actually be nested in a speculative context (e.g., + // with `-allinst`, see https://github.com/ldc-developers/ldc/issues/2932). + // Use an invalid null storage in that case, so that accessing the var at + // runtime will cause a segfault. + if (irLocal->nestedIndex == -1) { + Logger::println( + "WARNING: isn't actually nested, using invalid null storage"); + auto llType = DtoPtrToType(astype); + if (isSpecialRefVar(vd)) + llType = llType->getPointerTo(); + return makeVarDValue(astype, vd, llvm::ConstantPointerNull::get(llType)); + } + // get the nested context LLValue *ctx = nullptr; bool skipDIDeclaration = false; @@ -84,11 +100,11 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd, IF_LOG { Logger::cout() << "Context: " << *ctx << '\n'; } DtoCreateNestedContextType(vdparent->isFuncDeclaration()); - assert(isIrLocalCreated(vd)); //////////////////////////////////// // Extract variable from nested context + assert(irfunc->frameType); const auto frameType = LLPointerType::getUnqual(irfunc->frameType); IF_LOG { Logger::cout() << "casting to: " << *irfunc->frameType << '\n'; } LLValue *val = DtoBitCast(ctx, frameType); @@ -108,7 +124,6 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd, val = DtoAlignedLoad(val, name); }; - IrLocal *const irLocal = getIrLocal(vd); const auto vardepth = irLocal->nestedDepth; const auto funcdepth = irfunc->depth; @@ -132,10 +147,7 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd, IF_LOG Logger::cout() << "Frame: " << *val << '\n'; } - const auto idx = irLocal->nestedIndex; - assert(idx != -1 && "Nested context not yet resolved for variable."); - - offsetToNthField(idx, vd->toChars()); + offsetToNthField(irLocal->nestedIndex, vd->toChars()); IF_LOG { Logger::cout() << "Addr: " << *val << '\n'; Logger::cout() << "of type: " << *val->getType() << '\n'; diff --git a/tests/compilable/gh2932.d b/tests/compilable/gh2932.d new file mode 100644 index 00000000000..fbfa479cd2a --- /dev/null +++ b/tests/compilable/gh2932.d @@ -0,0 +1,20 @@ +// RUN: %ldc -c -allinst %s + +import std.algorithm; + +extern __gshared int[] array; + +void funcWithNoFrame() +{ + int local; + // lambda is codegen'd + pragma(msg, typeof(array.map!(e => local))); +} + +void funcWithFrame() +{ + int capturedVar, local; + int nestedFunc() { return capturedVar; } + // lambda is codegen'd with `-allinst` + static assert(__traits(compiles, array.map!(e => local))); +} From 909e1a5ed88f69f676773e38d637baa2a88fc260 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 15 Dec 2018 02:03:14 +0100 Subject: [PATCH 2/2] Safer variantQ --- gen/nested.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/gen/nested.cpp b/gen/nested.cpp index 809bf617cea..8404c18758b 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -57,22 +57,6 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd, return makeVarDValue(astype, vd); } - assert(isIrLocalCreated(vd)); - IrLocal *const irLocal = getIrLocal(vd); - - // The variable may not actually be nested in a speculative context (e.g., - // with `-allinst`, see https://github.com/ldc-developers/ldc/issues/2932). - // Use an invalid null storage in that case, so that accessing the var at - // runtime will cause a segfault. - if (irLocal->nestedIndex == -1) { - Logger::println( - "WARNING: isn't actually nested, using invalid null storage"); - auto llType = DtoPtrToType(astype); - if (isSpecialRefVar(vd)) - llType = llType->getPointerTo(); - return makeVarDValue(astype, vd, llvm::ConstantPointerNull::get(llType)); - } - // get the nested context LLValue *ctx = nullptr; bool skipDIDeclaration = false; @@ -101,6 +85,22 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd, DtoCreateNestedContextType(vdparent->isFuncDeclaration()); + assert(isIrLocalCreated(vd)); + IrLocal *const irLocal = getIrLocal(vd); + + // The variable may not actually be nested in a speculative context (e.g., + // with `-allinst`, see https://github.com/ldc-developers/ldc/issues/2932). + // Use an invalid null storage in that case, so that accessing the var at + // runtime will cause a segfault. + if (irLocal->nestedIndex == -1) { + Logger::println( + "WARNING: isn't actually nested, using invalid null storage"); + auto llType = DtoPtrToType(astype); + if (isSpecialRefVar(vd)) + llType = llType->getPointerTo(); + return makeVarDValue(astype, vd, llvm::ConstantPointerNull::get(llType)); + } + //////////////////////////////////// // Extract variable from nested context