Skip to content

Commit ac2c3fd

Browse files
authored
Merge pull request ldc-developers#2315 from kinke/di_small
Adapt to LLVM 5.0 debuginfo changes & misc. fixes, mainly for Win64
2 parents eedcb3d + e4e7eaa commit ac2c3fd

File tree

7 files changed

+276
-66
lines changed

7 files changed

+276
-66
lines changed

gen/dibuilder.cpp

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,26 @@ ldc::DIScope ldc::DIBuilder::GetCurrentScope() {
113113
return fn->diLexicalBlocks.top();
114114
}
115115

116-
void ldc::DIBuilder::Declare(const Loc &loc, llvm::Value *var,
116+
// Sets the memory address for a debuginfo variable.
117+
void ldc::DIBuilder::Declare(const Loc &loc, llvm::Value *storage,
117118
ldc::DILocalVariable divar,
118119
ldc::DIExpression diexpr) {
119120
unsigned charnum = (loc.linnum ? loc.charnum : 0);
120121
auto debugLoc = llvm::DebugLoc::get(loc.linnum, charnum, GetCurrentScope());
121-
DBuilder.insertDeclare(var, divar, diexpr, debugLoc, IR->scopebb());
122+
DBuilder.insertDeclare(storage, divar, diexpr, debugLoc, IR->scopebb());
123+
}
124+
125+
// Sets the (current) value for a debuginfo variable.
126+
void ldc::DIBuilder::SetValue(const Loc &loc, llvm::Value *value,
127+
ldc::DILocalVariable divar,
128+
ldc::DIExpression diexpr) {
129+
unsigned charnum = (loc.linnum ? loc.charnum : 0);
130+
auto debugLoc = llvm::DebugLoc::get(loc.linnum, charnum, GetCurrentScope());
131+
DBuilder.insertDbgValueIntrinsic(value,
132+
#if LDC_LLVM_VER < 600
133+
0,
134+
#endif
135+
divar, diexpr, debugLoc, IR->scopebb());
122136
}
123137

124138
ldc::DIFile ldc::DIBuilder::CreateFile(Loc &loc) {
@@ -1020,7 +1034,7 @@ void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) {
10201034

10211035
void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
10221036
Type *type, bool isThisPtr,
1023-
bool forceAsLocal,
1037+
bool forceAsLocal, bool isRefRVal,
10241038
llvm::ArrayRef<int64_t> addr) {
10251039
if (!mustEmitFullDebugInfo())
10261040
return;
@@ -1040,12 +1054,28 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
10401054
if (static_cast<llvm::MDNode *>(TD) == nullptr)
10411055
return; // unsupported
10421056

1043-
if (vd->isRef() || vd->isOut()) {
1057+
const bool isRefOrOut = vd->isRef() || vd->isOut(); // incl. special-ref vars
1058+
1059+
// For MSVC x64 targets, declare params rewritten by ExplicitByvalRewrite as
1060+
// DI references, as if they were ref parameters.
1061+
const bool isPassedExplicitlyByval =
1062+
isTargetMSVCx64 && !isRefOrOut && isaArgument(ll) && addr.empty();
1063+
1064+
bool useDbgValueIntrinsic = false;
1065+
if (isRefOrOut || isPassedExplicitlyByval) {
1066+
// With the exception of special-ref loop variables, the reference/pointer
1067+
// itself is constant. So we don't have to attach the debug information to a
1068+
// memory location and can use llvm.dbg.value to set the constant pointer
1069+
// for the DI reference.
1070+
useDbgValueIntrinsic =
1071+
isPassedExplicitlyByval || (!isSpecialRefVar(vd) && isRefRVal);
10441072
#if LDC_LLVM_VER >= 308
1045-
auto T = DtoType(type);
1046-
TD = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, TD,
1047-
getTypeAllocSize(T) * 8, // size (bits)
1048-
DtoAlignment(type) * 8); // align (bits)
1073+
// Note: createReferenceType expects the size to be the size of a pointer,
1074+
// not the size of the type the reference refers to.
1075+
TD = DBuilder.createReferenceType(
1076+
llvm::dwarf::DW_TAG_reference_type, TD,
1077+
gDataLayout->getPointerSizeInBits(), // size (bits)
1078+
DtoAlignment(type) * 8); // align (bits)
10491079
#else
10501080
TD = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, TD);
10511081
#endif
@@ -1122,10 +1152,15 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
11221152
#endif
11231153
variableMap[vd] = debugVariable;
11241154

1125-
// declare
1126-
Declare(vd->loc, ll, debugVariable, addr.empty()
1127-
? DBuilder.createExpression()
1128-
: DBuilder.createExpression(addr));
1155+
if (useDbgValueIntrinsic) {
1156+
SetValue(vd->loc, ll, debugVariable,
1157+
addr.empty() ? DBuilder.createExpression()
1158+
: DBuilder.createExpression(addr));
1159+
} else {
1160+
Declare(vd->loc, ll, debugVariable,
1161+
addr.empty() ? DBuilder.createExpression()
1162+
: DBuilder.createExpression(addr));
1163+
}
11291164
}
11301165

11311166
void ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *llVar,

gen/dibuilder.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,22 @@ class DIBuilder {
115115

116116
/// \brief Emits all things necessary for making debug info for a local
117117
/// variable vd.
118-
/// \param ll LL lvalue of the variable.
118+
/// \param ll LL value which, in combination with `addr`, yields the
119+
/// storage/lvalue of the variable. For special-ref loop variables, specify
120+
/// the storage/lvalue of the reference/pointer.
119121
/// \param vd Variable declaration to emit debug info for.
120122
/// \param type Type of variable if different from vd->type
121123
/// \param isThisPtr Variable is hidden this pointer
122124
/// \param forceAsLocal Emit as local even if the variable is a parameter
123-
/// \param addr An array of complex address operations.
125+
/// \param isRefRVal Only relevant for ref/out parameters: indicates whether
126+
/// ll & addr specify the reference's rvalue, i.e., the lvalue of the original
127+
/// variable, instead of the reference's lvalue.
128+
/// \param addr An array of complex address operations encoding a DWARF
129+
/// expression.
124130
void
125131
EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, Type *type = nullptr,
126132
bool isThisPtr = false, bool forceAsLocal = false,
133+
bool isRefRVal = false,
127134
llvm::ArrayRef<int64_t> addr = llvm::ArrayRef<int64_t>());
128135

129136
/// \brief Emits all things necessary for making debug info for a global
@@ -139,8 +146,10 @@ class DIBuilder {
139146
llvm::LLVMContext &getContext();
140147
Module *getDefinedModule(Dsymbol *s);
141148
DIScope GetCurrentScope();
142-
void Declare(const Loc &loc, llvm::Value *var, ldc::DILocalVariable divar,
149+
void Declare(const Loc &loc, llvm::Value *storage, ldc::DILocalVariable divar,
143150
ldc::DIExpression diexpr);
151+
void SetValue(const Loc &loc, llvm::Value *value, ldc::DILocalVariable divar,
152+
ldc::DIExpression diexpr);
144153
void AddFields(AggregateDeclaration *sd, ldc::DIFile file,
145154
llvm::SmallVector<llvm::Metadata *, 16> &elems);
146155
DIFile CreateFile(Loc &loc);

gen/functions.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -768,8 +768,14 @@ void defineParameters(IrFuncTy &irFty, VarDeclarations &parameters) {
768768
++llArgIdx;
769769
}
770770

771-
if (global.params.symdebug)
772-
gIR->DBuilder.EmitLocalVariable(irparam->value, vd, paramType);
771+
// The debuginfos for captured params are handled later by
772+
// DtoCreateNestedContext().
773+
if (global.params.symdebug && vd->nestedrefs.dim == 0) {
774+
// Reference (ref/out) parameters have no storage themselves as they are
775+
// constant pointers, so pass the reference rvalue to EmitLocalVariable().
776+
gIR->DBuilder.EmitLocalVariable(irparam->value, vd, paramType, false,
777+
false, /*isRefRVal=*/true);
778+
}
773779
}
774780
}
775781

gen/nested.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,13 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
130130
Logger::cout() << "of type: " << *val->getType() << '\n';
131131
}
132132
const bool isRefOrOut = vd->isRef() || vd->isOut();
133-
if (!isSpecialRefVar(vd) && (byref || isRefOrOut)) {
133+
if (isSpecialRefVar(vd)) {
134+
// Handled appropriately by makeVarDValue() and EmitLocalVariable(), pass
135+
// storage of pointer (reference lvalue).
136+
} else if (byref || isRefOrOut) {
134137
val = DtoAlignedLoad(val);
135-
// ref/out variables get a reference-debuginfo-type in
136-
// DIBuilder::EmitLocalVariable()
138+
// ref/out variables get a reference-debuginfo-type in EmitLocalVariable();
139+
// pass the GEP as reference lvalue in that case.
137140
if (!isRefOrOut)
138141
gIR->DBuilder.OpDeref(dwarfAddrOps);
139142
IF_LOG {
@@ -143,11 +146,13 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
143146
}
144147

145148
if (!skipDIDeclaration && global.params.symdebug) {
149+
#if LDC_LLVM_VER < 500
146150
// Because we are passing a GEP instead of an alloca to
147151
// llvm.dbg.declare, we have to make the address dereference explicit.
148152
gIR->DBuilder.OpDeref(dwarfAddrOps);
149-
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, true,
150-
dwarfAddrOps);
153+
#endif
154+
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false,
155+
/*forceAsLocal=*/true, false, dwarfAddrOps);
151156
}
152157

