LLVM 23.0.0git
DXILDebugInfo.cpp
Go to the documentation of this file.
1//===--- DXILDebugInfo.cpp - analysis&lowering for Debug info -*- C++ -*- ---=//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "DXILDebugInfo.h"
10#include "DXILAttributes.h"
13#include "llvm/IR/Attributes.h"
14#include "llvm/IR/DebugInfo.h"
16#include "llvm/IR/IntrinsicsDirectX.h"
17#include "llvm/IR/Module.h"
19
20#define DEBUG_TYPE "dx-debug-info"
21
22using namespace llvm;
23using namespace llvm::dxil;
24
25// llvm.dbg.value has an additional "offset" operand in DXIL.
27 DXILDebugInfoMap &Res) {
28 if (DVI->getIntrinsicID() != Intrinsic::dbg_value) {
29 return;
30 }
31
32 Type *Int64Ty = Type::getInt64Ty(DVI->getContext());
33 Constant *ZeroOffset = ConstantInt::get(Int64Ty, 0);
34
35 Value *NewOps[] = {
36 DVI->getOperand(0),
37 ZeroOffset,
38 DVI->getOperand(1),
39 DVI->getOperand(2),
40 };
41
42 CallInst *NewI = CallInst::Create(NewF->getFunctionType(), NewF, NewOps);
43 NewI->setTailCall(DVI->isTailCall());
44 NewI->setDebugLoc(DVI->getDebugLoc());
45 Res.InstReplace.insert({DVI, decltype(Res.InstReplace)::mapped_type(NewI)});
46}
47
49 Function *F = getDeclarationIfExists(&M, Intrinsic::dbg_value);
50 if (!F)
51 return;
52
53 FunctionType *FT = F->getFunctionType();
54 Type *Int64Ty = Type::getInt64Ty(F->getContext());
56 FT->getReturnType(),
57 {FT->getParamType(0), Int64Ty, FT->getParamType(1), FT->getParamType(2)},
58 /*isVarArg=*/false);
59 Function *NewF = Function::Create(NewFT, F->getLinkage(), F->getName());
60 NewF->copyAttributesFrom(F);
61 Res.FuncReplace.insert({F, decltype(Res.FuncReplace)::mapped_type(NewF)});
62
63 for (User *U : F->users()) {
64 auto *DVI = cast<DbgVariableIntrinsic>(U);
65 replaceDbgVariableIntr(DVI, NewF, Res);
66 }
67}
68
70 M.convertFromNewDbgValues();
71
74 DIF.processModule(M);
75
76 {
77 Function *DVDecl = nullptr;
78
79 // Logically these should be variables in the
80 // for (BasicBlock &BB : F) loop.
81 // They are defined here and cleared at the start of the loop body to avoid
82 // the cost of deconstruction and reconstruction.
84 DbgValues;
86 std::pair<Instruction *, DbgValueInst *>>
87 DbgValueFragments;
88 // Likewise, logically, this should be a variable in the
89 // for (Function &F : M) loop.
90 DenseSet<DILocalVariable *> DbgVariablesSeen;
91
92 const AttributeMask &AttrMask = getNonDXILAttributeMask();
93
94 for (Function &F : M) {
95 F.removeFnAttrs(AttrMask);
96 F.removeRetAttrs(AttrMask);
97 for (unsigned ArgNo = 0; ArgNo != F.arg_size(); ++ArgNo)
98 F.removeParamAttrs(ArgNo, AttrMask);
99
100 bool IsEntryBlock = true;
101 DbgVariablesSeen.clear();
102 for (BasicBlock &BB : F) {
103 Instruction *NextNonDebugInst = nullptr;
104 DbgValues.clear();
105 DbgValueFragments.clear();
107 I.eraseMetadataIf([](unsigned KindID, MDNode *) {
108 return KindID == LLVMContext::MD_DIAssignID;
109 });
110 if (!isa<DbgInfoIntrinsic>(I)) {
111 NextNonDebugInst = &I;
112 continue;
113 }
114 if (auto *DL = dyn_cast<DbgLabelInst>(&I)) {
115 DL->eraseFromParent();
116 continue;
117 }
118 // Process both llvm.dbg.value and llvm.dbg.assign here. We convert
119 // llvm.dbg.assign to llvm.dbg.value by dropping the last arguments,
120 // and remove redundant llvm.dbg.values.
121 if (auto *DV = dyn_cast<DbgValueInst>(&I)) {
122 // Keep track of the last location where we saw any debug value for
123 // a variable.
124 DILocalVariable *V = DV->getVariable();
125 DIExpression *E = DV->getExpression();
126 // If this is already an llvm.dbg.value instruction that we can
127 // keep, just do that, otherwise convert it.
128 auto *Val = cast<MetadataAsValue>(DV->getArgOperand(0));
129 auto *Var = cast<MetadataAsValue>(DV->getArgOperand(1));
130 auto *Expr = cast<MetadataAsValue>(DV->getArgOperand(2));
131 bool Replace = DV->getIntrinsicID() != Intrinsic::dbg_value;
132 if (!isa<ValueAsMetadata>(Val->getMetadata())) {
133 // This may be a DIArgList which is not supported in LLVM 3.7. If
134 // it is, we cannot record the new value, but we still need to
135 // kill any old value. Do this by poison. We do not know the
136 // correct type to use here and arbitrarily use i1.
137 // This should never be anything other than ValueAsMetadata or
138 // DIArgList, but in manually constructed LLVM IR, it can be.
139 // Handle this gracefully by also replacing it with poison.
142 Type::getInt1Ty(M.getContext()))));
143 E = DIExpression::get(M.getContext(), {});
144 Expr = MetadataAsValue::get(M.getContext(), E);
145 Replace = true;
146 }
147 std::pair<Instruction *, DbgValueInst *> &DbgValue = DbgValues[V];
148 std::pair<Instruction *, DbgValueInst *> &DbgValueFragment =
149 DbgValueFragments[{V, E}];
150 if (DbgValue.second) {
151 // If there is a later value of the same fragment at the same
152 // location, this value is redundant.
153 if (DbgValueFragment.first == NextNonDebugInst) {
154 DV->eraseFromParent();
155 continue;
156 }
157 // If there is a later identical value of the same fragment at a
158 // later point, and there have been no intervening values of
159 // different possibly overlapping fragments, that later value is
160 // redundant.
161 if (DbgValueFragment.second &&
162 DbgValueFragment.second == DbgValue.second &&
163 DbgValueFragment.second->getValue() == DV->getValue()) {
164 DbgValue.second->eraseFromParent();
165 }
166 }
167 DbgValueInst *NewDV;
168 if (Replace) {
169 if (!DVDecl) {
170 DVDecl =
171 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::dbg_value);
172 AttributeMask AM;
173 for (Attribute A : DVDecl->getAttributes().getFnAttrs())
174 if (A.isStringAttribute() ||
175 (A.getKindAsEnum() != Attribute::NoUnwind &&
176 A.getKindAsEnum() != Attribute::Memory))
177 AM.addAttribute(A);
178 DVDecl->removeFnAttrs(AM);
179 }
180 NewDV = cast<DbgValueInst>(
181 CallInst::Create(DVDecl, {Val, Var, Expr}, {}, "",
182 std::next(DV->getIterator())));
183 NewDV->setTailCall();
184 NewDV->setDebugLoc(DV->getDebugLoc());
185 DV->eraseFromParent();
186 } else {
187 NewDV = DV;
188 }
189 DbgValue = DbgValueFragment = {NextNonDebugInst, NewDV};
190 continue;
191 }
192 }
193 // If this is the entry block, if the first value we see for each debug
194 // value is undef, it is redundant.
195 if (IsEntryBlock) {
196 for (Instruction &I : make_early_inc_range(BB)) {
197 auto *DV = dyn_cast<DbgValueInst>(&I);
198 if (!DV || DbgVariablesSeen.contains(DV->getVariable()))
199 continue;
200 if (isa<UndefValue>(DV->getValue())) {
201 DV->eraseFromParent();
202 continue;
203 }
204 DbgVariablesSeen.insert(DV->getVariable());
205 }
206 }
207 IsEntryBlock = false;
208 }
209 }
210 }
211
212 for (DISubprogram *SP : DIF.subprograms()) {
213 if (MDTuple *RN = cast_or_null<MDTuple>(SP->getRawRetainedNodes())) {
214 SmallVector<Metadata *> MDs(RN->operands());
215 MDs.erase(std::remove_if(MDs.begin(), MDs.end(),
216 [](Metadata *M) { return isa<DILabel>(M); }),
217 MDs.end());
218 SP->replaceRetainedNodes(MDTuple::get(M.getContext(), MDs));
219 }
220 }
221
222 // Re-scan the module to account for removed metadata.
223 DIF.reset();
224 DIF.processModule(M);
225
226 // Replace llvm.dbg.value with equivalent DXIL intrinsics.
227 replaceDbgValue(M, Res);
228
229 for (DICompileUnit *CU : DIF.compile_units()) {
230 DISourceLanguageName Lang = CU->getSourceLanguage();
231 if (Lang.hasVersionedName()) {
232 auto LangName = static_cast<dwarf::SourceLanguageName>(Lang.getName());
233 Lang = dwarf::toDW_LANG(LangName, Lang.getVersion())
234 .value_or(dwarf::SourceLanguage{});
235 auto *NewCU = DICompileUnit::getDistinct(
236 M.getContext(), Lang, CU->getFile(), CU->getProducer(),
237 CU->isOptimized(), CU->getFlags(), CU->getRuntimeVersion(),
238 CU->getSplitDebugFilename(), CU->getEmissionKind(),
239 CU->getEnumTypes(), CU->getRetainedTypes(), CU->getGlobalVariables(),
240 CU->getImportedEntities(), CU->getMacros(), CU->getDWOId(),
241 CU->getSplitDebugInlining(), CU->getDebugInfoForProfiling(),
242 CU->getNameTableKind(), CU->getRangesBaseAddress(), CU->getSysRoot(),
243 CU->getSDK());
244 Res.MDReplace.insert({CU, NewCU});
245 }
246 }
247
248 std::vector<std::pair<const DICompileUnit *, const Metadata *>> CUSubprograms;
249
250 for (const Function &F : M) {
251 if (const DISubprogram *SP = F.getSubprogram()) {
252 auto *FunctionMD = ConstantAsMetadata::get(const_cast<Function *>(&F));
253 Res.MDExtra.insert({SP, FunctionMD});
254 }
255 }
256
257 for (const DISubprogram *SP : DIF.subprograms()) {
258 const DISubprogram *NewSP = SP;
259
260 static constexpr auto SupportedDIFlags =
261 static_cast<DISubprogram::DIFlags>(DISubprogram::FlagExportSymbols - 1);
262 static constexpr auto SupportedDISPFlags =
263 static_cast<DISubprogram::DISPFlags>(DISubprogram::SPFlagPure - 1);
264 if (SP->isDistinct() || SP->getFlags() & ~SupportedDIFlags ||
265 SP->getSPFlags() & ~SupportedDISPFlags) {
266 NewSP = DISubprogram::get(
267 M.getContext(), SP->getScope(), SP->getName(), SP->getLinkageName(),
268 SP->getFile(), SP->getLine(), SP->getType(), SP->getScopeLine(),
269 SP->getContainingType(), SP->getVirtualIndex(),
270 SP->getThisAdjustment(), SP->getFlags() & SupportedDIFlags,
271 SP->getSPFlags() & SupportedDISPFlags, SP->getUnit(),
272 SP->getTemplateParams(), SP->getDeclaration(), SP->getRetainedNodes(),
273 SP->getThrownTypes(), SP->getAnnotations(), SP->getTargetFuncName(),
274 SP->getKeyInstructionsEnabled());
275
276 Res.MDReplace.insert({SP, NewSP});
277
278 if (auto It = Res.MDExtra.find(SP); It != Res.MDExtra.end()) {
279 const Metadata *FunctionMD = It->second;
280 Res.MDExtra.erase(It);
281 Res.MDExtra.insert({NewSP, FunctionMD});
282 }
283 }
284
285 if (SP->getUnit())
286 CUSubprograms.push_back(
287 {SP->getUnit(), static_cast<const Metadata *>(SP)});
288 }
289
290 std::stable_sort(
291 CUSubprograms.begin(), CUSubprograms.end(), [](auto &&A, auto &&B) {
292 return std::less<const DICompileUnit *>()(A.first, B.first);
293 });
294 for (auto It = CUSubprograms.begin(), End = CUSubprograms.end(); It != End;) {
295 const DICompileUnit *CU = It->first;
296 const DICompileUnit *NewCU =
298 SmallVector<Metadata *, 16> Subprograms;
299 do {
300 Subprograms.push_back(const_cast<Metadata *>(It->second));
301 } while (++It != End && It->first == CU);
302 const auto *SubprogramsMD = MDTuple::get(M.getContext(), Subprograms);
303 Res.MDExtra.insert({NewCU, SubprogramsMD});
304 }
305
306 for (const GlobalVariable &GV : M.globals()) {
308 GV.getDebugInfo(GVEs);
309 for (DIGlobalVariableExpression *GVE : GVEs) {
310 if (GVE->getExpression()->getNumElements())
311 continue;
312 auto [It, Inserted] = Res.MDExtra.insert(
313 {GVE->getVariable(),
314 ValueAsMetadata::get(const_cast<GlobalVariable *>(&GV))});
315 if (!Inserted)
316 It->second = nullptr;
317 }
318 }
319
321 Res.MDReplace.insert({GVE, GVE->getVariable()});
322
323 for (DIScope *S : DIF.scopes()) {
324 if (auto *CB = dyn_cast<DICommonBlock>(S)) {
325 const Metadata *Scope = CB->getScope();
326 Scope = Res.MDReplace.lookup_or(Scope, Scope);
327 Res.MDReplace.insert({CB, Scope});
328 }
329 }
330
331 for (DIType *T : DIF.types()) {
332 if (auto *SR = dyn_cast<DISubrangeType>(T)) {
333 DIType *BT = SR->getBaseType();
334 if (!BT)
335 BT = DIBasicType::get(SR->getContext(), dwarf::DW_TAG_base_type,
336 SR->getName(), SR->getSizeInBits(),
337 SR->getAlignInBits(), dwarf::DW_ATE_unsigned,
338 SR->getNumExtraInhabitants(),
339 /*DataSizeInBits=*/0, SR->getFlags());
340 Res.MDReplace.insert({T, BT});
341 }
342 }
343
344 return Res;
345}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
BitTracker BT
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static void replaceDbgVariableIntr(DbgVariableIntrinsic *DVI, Function *NewF, DXILDebugInfoMap &Res)
static void replaceDbgValue(Module &M, DXILDebugInfoMap &Res)
This file contains constants used for implementing Dwarf debug support.
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
Class recording the (high level) value of a variable.
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:105
LLVM Basic Block Representation.
Definition BasicBlock.h:62
This class represents a function call, abstracting a target machine's calling convention.
bool isTailCall() const
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
void setTailCall(bool IsTc=true)
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:537
This is an important base class in LLVM.
Definition Constant.h:43
DWARF expression.
A pair of DIGlobalVariable and DIExpression.
DIFlags
Debug info flags.
Base class for scope-like contexts.
Wrapper structure that holds source language identity metadata that includes language name,...
uint32_t getVersion() const
Returns language version. Only valid for versioned language names.
uint16_t getName() const
Returns a versioned or unversioned language name.
Subprogram description. Uses SubclassData1.
DISPFlags
Debug info subprogram flags.
Base class for types.
This represents the llvm.dbg.value instruction.
This is the common base class for debug info intrinsics for variables.
Utility to find all debug info in a module.
Definition DebugInfo.h:105
LLVM_ABI void processModule(const Module &M)
Process entire module and collect debug info anchors.
LLVM_ABI void reset()
Clear all lists.
iterator_range< global_variable_expression_iterator > global_variables() const
Definition DebugInfo.h:154
iterator_range< subprogram_iterator > subprograms() const
Definition DebugInfo.h:152
iterator_range< type_iterator > types() const
Definition DebugInfo.h:158
iterator_range< scope_iterator > scopes() const
Definition DebugInfo.h:160
iterator_range< compile_unit_iterator > compile_units() const
Definition DebugInfo.h:150
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:225
bool erase(const KeyT &Val)
Definition DenseMap.h:379
iterator end()
Definition DenseMap.h:143
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
Definition DenseMap.h:262
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:286
Implements a dense probed hash-table based set.
Definition DenseSet.h:289
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:168
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:211
void removeFnAttrs(const AttributeMask &Attrs)
Definition Function.cpp:689
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition Function.h:328
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
Definition Function.cpp:838
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
Metadata node.
Definition Metadata.h:1069
static MDTuple * getDistinct(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1569
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1561
Tuple of metadata.
Definition Metadata.h:1489
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1518
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:110
Root of the metadata hierarchy.
Definition Metadata.h:64
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
Definition Type.cpp:310
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:306
Value * getOperand(unsigned i) const
Definition User.h:207
static LLVM_ABI ValueAsMetadata * get(Value *V)
Definition Metadata.cpp:509
LLVM Value Representation.
Definition Value.h:75
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:212
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition DenseSet.h:185
InstMap InstReplace
Completely replace one instruction with another in ValueEnumerator.
MDMap MDExtra
Enumerate extra metadata when Key is encountered in ValueEnumerator.
FuncMap FuncReplace
Completely replace one function with another in ValueEnumerator.
MDMap MDReplace
Completely replace one metadata with another in ValueEnumerator.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
SourceLanguageName
Definition Dwarf.h:229
std::optional< SourceLanguage > toDW_LANG(SourceLanguageName name, uint32_t version)
Convert a DWARF 6 pair of language name and version to a DWARF 5 DW_LANG.
Definition Dwarf.h:237
DXILDebugInfoMap run(Module &M)
const AttributeMask & getNonDXILAttributeMask()
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
auto cast_or_null(const Y &Val)
Definition Casting.h:714
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559