Fix debuginfos for nested ref/out parameters (use llvm.dbg.declare)

llvm.dbg.value() apparently doesn't like GEP + deref, so use
llvm.dbg.declare() & GEP.
This commit is contained in:
Martin 2017-09-07 23:12:07 +02:00
parent 93decabe6c
commit 8cc5ff6e79
6 changed files with 55 additions and 35 deletions

View file

@ -1034,7 +1034,7 @@ void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) {
void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
Type *type, bool isThisPtr,
bool forceAsLocal,
bool forceAsLocal, bool isRefRVal,
llvm::ArrayRef<int64_t> addr) {
if (!mustEmitFullDebugInfo())
return;
@ -1054,16 +1054,21 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
if (static_cast<llvm::MDNode *>(TD) == nullptr)
return; // unsupported
const bool isRefOrOut = vd->isRef() || vd->isOut(); // incl. special-ref vars
// For MSVC x64 targets, declare params rewritten by ExplicitByvalRewrite as
// DI references, as if they were ref parameters.
const bool isPassedExplicitlyByval =
isTargetMSVCx64 && !isRefOrOut && isaArgument(ll) && addr.empty();
bool useDbgValueIntrinsic = false;
if (vd->isRef() || vd->isOut() ||
// For MSVC x64 targets, declare params rewritten by ExplicitByvalRewrite
// as DI references, as if they were ref parameters.
(isTargetMSVCx64 && isaArgument(ll) && addr.empty())) {
if (isRefOrOut || isPassedExplicitlyByval) {
// With the exception of special-ref loop variables, the reference/pointer
// itself is constant. So we don't have to attach the debug information to a
// memory location and can use llvm.dbg.value to set the constant pointer
// for the DI reference.
useDbgValueIntrinsic = !isSpecialRefVar(vd);
useDbgValueIntrinsic =
isPassedExplicitlyByval || (!isSpecialRefVar(vd) && isRefRVal);
#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.

View file

@ -116,19 +116,21 @@ public:
/// \brief Emits all things necessary for making debug info for a local
/// variable vd.
/// \param ll LL value which, in combination with `addr`, yields the
/// storage/lvalue of the variable (not treating ref/out params as special
/// case; what's needed is the lvalue of the original variable).
/// For special-ref loop variables, specify the lvalue of the reference/
/// pointer.
/// storage/lvalue of the variable. For special-ref loop variables, specify
/// the storage/lvalue of the reference/pointer.
/// \param vd Variable declaration to emit debug info for.
/// \param type Type of variable if different from vd->type
/// \param isThisPtr Variable is hidden this pointer
/// \param forceAsLocal Emit as local even if the variable is a parameter
/// \param isRefRVal Only relevant for ref/out parameters: indicates whether
/// ll & addr specify the reference's rvalue, i.e., the lvalue of the original
/// variable, instead of the reference's lvalue.
/// \param addr An array of complex address operations encoding a DWARF
/// expression.
void
EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, Type *type = nullptr,
bool isThisPtr = false, bool forceAsLocal = false,
bool isRefRVal = false,
llvm::ArrayRef<int64_t> addr = llvm::ArrayRef<int64_t>());
/// \brief Emits all things necessary for making debug info for a global

View file

@ -770,8 +770,12 @@ void defineParameters(IrFuncTy &irFty, VarDeclarations &parameters) {
// The debuginfos for captured params are handled later by
// DtoCreateNestedContext().
if (global.params.symdebug && vd->nestedrefs.dim == 0)
gIR->DBuilder.EmitLocalVariable(irparam->value, vd, paramType);
if (global.params.symdebug && vd->nestedrefs.dim == 0) {
// Reference (ref/out) parameters have no storage themselves as they are
// constant pointers, so pass the reference rvalue to EmitLocalVariable().
gIR->DBuilder.EmitLocalVariable(irparam->value, vd, paramType, false,
false, /*isRefRVal=*/true);
}
}
}

View file

@ -129,16 +129,16 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
Logger::cout() << "Addr: " << *val << '\n';
Logger::cout() << "of type: " << *val->getType() << '\n';
}
const bool isRefOrOut = vd->isRef() || vd->isOut();
if (isSpecialRefVar(vd)) {
// Handled appropriately by makeVarDValue() and
// DIBuilder::EmitLocalVariable(), pass storage of pointer (reference
// lvalue).
} else if (byref || vd->isRef() || vd->isOut()) {
// makeVarDValue() and DIBuilder::EmitLocalVariable() expect the original
// variable's lvalue for ref/out params too (i.e., the reference rvalue),
// so always dereference.
// Handled appropriately by makeVarDValue() and EmitLocalVariable(), pass
// storage of pointer (reference lvalue).
} else if (byref || isRefOrOut) {
val = DtoAlignedLoad(val);
gIR->DBuilder.OpDeref(dwarfAddrOps);
// ref/out variables get a reference-debuginfo-type in EmitLocalVariable();
// pass the GEP as reference lvalue in that case.
if (!isRefOrOut)
gIR->DBuilder.OpDeref(dwarfAddrOps);
IF_LOG {
Logger::cout() << "Was byref, now: " << *irLocal->value << '\n';
Logger::cout() << "of type: " << *irLocal->value->getType() << '\n';
@ -146,8 +146,8 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
}
if (!skipDIDeclaration && global.params.symdebug) {
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, true,
dwarfAddrOps);
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false,
/*forceAsLocal=*/true, false, dwarfAddrOps);
}
return makeVarDValue(astype, vd, val);
@ -482,7 +482,7 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
if (vd->isRef() || vd->isOut()) {
Logger::println("Captured by reference, copying pointer to nested frame");
DtoAlignedStore(parm->value, gep);
gIR->DBuilder.OpDeref(dwarfAddrOps);
// pass GEP as reference lvalue to EmitLocalVariable()
} else {
Logger::println("Copying to nested frame");
// The parameter value is an alloca'd stack slot.
@ -499,7 +499,7 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
}
if (global.params.symdebug) {
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, false,
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, false, false,
dwarfAddrOps);
}
}

