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

View file

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

View file

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

View file

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

View file

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