Skip to content

Commit

Permalink
[RemoveDIs] Update DIBuilder to conditionally insert DbgRecords (#84739)
Browse files Browse the repository at this point in the history
Have DIBuilder conditionally insert either debug intrinsics or DbgRecord
depending on the module's IsNewDbgInfoFormat flag. The insertion methods
now return a `DbgInstPtr` (a `PointerUnion<Instruction *, DbgRecord
*>`).

Add a unittest for both modes (I couldn't find an existing test testing
insertion behaviours specifically).

This patch changes the existing assumption that DbgRecords are only ever
inserted if there's an instruction to insert-before because clang
currently inserts debug intrinsics while CodeGening (like any other
instruction) meaning it'll try inserting to the end of a block without a
terminator. We already have machinery in place to maintain the
DbgRecords when a terminator is removed - these become "trailing
DbgRecords" which are re-attached when a new instruction is inserted.
All I've done is allow this state to occur while inserting DbgRecords
too, i.e., it's not only removing terminators that causes this valid
transient state, but inserting DbgRecords into incomplete blocks too.

The C API will be updated in follow up patches.

---

Note: this doesn't mean clang is emitting DbgRecords yet, because the
modules it creates are still always in the old debug mode. That will
come in a future patch.
  • Loading branch information
OCHyams authored Mar 12, 2024
1 parent ce1fd92 commit 9997e03
Show file tree
Hide file tree
Showing 9 changed files with 358 additions and 187 deletions.
73 changes: 39 additions & 34 deletions llvm/include/llvm/IR/DIBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ namespace llvm {
class Module;
class Value;
class DbgAssignIntrinsic;
class DbgRecord;

using DbgInstPtr = PointerUnion<Instruction *, DbgRecord *>;

class DIBuilder {
Module &M;
Expand Down Expand Up @@ -90,13 +93,17 @@ namespace llvm {
void trackIfUnresolved(MDNode *N);

/// Internal helper for insertDeclare.
Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertBB, Instruction *InsertBefore);
DbgInstPtr insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertBB, Instruction *InsertBefore);

/// Internal helper for insertLabel.
Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL,
BasicBlock *InsertBB, Instruction *InsertBefore);
DbgInstPtr insertLabel(DILabel *LabelInfo, const DILocation *DL,
BasicBlock *InsertBB, Instruction *InsertBefore);

/// Internal helper. Track metadata if untracked and insert \p DPV.
void insertDPValue(DPValue *DPV, BasicBlock *InsertBB,
Instruction *InsertBefore, bool InsertAtHead = false);

/// Internal helper with common code used by insertDbg{Value,Addr}Intrinsic.
Instruction *insertDbgIntrinsic(llvm::Function *Intrinsic, llvm::Value *Val,
Expand All @@ -106,10 +113,11 @@ namespace llvm {
Instruction *InsertBefore);

/// Internal helper for insertDbgValueIntrinsic.
Instruction *
insertDbgValueIntrinsic(llvm::Value *Val, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertBB, Instruction *InsertBefore);
DbgInstPtr insertDbgValueIntrinsic(llvm::Value *Val,
DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertBB,
Instruction *InsertBefore);

public:
/// Construct a builder for a module.
Expand Down Expand Up @@ -921,9 +929,9 @@ namespace llvm {
/// \param Expr A complex location expression.
/// \param DL Debug info location.
/// \param InsertAtEnd Location for the new intrinsic.
Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertAtEnd);
DbgInstPtr insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertAtEnd);

/// Insert a new llvm.dbg.assign intrinsic call.
/// \param LinkedInstr Instruction with a DIAssignID to link with the new
Expand All @@ -939,59 +947,56 @@ namespace llvm {
/// \param DL Debug info location, usually: (line: 0,
/// column: 0, scope: var-decl-scope). See
/// getDebugValueLoc.
DbgAssignIntrinsic *insertDbgAssign(Instruction *LinkedInstr, Value *Val,
DILocalVariable *SrcVar,
DIExpression *ValExpr, Value *Addr,
DIExpression *AddrExpr,
const DILocation *DL);
DbgInstPtr insertDbgAssign(Instruction *LinkedInstr, Value *Val,
DILocalVariable *SrcVar, DIExpression *ValExpr,
Value *Addr, DIExpression *AddrExpr,
const DILocation *DL);

/// Insert a new llvm.dbg.declare intrinsic call.
/// \param Storage llvm::Value of the variable
/// \param VarInfo Variable's debug info descriptor.
/// \param Expr A complex location expression.
/// \param DL Debug info location.
/// \param InsertBefore Location for the new intrinsic.
Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
Instruction *InsertBefore);
DbgInstPtr insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
Instruction *InsertBefore);