153158
return makeVarDValue(astype, vd, val);
@@ -471,6 +476,7 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
471476

472477
IrLocal *irLocal = getIrLocal(vd);
473478
LLValue *gep = DtoGEPi(frame, 0, irLocal->nestedIndex, vd->toChars());
479+
LLSmallVector<int64_t, 2> dwarfAddrOps;
474480
if (vd->isParameter()) {
475481
IF_LOG Logger::println("nested param: %s", vd->toChars());
476482
LOG_SCOPE
@@ -481,6 +487,7 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
481487
if (vd->isRef() || vd->isOut()) {
482488
Logger::println("Captured by reference, copying pointer to nested frame");
483489
DtoAlignedStore(parm->value, gep);
490+
// pass GEP as reference lvalue to EmitLocalVariable()
484491
} else {
485492
Logger::println("Copying to nested frame");
486493
// The parameter value is an alloca'd stack slot.
@@ -497,11 +504,13 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
497504
}
498505

499506
if (global.params.symdebug) {
500-
LLSmallVector<int64_t, 2> addr;
507+
#if LDC_LLVM_VER < 500
501508
// Because we are passing a GEP instead of an alloca to
502509
// llvm.dbg.declare, we have to make the address dereference explicit.
503-
gIR->DBuilder.OpDeref(addr);
504-
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, false, addr);
510+
gIR->DBuilder.OpDeref(dwarfAddrOps);
511+
#endif
512+
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, false, false,
513+
dwarfAddrOps);
505514
}
506515
}
507516
}

0 commit comments

Comments
 (0)