Merge pull request #1598 from Syniurge/llvm38-debuginfofix-master

Debug info generation fixes for LLVM >= 3.8
This commit is contained in:
Johan Engelen 2016-07-18 15:12:30 +02:00 committed by GitHub
commit a8761617ac
10 changed files with 161 additions and 15 deletions

View file

@ -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;

View file

@ -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

View file

@ -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);
}
}
}

View file

@ -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");

View file

@ -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
View 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
View 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: ){{$}}

View 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

View 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

View file

@ -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())