/// Insert a new llvm.dbg.label intrinsic call.
/// \param LabelInfo Label's debug info descriptor.
/// \param DL Debug info location.
/// \param InsertBefore Location for the new intrinsic.
Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL,
Instruction *InsertBefore);
DbgInstPtr insertLabel(DILabel *LabelInfo, const DILocation *DL,
Instruction *InsertBefore);

/// Insert a new llvm.dbg.label intrinsic call.
/// \param LabelInfo Label's debug info descriptor.
/// \param DL Debug info location.
/// \param InsertAtEnd Location for the new intrinsic.
Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL,
BasicBlock *InsertAtEnd);
DbgInstPtr insertLabel(DILabel *LabelInfo, const DILocation *DL,
BasicBlock *InsertAtEnd);

/// Insert a new llvm.dbg.value intrinsic call.
/// \param Val llvm::Value of the variable
/// \param VarInfo Variable's debug info descriptor.
/// \param Expr A complex location expression.
/// \param DL Debug info location.
/// \param InsertAtEnd Location for the new intrinsic.
Instruction *insertDbgValueIntrinsic(llvm::Value *Val,
DILocalVariable *VarInfo,
DIExpression *Expr,
const DILocation *DL,
BasicBlock *InsertAtEnd);
DbgInstPtr insertDbgValueIntrinsic(llvm::Value *Val,
DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertAtEnd);

/// Insert a new llvm.dbg.value intrinsic call.
/// \param Val llvm::Value of the variable
/// \param VarInfo Variable's debug info descriptor.
/// \param Expr A complex location expression.
/// \param DL Debug info location.
/// \param InsertBefore Location for the new intrinsic.
Instruction *insertDbgValueIntrinsic(llvm::Value *Val,
DILocalVariable *VarInfo,
DIExpression *Expr,
const DILocation *DL,
Instruction *InsertBefore);
DbgInstPtr insertDbgValueIntrinsic(llvm::Value *Val,
DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
Instruction *InsertBefore);