View file

@ -16,35 +16,44 @@ void encloser(int arg0, ref int arg1)
// CDB: g
// CDB: dv /t
// CHECK: int arg0 = 0n1
// arg1 is missing
// (cdb displays references as pointers)
// CHECK-NEXT: int * arg1 = {{0x[0-9a-f`]*}}
// CHECK-NEXT: int enc_n = 0n123
// CDB: ?? *arg1
// CHECK: int 0n2
enc_n += arg1;
void nested(int nes_i)
{
int blub = arg0 + arg1 + enc_n;
// CDB: bp `nested_cdb.d:26`
// CDB: bp `nested_cdb.d:29`
// CDB: g
// CDB: dv /t
// CHECK: int arg0 = 0n1
// arg1 is missing
// CHECK-NEXT: int * arg1 = {{0x[0-9a-f`]*}}
// CHECK-NEXT: int enc_n = 0n125
// CDB: ?? *arg1
// CHECK: int 0n2
arg0 = arg1 = enc_n = nes_i;
// CDB: bp `nested_cdb.d:33`
// CDB: bp `nested_cdb.d:38`
// CDB: g
// CDB: dv /t
// CHECK: int arg0 = 0n456
// arg1 is missing
// CHECK-NEXT: int * arg1 = {{0x[0-9a-f`]*}}
// CHECK-NEXT: int enc_n = 0n456
// CDB: ?? *arg1
// CHECK: int 0n456
}
nested(456);
// CDB: bp `nested_cdb.d:42`
// CDB: bp `nested_cdb.d:49`
// CDB: g
// CDB: dv /t
// CHECK: int arg0 = 0n456
// arg1 is missing
// CHECK-NEXT: int * arg1 = {{0x[0-9a-f`]*}}
// CHECK-NEXT: int enc_n = 0n456
// CDB: ?? *arg1
// CHECK: int 0n456
}
void main()

View file

@ -12,7 +12,7 @@ void encloser(int arg0, ref int arg1)
// GDB: p arg0
// CHECK: $1 = 1
// GDB: p arg1
// no-CHECK: $2 = 2 (<optimized out>)
// CHECK: $2 = (int &) @{{0x[0-9a-f]*}}: 2
// GDB: p enc_n
// CHECK: $3 = 123
enc_n += arg1;
@ -25,7 +25,7 @@ void encloser(int arg0, ref int arg1)
// GDB: p arg0
// CHECK: $4 = 1
// GDB: p arg1
// no-CHECK: $5 = 2 (<optimized out>)
// CHECK: $5 = (int &) @{{0x[0-9a-f]*}}: 2
// GDB: p enc_n
// CHECK: $6 = 125
arg0 = arg1 = enc_n = nes_i;
@ -34,7 +34,7 @@ void encloser(int arg0, ref int arg1)
// GDB: p arg0
// CHECK: $7 = 456
// GDB: p arg1
// no-CHECK: $8 = 456 (<optimized out>)
// CHECK: $8 = (int &) @{{0x[0-9a-f]*}}: 456
// GDB: p enc_n
// CHECK: $9 = 456
}
@ -45,7 +45,7 @@ void encloser(int arg0, ref int arg1)
// GDB: p arg0
// CHECK: $10 = 456
// GDB: p arg1
// no-CHECK: $11 = 456 (<optimized out>)
// CHECK: $11 = (int &) @{{0x[0-9a-f]*}}: 456
// GDB: p enc_n
// CHECK: $12 = 456
}