Permalink
Browse files

Debuginfo: Fix nested variables (primarily for CodeView) (#2909)

We've been going back and forth between GEPs and complex DWARF
expressions based on the context pointer; this goes back to the latter,
as that fixes simple nested variables for CodeView with LLVM >= 6.

I guess it also helps for debuginfos of nested vars with enabled
optimizations.
  • Loading branch information...
kinke committed Nov 20, 2018
1 parent 78d6fb3 commit 32b6e49a654a3eb7d19e57f99fa2021ca759464c
Showing with 34 additions and 54 deletions.
  1. +4 −0 gen/dibuilder.h
  2. +21 −12 gen/nested.cpp
  3. +0 −31 tests/debuginfo/nested.d
  4. +9 −11 tests/debuginfo/nested_cdb.d
@@ -206,7 +206,11 @@ class DIBuilder {
uint64_t offset =
gDataLayout->getStructLayout(type)->getElementOffset(index);
#if LDC_LLVM_VER >= 500
addr.push_back(llvm::dwarf::DW_OP_plus_uconst);
#else
addr.push_back(llvm::dwarf::DW_OP_plus);
#endif
addr.push_back(offset);
}
@@ -93,6 +93,21 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
IF_LOG { Logger::cout() << "casting to: " << *irfunc->frameType << '\n'; }
LLValue *val = DtoBitCast(ctx, frameType);
// Make the DWARF variable address relative to the context pointer (ctx);
// register all ops (offsetting, dereferencing) required to get there in the
// following list.
LLSmallVector<int64_t, 4> dwarfAddrOps;
const auto offsetToNthField = [&val, &dwarfAddrOps](unsigned fieldIndex,
const char *name = "") {
gIR->DBuilder.OpOffset(dwarfAddrOps, val, fieldIndex);
val = DtoGEPi(val, 0, fieldIndex, name);
};
const auto dereference = [&val, &dwarfAddrOps](const char *name = "") {
gIR->DBuilder.OpDeref(dwarfAddrOps);
val = DtoAlignedLoad(val, name);
};
IrLocal *const irLocal = getIrLocal(vd);
const auto vardepth = irLocal->nestedDepth;
const auto funcdepth = irfunc->depth;
@@ -111,20 +126,16 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
} else {
// Load frame pointer and index that...
IF_LOG Logger::println("Lower depth");
val = DtoGEPi(val, 0, vardepth);
offsetToNthField(vardepth);
IF_LOG Logger::cout() << "Frame index: " << *val << '\n';
val = DtoAlignedLoad(
val, (std::string(".frame.") + vdparent->toChars()).c_str());
dereference((std::string(".frame.") + vdparent->toChars()).c_str());
IF_LOG Logger::cout() << "Frame: " << *val << '\n';
}
const auto idx = irLocal->nestedIndex;
assert(idx != -1 && "Nested context not yet resolved for variable.");
LLSmallVector<int64_t, 2> dwarfAddrOps;
LLValue *gep = DtoGEPi(val, 0, idx, vd->toChars());
val = gep;
offsetToNthField(idx, vd->toChars());
IF_LOG {
Logger::cout() << "Addr: " << *val << '\n';
Logger::cout() << "of type: " << *val->getType() << '\n';
@@ -135,8 +146,8 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
// storage of pointer (reference lvalue).
} else if (byref || isRefOrOut) {
val = DtoAlignedLoad(val);
// ref/out variables get a reference-debuginfo-type in EmitLocalVariable();
// pass the GEP as reference lvalue in that case.
// ref/out variables get a reference-debuginfo-type in EmitLocalVariable()
// => don't dereference, use reference lvalue as address
if (!isRefOrOut)
gIR->DBuilder.OpDeref(dwarfAddrOps);
IF_LOG {
@@ -147,11 +158,9 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
if (!skipDIDeclaration && global.params.symdebug) {
#if LDC_LLVM_VER < 500
// Because we are passing a GEP instead of an alloca to
// llvm.dbg.declare, we have to make the address dereference explicit.
gIR->DBuilder.OpDeref(dwarfAddrOps);
#endif
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false,
gIR->DBuilder.EmitLocalVariable(ctx, vd, nullptr, false,
/*forceAsLocal=*/true, false, dwarfAddrOps);
}

This file was deleted.

Oops, something went wrong.
@@ -1,11 +1,10 @@
// REQUIRES: atleast_llvm500
// REQUIRES: atmost_llvm501
// REQUIRES: Windows
// REQUIRES: cdb
// RUN: %ldc -g -of=%t.exe %s
// RUN: sed -e "/^\\/\\/ CDB:/!d" -e "s,// CDB:,," %s \
// RUN: | %cdb -snul -lines -y . %t.exe >%t.out
// RUN: FileCheck %s -check-prefix=CHECK -check-prefix=%arch < %t.out
// RUN: FileCheck %s < %t.out
// CDB: ld /f nested_cdb*
// enable case sensitive symbol lookup
@@ -14,7 +13,7 @@
void encloser(int arg0, ref int arg1)
{
int enc_n = 123;
// CDB: bp `nested_cdb.d:17`
// CDB: bp `nested_cdb.d:16`
// CDB: g
// CDB: dv /t
// CHECK: int arg0 = 0n1
@@ -28,7 +27,7 @@ void encloser(int arg0, ref int arg1)
void nested(int nes_i)
{
int blub = arg0 + arg1 + enc_n;
// CDB: bp `nested_cdb.d:31`
// CDB: bp `nested_cdb.d:30`
// CDB: g
// CDB: dv /t
// CHECK: int arg0 = 0n1
@@ -37,7 +36,7 @@ void encloser(int arg0, ref int arg1)
// CDB: ?? *arg1
// CHECK: int 0n2
arg0 = arg1 = enc_n = nes_i;
// CDB: bp `nested_cdb.d:40`
// CDB: bp `nested_cdb.d:39`
// CDB: g
// CDB: dv /t
// CHECK: int arg0 = 0n456
@@ -48,15 +47,14 @@ void encloser(int arg0, ref int arg1)
}
nested(456);
// CDB: bp `nested_cdb.d:51`
// CDB: bp `nested_cdb.d:50`
// CDB: g
// CDB: dv /t
// the following values are garbage on Win32...
// x64: int arg0 = 0n456
// x64-NEXT: int * arg1 = {{0x[0-9a-f`]*}}
// x64-NEXT: int enc_n = 0n456
// CHECK: int arg0 = 0n456
// CHECK-NEXT: int * arg1 = {{0x[0-9a-f`]*}}
// CHECK-NEXT: int enc_n = 0n456
// CDB: ?? *arg1
// x64: int 0n456
// CHECK: int 0n456
}
void main()

0 comments on commit 32b6e49

Please sign in to comment.