Skip to content

Commit

Permalink
DI: Don't use llvm.dbg.declare with non-alloca storage
Browse files Browse the repository at this point in the history
Represent the local or parameter as DI reference instead, using
llvm.dbg.value to set the constant storage/lvalue.

Affects parameters rewritten by ExplicitByvalRewrite and nested
variables, possibly some more.
  • Loading branch information
kinke committed Aug 27, 2017
1 parent 7563930 commit b367f26
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 54 deletions.
14 changes: 8 additions & 6 deletions gen/dibuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1054,13 +1054,15 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
if (static_cast<llvm::MDNode *>(TD) == nullptr)
return; // unsupported

// llvm.dbg.declare only works properly with local allocas.
// Represent variables with non-alloca LL storage as DI references, like `ref`
// and `out` parameters. Their values are constant, so we don't have to attach
// the debug information to a memory location and can use llvm.dbg.value
// instead.
const bool storedInAlloca = llvm::dyn_cast<llvm::AllocaInst>(ll);
bool useDbgValueIntrinsic = false;
if (vd->isRef() || vd->isOut()) {
// `ref` and `out` parameters are not stored locally in an alloca slot, so
// llvm.dbg.declare cannot be used. Their values are constant though, so we
// don't have to attach the debug information to a memory location and can
// use llvm.dbg.value instead.
useDbgValueIntrinsic = !llvm::dyn_cast<llvm::AllocaInst>(ll);
if (!storedInAlloca || vd->isRef() || vd->isOut()) {
useDbgValueIntrinsic = !storedInAlloca;
#if LDC_LLVM_VER >= 308
// Note: createReferenceType expects the size to be the size of a pointer,
// not the size of the type the reference refers to.
Expand Down
98 changes: 58 additions & 40 deletions tests/debuginfo/args_cdb.d
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,21 @@ import core.simd;
// enable case sensitive symbol lookup
// CDB: .symopt-1

struct Small { size_t val; }
struct Large { size_t a, b, c, d, e, f, g, h; }

int byValue(ubyte ub, ushort us, uint ui, ulong ul,
float f, double d, real r,
cdouble c, int delegate() dg, int function() fun,
int[] slice, float[int] aa, ubyte[16] fa,
float4 f4, double4 d4,
Interface ifc, TypeInfo_Class ti, typeof(null) np)
Small small, Large large,
TypeInfo_Class ti, typeof(null) np)
{
// CDB: bp `args_cdb.d:25`
// CDB: bp `args_cdb.d:27`
// CDB: g
// arguments implicitly passed by reference on x64 and not shown if unused
float cim = c.im + fa[7] + dg() + ifc.offset;
float cim = c.im + fa[7] + dg() + large.a;
return 1;
// CHECK: !args_cdb.byValue
// CDB: dv /t
Expand All @@ -42,12 +46,12 @@ int byValue(ubyte ub, ushort us, uint ui, ulong ul,
// CHECK: <function> * fun = {{0x[0-9a-f`]*}}
// x86: struct int[] slice =
// CHECK: unsigned char * aa = {{0x[0-9a-f`]*}}
// "Internal implementation error for fa" with cdb on x64, ok in VS
// x86: unsigned char [16] fa
// CHECK: unsigned char (*)[16] fa
// x86: float [4] f4 = float [4]
// x86: double [4] d4 = double [4]
// x64: Interface * ifc
// x86: Interface ifc
// CHECK: Small small
// x64: Large * large
// x86: Large large
// CHECK: struct TypeInfo_Class * ti = {{0x[0-9a-f`]*}}
// CHECK: void * np = {{0x[0`]*}}

Expand All @@ -64,31 +68,31 @@ int byValue(ubyte ub, ushort us, uint ui, ulong ul,

// CDB: ?? dg
// CHECK: int delegate()
// CHECK-NEXT: context
// CHECK-NEXT: funcptr
// CHECK-NEXT: context :
// CHECK-NEXT: funcptr :
// CHECK-SAME: args_cdb.main.__lambda

// CDB: ?? slice
// CHECK: struct int[]
// CHECK-NEXT: length : 2
// CHECK-NEXT: ptr
// CHECK-NEXT: ptr :

// CDB: ?? fa[1]
// "Internal implementation error for fa" with cdb on x64, ok in VS
// no-x86: unsigned char 0x0e (displays 0xf6)
// CDB: ?? (*fa)[1]
// CHECK: unsigned char 0x0e

// CDB: ?? f4[1]
// CHECK: float 16

// CDB: ?? d4[2]
// CDB: ?? d4[1]
// CHECK: double 17

// CDB: ?? ifc
// CHECK: Interface
// CHECK-NEXT: classinfo
// CHECK-NEXT: vtbl
// x64-NEXT: offset : 0x12
// no-x86-NEXT: offset : 0x12 (displays 0)
// CDB: ?? small
// CHECK: Small
// CHECK-NEXT: val : 0x12

// CDB: ?? large
// CHECK: Large
// CHECK-NEXT: a : 0x13

// CDB: ?? ti
// CHECK: TypeInfo_Class
Expand All @@ -100,9 +104,10 @@ int byPtr(ubyte* ub, ushort* us, uint* ui, ulong* ul,
cdouble* c, int delegate()* dg, int function()* fun,
int[]* slice, float[int]* aa, ubyte[16]* fa,
float4* f4, double4* d4,
Interface* ifc, TypeInfo_Class* ti, typeof(null)* np)
Small* small, Large* large,
TypeInfo_Class* ti, typeof(null)* np)
{
// CDB: bp `args_cdb.d:106`
// CDB: bp `args_cdb.d:110`
// CDB: g
return 3;
// CHECK: !args_cdb.byPtr
Expand All @@ -127,8 +132,8 @@ int byPtr(ubyte* ub, ushort* us, uint* ui, ulong* ul,
// CHECK-NEXT: im : 9
// CDB: ?? *dg
// CHECK: int delegate()
// CHECK-NEXT: context
// CHECK-NEXT: funcptr
// CHECK-NEXT: context :
// CHECK-NEXT: funcptr :
// CHECK-SAME: args_cdb.main.__lambda
// CDB: ?? *fun
// CHECK: <function> *
Expand All @@ -145,13 +150,16 @@ int byPtr(ubyte* ub, ushort* us, uint* ui, ulong* ul,
// CHECK: float 16
// CDB: ?? (*d4)[2]
// CHECK: double 17
// CDB: ?? *ifc
// CHECK: struct Interface
// CHECK: offset : 0x12
// CDB: ?? *small
// CHECK: struct Small
// CHECK-NEXT: val : 0x12
// CDB: ?? *large
// CHECK: struct Large
// CHECK-NEXT: a : 0x13
// CHECK-NEXT: b :
// CDB: ?? *ti
// CHECK: struct TypeInfo_Class
// CHECK-NEXT: m_init : byte[]
// shows bad member values
// CDB: ?? *np
// CHECK: void * {{0x[0`]*}}
}
Expand All @@ -161,9 +169,10 @@ int byRef(ref ubyte ub, ref ushort us, ref uint ui, ref ulong ul,
ref cdouble c, ref int delegate() dg, ref int function() fun,
ref int[] slice, ref float[int] aa, ref ubyte[16] fa,
ref float4 f4, ref double4 d4,
ref Interface ifc, ref TypeInfo_Class ti, ref typeof(null) np)
ref Small small, ref Large large,
ref TypeInfo_Class ti, ref typeof(null) np)
{
// CDB: bp `args_cdb.d:218`
// CDB: bp `args_cdb.d:176`
// CDB: g
// CHECK: !args_cdb.byRef

Expand All @@ -189,7 +198,7 @@ int byRef(ref ubyte ub, ref ushort us, ref uint ui, ref ulong ul,
// CHECK-NEXT: im : 9
// CDB: ?? *dg
// CHECK: int delegate()
// CHECK-NEXT: context
// CHECK-NEXT: context :
// CHECK-NEXT: funcptr : {{0x[0-9a-f`]*}}
// CHECK-SAME: args_cdb.main.__lambda
// CDB: ?? *fun
Expand All @@ -206,16 +215,23 @@ int byRef(ref ubyte ub, ref ushort us, ref uint ui, ref ulong ul,
// CHECK: float 16
// CDB: ?? (*d4)[2]
// CHECK: double 17
// CDB: ?? *ifc
// CHECK: struct Interface
// CHECK: offset : 0x12
// CDB: ?? *small
// CHECK: struct Small
// CHECK-NEXT: val : 0x12
// CDB: ?? *large
// CHECK: struct Large
// CHECK-NEXT: a : 0x13
// CHECK-NEXT: b :
// CDB: ?? *ti
// CHECK: struct TypeInfo_Class * {{0x[0-9a-f`]*}}
// CHECK-NEXT: m_init : byte[]
// CDB: ?? *np
// CHECK: void * {{0x[0`]*}}
// no-CHECK: void * {{0x[0`]*}} (not available)

// needs access to references to actually generate debug info
float cim = c.im + fa[7] + dg() + fun() + slice.length + aa.length + f4[0] + d4[1] +
small.val + large.a + ti.initializer.length;

ub++;
us++;
ui++;
Expand All @@ -231,7 +247,8 @@ int byRef(ref ubyte ub, ref ushort us, ref uint ui, ref ulong ul,
fa[0]++;
f4.array[0] = f4.array[0] + 1;
d4.array[0] = d4.array[0] + 1;
ifc = Interface(typeid(Object), null, 18);
small.val++;
large.a++;
ti = typeid(TypeInfo);
np = null;
return 2;
Expand All @@ -254,13 +271,14 @@ int main()
ubyte[16] fa; fa[] = 14;
float4 f4 = 16;
double4 d4 = 17;
Interface ifc = Interface(typeid(Object), null, 18);
Small small = Small(18);
Large large = Large(19);
TypeInfo_Class ti = typeid(TypeInfo);
typeof(null) np = null;

byValue(ub, us, ui, ul, f, d, r, c, dg, fun, slice, aa, fa, f4, d4, ifc, ti, np);
byPtr(&ub, &us, &ui, &ul, &f, &d, &r, &c, &dg, &fun, &slice, &aa, &fa, &f4, &d4, &ifc, &ti, &np);
byRef(ub, us, ui, ul, f, d, r, c, dg, fun, slice, aa, fa, f4, d4, ifc, ti, np);
byValue(ub, us, ui, ul, f, d, r, c, dg, fun, slice, aa, fa, f4, d4, small, large, ti, np);
byPtr(&ub, &us, &ui, &ul, &f, &d, &r, &c, &dg, &fun, &slice, &aa, &fa, &f4, &d4, &small, &large, &ti, &np);
byRef(ub, us, ui, ul, f, d, r, c, dg, fun, slice, aa, fa, f4, d4, small, large, ti, np);

return 0;
}
Expand Down
8 changes: 4 additions & 4 deletions tests/debuginfo/nested.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@
// CHECK-SAME: !dbg
void encloser(int arg0, int arg1)
{
// CHECK: @llvm.dbg.declare{{.*}}%enc_n{{.*}}enc_n
// CHECK: @llvm.dbg.value{{.*}}%enc_n{{.*}}enc_n
int enc_n;

// CHECK-LABEL: define {{.*}}encloser{{.*}}nested
void nested(int nes_i)
{
// CHECK: %arg0 = getelementptr inbounds %nest.encloser
// CHECK: @llvm.dbg.declare{{.*}}%arg0
// CHECK: @llvm.dbg.value{{.*}}%arg0
// CHECK: %arg1 = getelementptr inbounds %nest.encloser
// CHECK: @llvm.dbg.declare{{.*}}%arg1
// CHECK: @llvm.dbg.value{{.*}}%arg1
// CHECK: %enc_n = getelementptr inbounds %nest.encloser
// CHECK: @llvm.dbg.declare{{.*}}%enc_n
// CHECK: @llvm.dbg.value{{.*}}%enc_n
arg0 = arg1 = enc_n = nes_i; // accessing arg0, arg1 and enc_n from a nested function turns them into closure variables

// nes_i and arg1 have the same parameter index in the generated IR, if both get declared as
Expand Down
8 changes: 4 additions & 4 deletions tests/debuginfo/nested_llvm307.d
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@
// CHECK-LABEL: define {{.*}} @_D{{.*}}8encloser
void encloser(int arg0, int arg1)
{
// CHECK: @llvm.dbg.declare{{.*}}%enc_n{{.*}}enc_n
// CHECK: @llvm.dbg.value{{.*}}%enc_n{{.*}}enc_n
int enc_n;

// CHECK-LABEL: define {{.*}} @_D{{.*}}8encloser{{.*}}nested
void nested(int nes_i)
{
// CHECK: %arg0 = getelementptr inbounds %nest.encloser
// CHECK: @llvm.dbg.declare{{.*}}%arg0
// CHECK: @llvm.dbg.value{{.*}}%arg0
// CHECK: %arg1 = getelementptr inbounds %nest.encloser
// CHECK: @llvm.dbg.declare{{.*}}%arg1
// CHECK: @llvm.dbg.value{{.*}}%arg1
// CHECK: %enc_n = getelementptr inbounds %nest.encloser
// CHECK: @llvm.dbg.declare{{.*}}%enc_n
// CHECK: @llvm.dbg.value{{.*}}%enc_n
arg0 = arg1 = enc_n = nes_i; // accessing arg0, arg1 and enc_n from a nested function turns them into closure variables
}
}
Expand Down

0 comments on commit b367f26

Please sign in to comment.