/// Replace the vtable holder in the given type.
///
Expand Down
13 changes: 3 additions & 10 deletions llvm/lib/IR/BasicBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -754,8 +754,6 @@ void BasicBlock::spliceDebugInfoEmptyBlock(BasicBlock::iterator Dest,
// occur when a block is optimised away and the terminator has been moved
// somewhere else.
if (Src->empty()) {
assert(Dest != end() &&
"Transferring trailing DPValues to another trailing position");
DPMarker *SrcTrailingDPValues = Src->getTrailingDPValues();
if (!SrcTrailingDPValues)
return;
Expand Down Expand Up @@ -1040,15 +1038,10 @@ void BasicBlock::insertDPValueAfter(DbgRecord *DPV, Instruction *I) {

void BasicBlock::insertDPValueBefore(DbgRecord *DPV,
InstListType::iterator Where) {
// We should never directly insert at the end of the block, new DPValues
// shouldn't be generated at times when there's no terminator.
assert(Where != end());
assert(Where->getParent() == this);
if (!Where->DbgMarker)
createMarker(Where);
assert(Where == end() || Where->getParent() == this);
bool InsertAtHead = Where.getHeadBit();
createMarker(&*Where);
Where->DbgMarker->insertDPValue(DPV, InsertAtHead);
DPMarker *M = createMarker(Where);
M->insertDPValue(DPV, InsertAtHead);
}

DPMarker *BasicBlock::getNextMarker(Instruction *I) {
Expand Down
131 changes: 92 additions & 39 deletions llvm/lib/IR/DIBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,35 +925,47 @@ DILexicalBlock *DIBuilder::createLexicalBlock(DIScope *Scope, DIFile *File,
File, Line, Col);
}

Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
Instruction *InsertBefore) {
DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
Instruction *InsertBefore) {
return insertDeclare(Storage, VarInfo, Expr, DL, InsertBefore->getParent(),
InsertBefore);
}

Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertAtEnd) {
DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertAtEnd) {
// If this block already has a terminator then insert this intrinsic before
// the terminator. Otherwise, put it at the end of the block.
Instruction *InsertBefore = InsertAtEnd->getTerminator();
return insertDeclare(Storage, VarInfo, Expr, DL, InsertAtEnd, InsertBefore);
}

DbgAssignIntrinsic *
DIBuilder::insertDbgAssign(Instruction *LinkedInstr, Value *Val,
DILocalVariable *SrcVar, DIExpression *ValExpr,
Value *Addr, DIExpression *AddrExpr,
const DILocation *DL) {
DbgInstPtr DIBuilder::insertDbgAssign(Instruction *LinkedInstr, Value *Val,
DILocalVariable *SrcVar,
DIExpression *ValExpr, Value *Addr,
DIExpression *AddrExpr,
const DILocation *DL) {
auto *Link = cast_or_null<DIAssignID>(
LinkedInstr->getMetadata(LLVMContext::MD_DIAssignID));
assert(Link && "Linked instruction must have DIAssign metadata attached");

if (M.IsNewDbgInfoFormat) {
DPValue *DPV = DPValue::createDPVAssign(Val, SrcVar, ValExpr, Link, Addr,
AddrExpr, DL);
BasicBlock *InsertBB = LinkedInstr->getParent();
// Insert after LinkedInstr.
BasicBlock::iterator NextIt = std::next(LinkedInstr->getIterator());
Instruction *InsertBefore = NextIt == InsertBB->end() ? nullptr : &*NextIt;
insertDPValue(DPV, InsertBB, InsertBefore, true);
return DPV;
}

LLVMContext &Ctx = LinkedInstr->getContext();
Module *M = LinkedInstr->getModule();
if (!AssignFn)
AssignFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_assign);

auto *Link = LinkedInstr->getMetadata(LLVMContext::MD_DIAssignID);
assert(Link && "Linked instruction must have DIAssign metadata attached");

std::array<Value *, 6> Args = {
MetadataAsValue::get(Ctx, ValueAsMetadata::get(Val)),
MetadataAsValue::get(Ctx, SrcVar),
Expand All @@ -971,35 +983,36 @@ DIBuilder::insertDbgAssign(Instruction *LinkedInstr, Value *Val,
return DVI;
}

Instruction *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL,
Instruction *InsertBefore) {
DbgInstPtr DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL,
Instruction *InsertBefore) {
return insertLabel(LabelInfo, DL,
InsertBefore ? InsertBefore->getParent() : nullptr,
InsertBefore);
}

Instruction *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL,
BasicBlock *InsertAtEnd) {
DbgInstPtr DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL,
BasicBlock *InsertAtEnd) {
return insertLabel(LabelInfo, DL, InsertAtEnd, nullptr);
}

Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V,
DILocalVariable *VarInfo,
DIExpression *Expr,
const DILocation *DL,
Instruction *InsertBefore) {
Instruction *DVI = insertDbgValueIntrinsic(
DbgInstPtr DIBuilder::insertDbgValueIntrinsic(Value *V,
DILocalVariable *VarInfo,
DIExpression *Expr,
const DILocation *DL,
Instruction *InsertBefore) {
DbgInstPtr DVI = insertDbgValueIntrinsic(
V, VarInfo, Expr, DL, InsertBefore ? InsertBefore->getParent() : nullptr,
InsertBefore);
cast<CallInst>(DVI)->setTailCall();
if (DVI.is<Instruction *>())
cast<CallInst>(DVI.get<Instruction *>())->setTailCall();
return DVI;
}

Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V,
DILocalVariable *VarInfo,
DIExpression *Expr,
const DILocation *DL,
BasicBlock *InsertAtEnd) {
DbgInstPtr DIBuilder::insertDbgValueIntrinsic(Value *V,
DILocalVariable *VarInfo,
DIExpression *Expr,
const DILocation *DL,
BasicBlock *InsertAtEnd) {
return insertDbgValueIntrinsic(V, VarInfo, Expr, DL, InsertAtEnd, nullptr);
}

Expand All @@ -1023,24 +1036,37 @@ static Function *getDeclareIntrin(Module &M) {
return Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
}

Instruction *DIBuilder::insertDbgValueIntrinsic(
DbgInstPtr DIBuilder::insertDbgValueIntrinsic(
llvm::Value *Val, DILocalVariable *VarInfo, DIExpression *Expr,
const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore) {
if (M.IsNewDbgInfoFormat) {
DPValue *DPV = DPValue::createDPValue(Val, VarInfo, Expr, DL);
insertDPValue(DPV, InsertBB, InsertBefore);
return DPV;
}

if (!ValueFn)
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
return insertDbgIntrinsic(ValueFn, Val, VarInfo, Expr, DL, InsertBB,
InsertBefore);
}

Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertBB,
Instruction *InsertBefore) {
DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertBB,
Instruction *InsertBefore) {
assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.declare");
assert(DL && "Expected debug loc");
assert(DL->getScope()->getSubprogram() ==
VarInfo->getScope()->getSubprogram() &&
"Expected matching subprograms");

if (M.IsNewDbgInfoFormat) {
DPValue *DPV = DPValue::createDPVDeclare(Storage, VarInfo, Expr, DL);
insertDPValue(DPV, InsertBB, InsertBefore);
return DPV;
}

if (!DeclareFn)
DeclareFn = getDeclareIntrin(M);

Expand All @@ -1055,6 +1081,23 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
return B.CreateCall(DeclareFn, Args);
}

void DIBuilder::insertDPValue(DPValue *DPV, BasicBlock *InsertBB,
Instruction *InsertBefore, bool InsertAtHead) {
assert(InsertBefore || InsertBB);
trackIfUnresolved(DPV->getVariable());
trackIfUnresolved(DPV->getExpression());
if (DPV->isDbgAssign())
trackIfUnresolved(DPV->getAddressExpression());

BasicBlock::iterator InsertPt;
if (InsertBB && InsertBefore)
InsertPt = InsertBefore->getIterator();
else if (InsertBB)
InsertPt = InsertBB->end();
InsertPt.setHeadBit(InsertAtHead);
InsertBB->insertDPValueBefore(DPV, InsertPt);
}

Instruction *DIBuilder::insertDbgIntrinsic(llvm::Function *IntrinsicFn,
Value *V, DILocalVariable *VarInfo,
DIExpression *Expr,
Expand All @@ -1081,18 +1124,28 @@ Instruction *DIBuilder::insertDbgIntrinsic(llvm::Function *IntrinsicFn,
return B.CreateCall(IntrinsicFn, Args);
}

Instruction *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL,
BasicBlock *InsertBB,
Instruction *InsertBefore) {
DbgInstPtr DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL,
BasicBlock *InsertBB,
Instruction *InsertBefore) {
assert(LabelInfo && "empty or invalid DILabel* passed to dbg.label");
assert(DL && "Expected debug loc");
assert(DL->getScope()->getSubprogram() ==
LabelInfo->getScope()->getSubprogram() &&
"Expected matching subprograms");

trackIfUnresolved(LabelInfo);
if (M.IsNewDbgInfoFormat) {
DPLabel *DPL = new DPLabel(LabelInfo, DL);
if (InsertBB && InsertBefore)
InsertBB->insertDPValueBefore(DPL, InsertBefore->getIterator());
else if (InsertBB)
InsertBB->insertDPValueBefore(DPL, InsertBB->end());
return DPL;
}

if (!LabelFn)
LabelFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_label);

trackIfUnresolved(LabelInfo);
Value *Args[] = {MetadataAsValue::get(VMContext, LabelInfo)};

IRBuilder<> B(DL->getContext());
Expand Down
Loading

0 comments on commit 9997e03

Please sign in to comment.