mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 16:41:06 +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));
|
||||
|
||||
// FIXME: duplicates?
|
||||
return DBuilder.createFunction(
|
||||
auto SP = DBuilder.createFunction(
|
||||
CU, // context
|
||||
fd->toPrettyChars(), // name
|
||||
getIrFunc(fd)->func->getName(), // linkage name
|
||||
|
@ -667,6 +667,12 @@ ldc::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) {
|
|||
getIrFunc(fd)->func
|
||||
#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,
|
||||
|
@ -695,7 +701,7 @@ ldc::DISubprogram ldc::DIBuilder::EmitThunk(llvm::Function *Thunk,
|
|||
name.append(".__thunk");
|
||||
|
||||
// FIXME: duplicates?
|
||||
return DBuilder.createFunction(
|
||||
auto SP = DBuilder.createFunction(
|
||||
CU, // context
|
||||
name, // name
|
||||
Thunk->getName(), // linkage name
|
||||
|
@ -712,6 +718,12 @@ ldc::DISubprogram ldc::DIBuilder::EmitThunk(llvm::Function *Thunk,
|
|||
getIrFunc(fd)->func
|
||||
#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,
|
||||
|
@ -756,7 +768,7 @@ ldc::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function *Fn,
|
|||
#endif
|
||||
|
||||
// FIXME: duplicates?
|
||||
return DBuilder.createFunction(
|
||||
auto SP = DBuilder.createFunction(
|
||||
CU, // context
|
||||
prettyname, // name
|
||||
Fn->getName(), // linkage name
|
||||
|
@ -773,6 +785,10 @@ ldc::DISubprogram ldc::DIBuilder::EmitModuleCTor(llvm::Function *Fn,
|
|||
Fn
|
||||
#endif
|
||||
);
|
||||
#if LDC_LLVM_VER >= 308
|
||||
Fn->setSubprogram(SP);
|
||||
#endif
|
||||
return SP;
|
||||
}
|
||||
|
||||
void ldc::DIBuilder::EmitFuncStart(FuncDeclaration *fd) {
|
||||
|
@ -858,6 +874,11 @@ void ldc::DIBuilder::EmitStopPoint(Loc &loc) {
|
|||
LOG_SCOPE;
|
||||
IR->ir->SetCurrentDebugLocation(
|
||||
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) {
|
||||
|
@ -884,7 +905,7 @@ void ldc::DIBuilder::EmitValue(llvm::Value *val, 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
|
||||
llvm::ArrayRef<int64_t> addr
|
||||
#else
|
||||
|
@ -919,7 +940,7 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
|||
|
||||
#if LDC_LLVM_VER < 308
|
||||
unsigned tag;
|
||||
if (vd->isParameter()) {
|
||||
if (!fromNested && vd->isParameter()) {
|
||||
tag = llvm::dwarf::DW_TAG_arg_variable;
|
||||
} else {
|
||||
tag = llvm::dwarf::DW_TAG_auto_variable;
|
||||
|
@ -963,7 +984,7 @@ void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
|
|||
Flags // flags
|
||||
);
|
||||
#else
|
||||
if (vd->isParameter()) {
|
||||
if (!fromNested && vd->isParameter()) {
|
||||
FuncDeclaration *fd = vd->parent->isFuncDeclaration();
|
||||
assert(fd);
|
||||
size_t argNo = 0;
|
||||
|
|
|
@ -87,6 +87,8 @@ class DIBuilder {
|
|||
#endif
|
||||
}
|
||||
|
||||
Loc currentLoc;
|
||||
|
||||
public:
|
||||
explicit DIBuilder(IRState *const IR);
|
||||
|
||||
|
@ -127,6 +129,8 @@ public:
|
|||
/// \brief Emits debug info for block end
|
||||
void EmitBlockEnd();
|
||||
|
||||
Loc GetCurrentLoc() const;
|
||||
|
||||
void EmitStopPoint(Loc &loc);
|
||||
|
||||
void EmitValue(llvm::Value *val, VarDeclaration *vd);
|
||||
|
@ -137,10 +141,11 @@ public:
|
|||
/// \param vd Variable declaration to emit debug info for.
|
||||
/// \param type Type of parameter if diferent from vd->type
|
||||
/// \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.
|
||||
void
|
||||
EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, Type *type = nullptr,
|
||||
bool isThisPtr = false,
|
||||
bool isThisPtr = false, bool fromNested = false,
|
||||
#if LDC_LLVM_VER >= 306
|
||||
llvm::ArrayRef<int64_t> addr = llvm::ArrayRef<int64_t>()
|
||||
#else
|
||||
|
|
|
@ -154,7 +154,7 @@ DValue *DtoNestedVariable(Loc &loc, Type *astype, VarDeclaration *vd,
|
|||
}
|
||||
|
||||
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);
|
||||
|
@ -508,7 +508,7 @@ void DtoCreateNestedContext(FuncDeclaration *fd) {
|
|||
LLSmallVector<LLValue *, 2> addr;
|
||||
#endif
|
||||
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");
|
||||
}
|
||||
irs->scope() = save;
|
||||
irs->DBuilder.EmitStopPoint(ctch->loc); // re-set debug loc after the
|
||||
// SetInsertPoint(allocaInst) call
|
||||
} else if (ctch->type) {
|
||||
// catch without var
|
||||
exnObj = DtoAlloca(ctch->type, "exnObj");
|
||||
|
|
|
@ -283,21 +283,30 @@ llvm::BasicBlock *ScopeStack::runCleanupPad(CleanupCursor scope,
|
|||
// can place an exception frame (but not done here)
|
||||
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");
|
||||
llvm::CallInst::Create(endFn, frame,
|
||||
{llvm::OperandBundleDef("funclet", cleanuppad)}, "",
|
||||
cleanupret);
|
||||
irs->ir->SetInsertPoint(cleanupret);
|
||||
irs->DBuilder.EmitStopPoint(irs->func()->decl->loc);
|
||||
irs->ir->CreateCall(endFn, frame,
|
||||
{llvm::OperandBundleDef("funclet", cleanuppad)}, "");
|
||||
llvm::CleanupReturnInst::Create(cleanuppad, unwindTo, cleanupret);
|
||||
|
||||
auto copybb = executeCleanupCopying(irs, cleanupScopes[scope], cleanupbb,
|
||||
cleanupret, unwindTo, cleanuppad);
|
||||
|
||||
auto beginFn = getRuntimeFunction(Loc(), irs->module, "_d_enter_cleanup");
|
||||
auto exec = llvm::CallInst::Create(
|
||||
beginFn, frame, {llvm::OperandBundleDef("funclet", cleanuppad)}, "",
|
||||
cleanupbb);
|
||||
irs->ir->SetInsertPoint(cleanupbb);
|
||||
irs->DBuilder.EmitStopPoint(irs->func()->decl->loc);
|
||||
auto exec = irs->ir->CreateCall(
|
||||
beginFn, frame, {llvm::OperandBundleDef("funclet", cleanuppad)}, "");
|
||||
llvm::BranchInst::Create(copybb, cleanupret, exec, cleanupbb);
|
||||
|
||||
irs->ir->SetInsertPoint(savedInsertBlock, savedInsertPoint);
|
||||
irs->DBuilder.EmitStopPoint(savedDbgLoc);
|
||||
|
||||
return cleanupbb;
|
||||
}
|
||||
#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)
|
||||
for version in range(305, config.llvm_version+1):
|
||||
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)
|
||||
config.available_features.add(platform.system())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue