mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-04 17:11:44 +03:00
Merge pull request #1598 from Syniurge/llvm38-debuginfofix-master
Debug info generation fixes for LLVM >= 3.8
This commit is contained in:
commit
a8761617ac
10 changed files with 161 additions and 15 deletions
|
@ -650,7 +650,7 @@ ldc::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) {
|
||||||
CreateFunctionType(static_cast<TypeFunction *>(fd->type));
|
CreateFunctionType(static_cast<TypeFunction *>(fd->type));
|
||||||
|
|
||||||
// FIXME: duplicates?
|
// FIXME: duplicates?
|
||||||
return DBuilder.createFunction(
|
auto SP = DBuilder.createFunction(
|
||||||
CU, // context
|
CU, // context
|
||||||
fd->toPrettyChars(), // name
|
fd->toPrettyChars(), // name
|
||||||
getIrFunc(fd)->func->getName(), // linkage name
|
getIrFunc(fd)->func->getName(), // linkage name
|
||||||
|
@ -667,6 +667,12 @@ ldc::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) {
|
||||||
getIrFunc(fd)->func
|
getIrFunc(fd)->func
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
#if LDC_LLVM_VER >= 308
|
||||||
|
if (fd->fbody) {
|
||||||
|
getIrFunc(fd)->func->setSubprogram(SP);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return SP;
|
||||||
}
|
}
|
||||||
|
|
||||||
ldc::DISubprogram ldc::DIBuilder::EmitThunk(llvm::Function *Thunk,
|
ldc::DISubprogram ldc::DIBuilder::EmitThunk(llvm::Function *Thunk,
|
||||||
|
@ -695,7 +701,7 @@ ldc::DISubprogram ldc::DIBuilder::EmitThunk(llvm::Function *Thunk,
|
||||||
name.append(".__thunk");
|
name.append(".__thunk");
|
||||||
|
|
||||||
// FIXME: duplicates?
|
// FIXME: duplicates?
|
||||||
return DBuilder.createFunction(
|
auto SP = DBuilder.createFunction(
|
||||||
CU, // context
|
CU, // context
|
||||||
name, // name
|
name, // name
|
||||||
Thunk->getName(), // linkage name
|
Thunk->getName(), // linkage name
|
||||||
|
@ -712,6 +718,12 @@ ldc::DISubprogram ldc::DIBuilder::EmitThunk(llvm::Function *Thunk,
|
||||||
getIrFunc(fd)->func
|
getIrFunc(fd)->func
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
#if LDC_LLVM_VER >= 308
|
||||||
|
if (fd->fbody) {
|
||||||
|
getIrFunc(fd)->func->setSubprogram(SP);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return SP;
|
||||||
}
|
}
|
||||||
|
|
||||||
ldc::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function *Fn,
|
ldc::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function *Fn,
|
||||||
|
@ -756,7 +768,7 @@ ldc::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function *Fn,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FIXME: duplicates?
|
// FIXME: duplicates?
|
||||||
return DBuilder.createFunction(
|
auto SP = DBuilder.createFunction(
|
||||||
CU, // context
|
CU, // context
|
||||||
prettyname, // name
|
prettyname, // name
|
||||||
Fn->getName(), // linkage name
|
Fn->getName(), // linkage name
|
||||||
|
@ -773,6 +785,10 @@ ldc::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function *Fn,
|
||||||
Fn
|
Fn
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
#if LDC_LLVM_VER >= 308
|
||||||
|
Fn->setSubprogram(SP);
|
||||||
|
#endif
|
||||||
|
return SP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ldc::DIBuilder::EmitFuncStart(FuncDeclaration *fd) {
|
void ldc::DIBuilder::EmitFuncStart(FuncDeclaration *fd) {
|
||||||
|
@ -858,6 +874,11 @@ void ldc::DIBuilder::EmitStopPoint(Loc &loc) {
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
IR->ir->SetCurrentDebugLocation(
|
IR->ir->SetCurrentDebugLocation(
|
||||||
llvm::DebugLoc::get(loc.linnum, charnum, GetCurrentScope()));
|
llvm::DebugLoc::get(loc.linnum, charnum, GetCurrentScope()));
|
||||||
|
currentLoc = loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loc ldc::DIBuilder::GetCurrentLoc() const {
|
||||||
|
return currentLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) {
|
void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) {
|
||||||
|
@ -884,7 +905,7 @@ void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
||||||
Type *type, bool isThisPtr,
|
Type *type, bool isThisPtr, bool fromNested,
|
||||||
#if LDC_LLVM_VER >= 306
|
#if LDC_LLVM_VER >= 306
|
||||||
llvm::ArrayRef<int64_t> addr
|
llvm::ArrayRef<int64_t> addr
|
||||||
#else
|
#else
|
||||||
|
@ -919,7 +940,7 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
||||||
|
|
||||||
#if LDC_LLVM_VER < 308
|
#if LDC_LLVM_VER < 308
|
||||||
unsigned tag;
|
unsigned tag;
|
||||||
if (vd->isParameter()) {
|
if (!fromNested && vd->isParameter()) {
|
||||||
tag = llvm::dwarf::DW_TAG_arg_variable;
|
tag = llvm::dwarf::DW_TAG_arg_variable;
|
||||||
} else {
|
} else {
|
||||||
tag = llvm::dwarf::DW_TAG_auto_variable;
|
tag = llvm::dwarf::DW_TAG_auto_variable;
|
||||||
|
@ -963,7 +984,7 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
||||||
Flags // flags
|
Flags // flags
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
if (vd->isParameter()) {
|
if (!fromNested && vd->isParameter()) {
|
||||||
FuncDeclaration *fd = vd->parent->isFuncDeclaration();
|
FuncDeclaration *fd = vd->parent->isFuncDeclaration();
|
||||||
assert(fd);
|
assert(fd);
|
||||||
size_t argNo = 0;
|
size_t argNo = 0;
|
||||||
|
|
|
@ -87,6 +87,8 @@ class DIBuilder {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loc currentLoc;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DIBuilder(IRState *const IR);
|
explicit DIBuilder(IRState *const IR);
|
||||||
|
|
||||||
|
@ -127,6 +129,8 @@ public:
|
||||||
/// \brief Emits debug info for block end
|
/// \brief Emits debug info for block end
|
||||||
void EmitBlockEnd();
|
void EmitBlockEnd();
|
||||||
|
|
||||||
|
Loc GetCurrentLoc() const;
|
||||||
|
|
||||||
void EmitStopPoint(Loc &loc);
|
void EmitStopPoint(Loc &loc);
|
||||||
|
|
||||||
void EmitValue(llvm::Value *val, VarDeclaration *vd);
|
void EmitValue(llvm::Value *val, VarDeclaration *vd);
|
||||||
|
@ -137,10 +141,11 @@ public:
|
||||||
/// \param vd Variable declaration to emit debug info for.
|
/// \param vd Variable declaration to emit debug info for.
|
||||||
/// \param type Type of parameter if diferent from vd->type
|
/// \param type Type of parameter if diferent from vd->type
|
||||||
/// \param isThisPtr Parameter is hidden this pointer
|
/// \param isThisPtr Parameter is hidden this pointer
|
||||||
|
/// \param fromNested Is a closure variable accessed through nest_arg
|
||||||
/// \param addr An array of complex address operations.
|
/// \param addr An array of complex address operations.
|
||||||
void
|
void
|
||||||
EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, Type *type = nullptr,
|
EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, Type *type = nullptr,
|
||||||
bool isThisPtr = false,
|
bool isThisPtr = false, bool fromNested = false,
|
||||||
#if LDC_LLVM_VER >= 306
|
#if LDC_LLVM_VER >= 306
|
||||||
llvm::ArrayRef<int64_t> addr = llvm::ArrayRef<int64_t>()
|
llvm::ArrayRef<int64_t> addr = llvm::ArrayRef<int64_t>()
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -154,7 +154,7 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwarfValue && global.params.symdebug) {
|
if (dwarfValue && global.params.symdebug) {
|
||||||
gIR->DBuilder.EmitLocalVariable(dwarfValue, vd, nullptr, false, dwarfAddr);
|
gIR->DBuilder.EmitLocalVariable(dwarfValue, vd, nullptr, false, /*fromNested=*/ true, dwarfAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeVarDValue(astype, vd, val);
|
return makeVarDValue(astype, vd, val);
|
||||||
|
@ -508,7 +508,7 @@ void DtoCreateNestedContext(FuncDeclaration *fd) {
|
||||||
LLSmallVector<LLValue *, 2> addr;
|
LLSmallVector<LLValue *, 2> addr;
|
||||||
#endif
|
#endif
|
||||||
gIR->DBuilder.OpOffset(addr, frameType, irLocal->nestedIndex);
|
gIR->DBuilder.OpOffset(addr, frameType, irLocal->nestedIndex);
|
||||||
gIR->DBuilder.EmitLocalVariable(gep, vd, nullptr, false, addr);
|
gIR->DBuilder.EmitLocalVariable(frame, vd, nullptr, false, false, addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -837,6 +837,8 @@ public:
|
||||||
exnObj = DtoAlloca(var->type, "exnObj");
|
exnObj = DtoAlloca(var->type, "exnObj");
|
||||||
}
|
}
|
||||||
irs->scope() = save;
|
irs->scope() = save;
|
||||||
|
irs->DBuilder.EmitStopPoint(ctch->loc); // re-set debug loc after the
|
||||||
|
// SetInsertPoint(allocaInst) call
|
||||||
} else if (ctch->type) {
|
} else if (ctch->type) {
|
||||||
// catch without var
|
// catch without var
|
||||||
exnObj = DtoAlloca(ctch->type, "exnObj");
|
exnObj = DtoAlloca(ctch->type, "exnObj");
|
||||||
|
|
|
@ -283,21 +283,30 @@ llvm::BasicBlock *ScopeStack::runCleanupPad(CleanupCursor scope,
|
||||||
// can place an exception frame (but not done here)
|
// can place an exception frame (but not done here)
|
||||||
auto frame = getNullPtr(getVoidPtrType());
|
auto frame = getNullPtr(getVoidPtrType());
|
||||||
|
|
||||||
|
auto savedInsertBlock = irs->ir->GetInsertBlock();
|
||||||
|
auto savedInsertPoint = irs->ir->GetInsertPoint();
|
||||||
|
auto savedDbgLoc = irs->DBuilder.GetCurrentLoc();
|
||||||
|
|
||||||
auto endFn = getRuntimeFunction(Loc(), irs->module, "_d_leave_cleanup");
|
auto endFn = getRuntimeFunction(Loc(), irs->module, "_d_leave_cleanup");
|
||||||
llvm::CallInst::Create(endFn, frame,
|
irs->ir->SetInsertPoint(cleanupret);
|
||||||
{llvm::OperandBundleDef("funclet", cleanuppad)}, "",
|
irs->DBuilder.EmitStopPoint(irs->func()->decl->loc);
|
||||||
cleanupret);
|
irs->ir->CreateCall(endFn, frame,
|
||||||
|
{llvm::OperandBundleDef("funclet", cleanuppad)}, "");
|
||||||
llvm::CleanupReturnInst::Create(cleanuppad, unwindTo, cleanupret);
|
llvm::CleanupReturnInst::Create(cleanuppad, unwindTo, cleanupret);
|
||||||
|
|
||||||
auto copybb = executeCleanupCopying(irs, cleanupScopes[scope], cleanupbb,
|
auto copybb = executeCleanupCopying(irs, cleanupScopes[scope], cleanupbb,
|
||||||
cleanupret, unwindTo, cleanuppad);
|
cleanupret, unwindTo, cleanuppad);
|
||||||
|
|
||||||
auto beginFn = getRuntimeFunction(Loc(), irs->module, "_d_enter_cleanup");
|
auto beginFn = getRuntimeFunction(Loc(), irs->module, "_d_enter_cleanup");
|
||||||
auto exec = llvm::CallInst::Create(
|
irs->ir->SetInsertPoint(cleanupbb);
|
||||||
beginFn, frame, {llvm::OperandBundleDef("funclet", cleanuppad)}, "",
|
irs->DBuilder.EmitStopPoint(irs->func()->decl->loc);
|
||||||
cleanupbb);
|
auto exec = irs->ir->CreateCall(
|
||||||
|
beginFn, frame, {llvm::OperandBundleDef("funclet", cleanuppad)}, "");
|
||||||
llvm::BranchInst::Create(copybb, cleanupret, exec, cleanupbb);
|
llvm::BranchInst::Create(copybb, cleanupret, exec, cleanupbb);
|
||||||
|
|
||||||
|
irs->ir->SetInsertPoint(savedInsertBlock, savedInsertPoint);
|
||||||
|
irs->DBuilder.EmitStopPoint(savedDbgLoc);
|
||||||
|
|
||||||
return cleanupbb;
|
return cleanupbb;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
34
tests/debuginfo/msvc_eh.d
Executable file
34
tests/debuginfo/msvc_eh.d
Executable file
|
@ -0,0 +1,34 @@
|
||||||
|
// Checks that !dbg is being attached to MSVC EH/cleanup runtime calls.
|
||||||
|
// REQUIRES: atleast_llvm308
|
||||||
|
// REQUIRES: Windows
|
||||||
|
// RUN: %ldc -g -c -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
|
||||||
|
|
||||||
|
struct WithDtor
|
||||||
|
{
|
||||||
|
int z;
|
||||||
|
~this() { z = -1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void throwSome()
|
||||||
|
{
|
||||||
|
throw new Exception("!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: define {{.*}} @{{.*}}foo_msvc
|
||||||
|
// CHECK-SAME: !dbg
|
||||||
|
void foo_msvc()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WithDtor swd_1;
|
||||||
|
swd_1.z = 24;
|
||||||
|
throwSome();
|
||||||
|
}
|
||||||
|
catch(Throwable t)
|
||||||
|
{
|
||||||
|
WithDtor swd_2 = { 48 };
|
||||||
|
}
|
||||||
|
// CHECK-DAG: call {{.*}}@_d_eh_enter_catch{{.*}} !dbg
|
||||||
|
// CHECK-DAG: call {{.*}}@_d_enter_cleanup{{.*}} !dbg
|
||||||
|
// CHECK-DAG: call {{.*}}@_d_leave_cleanup{{.*}} !dbg
|
||||||
|
}
|
28
tests/debuginfo/nested.d
Normal file
28
tests/debuginfo/nested.d
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// Tests debug info generation for nested functions
|
||||||
|
// REQUIRES: atleast_llvm308
|
||||||
|
// RUN: %ldc -g -c -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
|
||||||
|
|
||||||
|
// CHECK: define {{.*}} @{{.*}}encloser
|
||||||
|
// CHECK-SAME: !dbg
|
||||||
|
void encloser(int arg0, int arg1)
|
||||||
|
{
|
||||||
|
// CHECK: @llvm.dbg.declare{{.*}}%.frame{{.*}}enc_n
|
||||||
|
int enc_n;
|
||||||
|
|
||||||
|
// CHECK-LABEL: define {{.*}}encloser{{.*}}nested
|
||||||
|
void nested(int nes_i)
|
||||||
|
{
|
||||||
|
// CHECK: @llvm.dbg.declare{{.*}}%nestedFrame{{.*}}arg1
|
||||||
|
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
|
||||||
|
// function parameters this triggers off an assert in LLVM >=3.8 (see Github PR #1598)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: !DISubprogram(name:{{.*}}"{{.*}}encloser.nested"
|
||||||
|
// CHECK: !DILocalVariable{{.*}}nes_i
|
||||||
|
// CHECK-SAME: arg: 2
|
||||||
|
// CHECK: !DILocalVariable{{.*}}arg1
|
||||||
|
// CHECK-NOT: arg:
|
||||||
|
// CHECK-SAME: ){{$}}
|
22
tests/debuginfo/nested_llvm306.d
Normal file
22
tests/debuginfo/nested_llvm306.d
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// Tests debug info generation for nested functions
|
||||||
|
// REQUIRES: atmost_llvm306
|
||||||
|
// RUN: %ldc -g -c -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
|
||||||
|
|
||||||
|
// CHECK-LABEL: define {{.*}} @_D{{.*}}8encloserFiiZv
|
||||||
|
void encloser(int arg0, int arg1)
|
||||||
|
{
|
||||||
|
// CHECK: @llvm.dbg.declare{{.*}}%.frame{{.*}}enc_n
|
||||||
|
int enc_n;
|
||||||
|
|
||||||
|
// CHECK-LABEL: define {{.*}} @_D{{.*}}encloser{{.*}}nested
|
||||||
|
void nested(int nes_i)
|
||||||
|
{
|
||||||
|
// CHECK: @llvm.dbg.declare{{.*}}%nestedFrame{{.*}}arg1
|
||||||
|
arg0 = arg1 = enc_n = nes_i; // accessing arg0, arg1 and enc_n from a nested function turns them into closure variables
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: @_D{{.*}}8encloserFiiZv{{.*}}DW_TAG_subprogram
|
||||||
|
// CHECK: @_D{{.*}}8encloserFiiZ6nestedMFiZv{{.*}}DW_TAG_subprogram
|
||||||
|
// CHECK: nes_i{{.*}}DW_TAG_arg_variable
|
||||||
|
// CHECK: arg1{{.*}}DW_TAG_auto_variable
|
23
tests/debuginfo/nested_llvm307.d
Normal file
23
tests/debuginfo/nested_llvm307.d
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Tests debug info generation for nested functions
|
||||||
|
// REQUIRES: llvm307
|
||||||
|
// RUN: %ldc -g -c -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
|
||||||
|
|
||||||
|
// CHECK-LABEL: define {{.*}} @_D{{.*}}8encloser
|
||||||
|
void encloser(int arg0, int arg1)
|
||||||
|
{
|
||||||
|
// CHECK: @llvm.dbg.declare{{.*}}%.frame{{.*}}enc_n
|
||||||
|
int enc_n;
|
||||||
|
|
||||||
|
// CHECK-LABEL: define {{.*}} @_D{{.*}}8encloser{{.*}}nested
|
||||||
|
void nested(int nes_i)
|
||||||
|
{
|
||||||
|
// CHECK: @llvm.dbg.declare{{.*}}%nestedFrame{{.*}}arg1
|
||||||
|
arg0 = arg1 = enc_n = nes_i; // accessing arg0, arg1 and enc_n from a nested function turns them into closure variables
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: !DISubprogram(name:{{.*}}"{{.*}}.encloser"
|
||||||
|
// CHECK-SAME: function: void {{.*}} @_D{{.*}}8encloserFiiZv
|
||||||
|
// CHECK-LABEL: !DISubprogram(name:{{.*}}"{{.*}}.encloser.nested"
|
||||||
|
// CHECK: !DILocalVariable{{.*}}DW_TAG_arg_variable{{.*}}nes_i
|
||||||
|
// CHECK: !DILocalVariable{{.*}}DW_TAG_auto_variable{{.*}}arg1
|
|
@ -43,6 +43,8 @@ if not config.with_PGO:
|
||||||
config.available_features.add("llvm%d" % config.llvm_version)
|
config.available_features.add("llvm%d" % config.llvm_version)
|
||||||
for version in range(305, config.llvm_version+1):
|
for version in range(305, config.llvm_version+1):
|
||||||
config.available_features.add("atleast_llvm%d" % version)
|
config.available_features.add("atleast_llvm%d" % version)
|
||||||
|
for version in range(config.llvm_version, 310):
|
||||||
|
config.available_features.add("atmost_llvm%d" % version)
|
||||||
|
|
||||||
# Define OS as available feature (Windows, Darwin, Linux)
|
# Define OS as available feature (Windows, Darwin, Linux)
|
||||||
config.available_features.add(platform.system())
|
config.available_features.add(platform.system())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue