LLVM 24.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
71 // Convert debug markers back to dbg.value intrinsics. Record whether any
72 // changes were made.
73 Res.Modified = M.convertFromNewDbgValues();
75 DIF.processModule(M);
76
77 {
78 Function *DVDecl = nullptr;
79
80 // Logically these should be variables in the
81 // for (BasicBlock &BB : F) loop.
82 // They are defined here and cleared at the start of the loop body to avoid
83 // the cost of deconstruction and reconstruction.
85 DbgValues;
87 std::pair<Instruction *, DbgValueInst *>>
88 DbgValueFragments;
89 // Likewise, logically, this should be a variable in the
90 // for (Function &F : M) loop.
91 DenseSet<DILocalVariable *> DbgVariablesSeen;
92
93 const AttributeMask &AttrMask = getNonDXILAttributeMask();
94
95 for (Function &F : M) {
96 F.removeFnAttrs(AttrMask);
97 F.removeRetAttrs(AttrMask);
98 for (unsigned ArgNo = 0; ArgNo != F.arg_size(); ++ArgNo)
99 F.removeParamAttrs(ArgNo, AttrMask);
100
101 bool IsEntryBlock = true;
102 DbgVariablesSeen.clear();
103 for (BasicBlock &BB : F) {
104 Instruction *NextNonDebugInst = nullptr;
105 DbgValues.clear();
106 DbgValueFragments.clear();
108 I.eraseMetadataIf([](unsigned KindID, MDNode *) {
109 return KindID == LLVMContext::MD_DIAssignID;
110 });
111 if (!isa<DbgInfoIntrinsic>(I)) {
112 NextNonDebugInst = &I;
113 continue;
114 }
115 if (auto *DL = dyn_cast<DbgLabelInst>(&I)) {
116 DL->eraseFromParent();
117 Res.Modified = true;
118 continue;
119 }
120 // Process both llvm.dbg.value and llvm.dbg.assign here. We convert
121 // llvm.dbg.assign to llvm.dbg.value by dropping the last arguments,
122 // and remove redundant llvm.dbg.values.
123 if (auto *DV = dyn_cast<DbgValueInst>(&I)) {
124 // Keep track of the last location where we saw any debug value for
125 // a variable.
126 DILocalVariable *V = DV->getVariable();
127 DIExpression *E = DV->getExpression();
128 // If this is already an llvm.dbg.value instruction that we can
129 // keep, just do that, otherwise convert it.
130 auto *Val = cast<MetadataAsValue>(DV->getArgOperand(0));
131 auto *Var = cast<MetadataAsValue>(DV->getArgOperand(1));
132 auto *Expr = cast<MetadataAsValue>(DV->getArgOperand(2));
133 bool Replace = DV->getIntrinsicID() != Intrinsic::dbg_value;
134 if (!isa<ValueAsMetadata>(Val->getMetadata())) {
135 // This may be a DIArgList which is not supported in LLVM 3.7. If
136 // it is, we cannot record the new value, but we still need to
137 // kill any old value. Do this by poison. We do not know the
138 // correct type to use here and arbitrarily use i1.
139 // This should never be anything other than ValueAsMetadata or
140 // DIArgList, but in manually constructed LLVM IR, it can be.
141 // Handle this gracefully by also replacing it with poison.
144 Type::getInt1Ty(M.getContext()))));
145 E = DIExpression::get(M.getContext(), {});
146 Expr = MetadataAsValue::get(M.getContext(), E);
147 Replace = true;
148 }
149 std::pair<Instruction *, DbgValueInst *> &DbgValue = DbgValues[V];
150 std::pair<Instruction *, DbgValueInst *> &DbgValueFragment =
151 DbgValueFragments[{V, E}];
152 if (DbgValue.second) {
153 // If there is a later value of the same fragment at the same
154 // location, this value is redundant.
155 if (DbgValueFragment.first == NextNonDebugInst) {
156 DV->eraseFromParent();
157 Res.Modified = true;
158 continue;
159 }
160 // If there is a later identical value of the same fragment at a
161 // later point, and there have been no intervening values of
162 // different possibly overlapping fragments, that later value is
163 // redundant.
164 if (DbgValueFragment.second &&
165 DbgValueFragment.second == DbgValue.second &&
166 DbgValueFragment.second->getValue() == DV->getValue()) {
167 DbgValue.second->eraseFromParent();
168 Res.Modified = true;
169 }
170 }
171 DbgValueInst *NewDV;
172 if (Replace) {
173 if (!DVDecl) {
174 DVDecl =
175 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::dbg_value);
176 AttributeMask AM;
177 for (Attribute A : DVDecl->getAttributes().getFnAttrs())
178 if (A.isStringAttribute() ||
179 (A.getKindAsEnum() != Attribute::NoUnwind &&
180 A.getKindAsEnum() != Attribute::Memory))
181 AM.addAttribute(A);
182 DVDecl->removeFnAttrs(AM);
183 }
184 NewDV = cast<DbgValueInst>(
185 CallInst::Create(DVDecl, {Val, Var, Expr}, {}, "",
186 std::next(DV->getIterator())));
187 NewDV->setTailCall();
188 NewDV->setDebugLoc(DV->getDebugLoc());
189 DV->eraseFromParent();
190 Res.Modified = true;
191 } else {
192 NewDV = DV;
193 }
194 DbgValue = DbgValueFragment = {NextNonDebugInst, NewDV};
195 continue;
196 }
197 }
198 // If this is the entry block, if the first value we see for each debug
199 // value is undef, it is redundant.
200 if (IsEntryBlock) {
201 for (Instruction &I : make_early_inc_range(BB)) {
202 auto *DV = dyn_cast<DbgValueInst>(&I);
203 if (!DV || DbgVariablesSeen.contains(DV->getVariable()))
204 continue;
205 if (isa<UndefValue>(DV->getValue())) {
206 DV->eraseFromParent();
207 Res.Modified = true;
208 continue;
209 }
210 DbgVariablesSeen.insert(DV->getVariable());
211 }
212 }
213 IsEntryBlock = false;
214 }
215 }
216 }
217
218 for (DISubprogram *SP : DIF.subprograms()) {
219 if (MDTuple *RN = cast_or_null<MDTuple>(SP->getRawRetainedNodes())) {
220 SmallVector<Metadata *> MDs(RN->operands());
221 MDs.erase(std::remove_if(MDs.begin(), MDs.end(),
222 [](Metadata *M) { return isa<DILabel>(M); }),
223 MDs.end());
224 SP->replaceRetainedNodes(MDTuple::get(M.getContext(), MDs));
225 Res.Modified = true;
226 }
227 }
228
229 // Re-scan the module to account for removed metadata.
230 DIF.reset();
231 DIF.processModule(M);
232
233 // Replace llvm.dbg.value with equivalent DXIL intrinsics.
234 replaceDbgValue(M, Res);
235
236 for (DICompileUnit *CU : DIF.compile_units()) {
237 DISourceLanguageName Lang = CU->getSourceLanguage();
238 if (Lang.hasVersionedName()) {
239 auto LangName = static_cast<dwarf::SourceLanguageName>(Lang.getName());
240 Lang = dwarf::toDW_LANG(LangName, Lang.getVersion())
241 .value_or(dwarf::SourceLanguage{});
242 auto *NewCU = DICompileUnit::getDistinct(
243 M.getContext(), Lang, CU->getFile(), CU->getProducer(),
244 CU->isOptimized(), CU->getFlags(), CU->getRuntimeVersion(),
245 CU->getSplitDebugFilename(), CU->getEmissionKind(),
246 CU->getEnumTypes(), CU->getRetainedTypes(), CU->getGlobalVariables(),
247 CU->getImportedEntities(), CU->getMacros(), CU->getDWOId(),
248 CU->getSplitDebugInlining(), CU->getDebugInfoForProfiling(),
249 CU->getNameTableKind(), CU->getRangesBaseAddress(), CU->getSysRoot(),
250 CU->getSDK());
251 Res.MDReplace.insert({CU, NewCU});
252 }
253 }
254
255 std::vector<std::pair<const DICompileUnit *, const Metadata *>> CUSubprograms;
256
257 for (const Function &F : M) {
258 if (const DISubprogram *SP = F.getSubprogram()) {
259 auto *FunctionMD = ConstantAsMetadata::get(const_cast<Function *>(&F));
260 Res.MDExtra.insert({SP, FunctionMD});
261 }
262 }
263
264 for (const DISubprogram *SP : DIF.subprograms()) {
265 const DISubprogram *NewSP = SP;
266
267 static constexpr auto SupportedDIFlags =
268 static_cast<DISubprogram::DIFlags>(DISubprogram::FlagExportSymbols - 1);
269 static constexpr auto SupportedDISPFlags =
270 static_cast<DISubprogram::DISPFlags>(DISubprogram::SPFlagPure - 1);
271 if (SP->isDistinct() || SP->getFlags() & ~SupportedDIFlags ||
272 SP->getSPFlags() & ~SupportedDISPFlags) {
273 NewSP = DISubprogram::get(
274 M.getContext(), SP->getScope(), SP->getName(), SP->getLinkageName(),
275 SP->getFile(), SP->getLine(), SP->getType(), SP->getScopeLine(),
276 SP->getContainingType(), SP->getVirtualIndex(),
277 SP->getThisAdjustment(), SP->getFlags() & SupportedDIFlags,
278 SP->getSPFlags() & SupportedDISPFlags, SP->getUnit(),
279 SP->getTemplateParams(), SP->getDeclaration(), SP->getRetainedNodes(),
280 SP->getThrownTypes(), SP->getAnnotations(), SP->getTargetFuncName(),
281 SP->getKeyInstructionsEnabled());
282
283 Res.MDReplace.insert({SP, NewSP});
284
285 if (auto It = Res.MDExtra.find(SP); It != Res.MDExtra.end()) {
286 const Metadata *FunctionMD = It->second;
287 Res.MDExtra.erase(It);
288 Res.MDExtra.insert({NewSP, FunctionMD});
289 }
290 }
291
292 if (SP->getUnit())
293 CUSubprograms.push_back(
294 {SP->getUnit(), static_cast<const Metadata *>(SP)});
295 }
296
297 std::stable_sort(
298 CUSubprograms.begin(), CUSubprograms.end(), [](auto &&A, auto &&B) {
299 return std::less<const DICompileUnit *>()(A.first, B.first);
300 });
301 for (auto It = CUSubprograms.begin(), End = CUSubprograms.end(); It != End;) {
302 const DICompileUnit *CU = It->first;
303 const DICompileUnit *NewCU =
305 SmallVector<Metadata *, 16> Subprograms;
306 do {
307 Subprograms.push_back(const_cast<Metadata *>(It->second));
308 } while (++It != End && It->first == CU);
309 const auto *SubprogramsMD = MDTuple::get(M.getContext(), Subprograms);
310 Res.MDExtra.insert({NewCU, SubprogramsMD});
311 }
312
313 for (const GlobalVariable &GV : M.globals()) {
315 GV.getDebugInfo(GVEs);
316 for (DIGlobalVariableExpression *GVE : GVEs) {
317 if (GVE->getExpression()->getNumElements())
318 continue;
319 auto [It, Inserted] = Res.MDExtra.insert(
320 {GVE->getVariable(),
321 ValueAsMetadata::get(const_cast<GlobalVariable *>(&GV))});
322 if (!Inserted)
323 It->second = nullptr;
324 }
325 }
326
328 Res.MDReplace.insert({GVE, GVE->getVariable()});
329
330 for (DIScope *S : DIF.scopes()) {
331 if (auto *CB = dyn_cast<DICommonBlock>(S)) {
332 const Metadata *Scope = CB->getScope();
333 Scope = Res.MDReplace.lookup_or(Scope, Scope);
334 Res.MDReplace.insert({CB, Scope});
335 }
336 }
337
338 for (DIType *T : DIF.types()) {
339 if (auto *SR = dyn_cast<DISubrangeType>(T)) {
340 DIType *BT = SR->getBaseType();
341 if (!BT)
342 BT = DIBasicType::get(SR->getContext(), dwarf::DW_TAG_base_type,
343 SR->getName(), SR->getSizeInBits(),
344 SR->getAlignInBits(), dwarf::DW_ATE_unsigned,
345 SR->getNumExtraInhabitants(),
346 /*DataSizeInBits=*/0, SR->getFlags());
347 Res.MDReplace.insert({T, BT});
348 }
349 }
350
351 return Res;
352}
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:155
iterator_range< subprogram_iterator > subprograms() const
Definition DebugInfo.h:153
iterator_range< type_iterator > types() const
Definition DebugInfo.h:159
iterator_range< scope_iterator > scopes() const
Definition DebugInfo.h:161
iterator_range< compile_unit_iterator > compile_units() const
Definition DebugInfo.h:151
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
bool erase(const KeyT &Val)
Definition DenseMap.h:377
iterator end()
Definition DenseMap.h:141
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
Definition DenseMap.h:260
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:284
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
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:169
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:212
void removeFnAttrs(const AttributeMask &Attrs)
Definition Function.cpp:696
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition Function.h:329
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
Definition Function.cpp:845
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:1575
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1567
Tuple of metadata.
Definition Metadata.h:1484
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1513
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:111
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:68
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:510
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:209
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition DenseSet.h:182
bool Modified
Whether the run modified the IR of the module the map was produced for.
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