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"
11#include "llvm/IR/DebugInfo.h"
13#include "llvm/IR/IntrinsicsDirectX.h"
14#include "llvm/IR/Module.h"
16
17#define DEBUG_TYPE "dx-debug-info"
18
19using namespace llvm;
20using namespace llvm::dxil;
21
22// llvm.dbg.value has an additional "offset" operand in DXIL.
24 DXILDebugInfoMap &Res) {
25 if (DVI->getIntrinsicID() != Intrinsic::dbg_value) {
26 return;
27 }
28
29 Type *Int64Ty = Type::getInt64Ty(DVI->getContext());
30 Constant *ZeroOffset = ConstantInt::get(Int64Ty, 0);
31
32 Value *NewOps[] = {
33 DVI->getOperand(0),
34 ZeroOffset,
35 DVI->getOperand(1),
36 DVI->getOperand(2),
37 };
38
39 CallInst *NewI = CallInst::Create(NewF->getFunctionType(), NewF, NewOps);
40 NewI->setTailCall(DVI->isTailCall());
41 NewI->setDebugLoc(DVI->getDebugLoc());
42 Res.InstReplace.insert({DVI, decltype(Res.InstReplace)::mapped_type(NewI)});
43}
44
46 Function *F = getDeclarationIfExists(&M, Intrinsic::dbg_value);
47 if (!F)
48 return;
49
50 FunctionType *FT = F->getFunctionType();
51 Type *Int64Ty = Type::getInt64Ty(F->getContext());
53 FT->getReturnType(),
54 {FT->getParamType(0), Int64Ty, FT->getParamType(1), FT->getParamType(2)},
55 /*isVarArg=*/false);
56 Function *NewF = Function::Create(NewFT, F->getLinkage(), F->getName());
57 NewF->copyAttributesFrom(F);
58 Res.FuncReplace.insert({F, decltype(Res.FuncReplace)::mapped_type(NewF)});
59
60 for (User *U : F->users()) {
61 auto *DVI = cast<DbgVariableIntrinsic>(U);
62 replaceDbgVariableIntr(DVI, NewF, Res);
63 }
64}
65
69 DIF.processModule(M);
70
71 for (auto &F : M) {
72 for (auto &BB : F) {
73 for (auto &I : make_early_inc_range(reverse(BB))) {
74 if (auto *DL = dyn_cast<DbgLabelInst>(&I)) {
75 DL->eraseFromParent();
76 continue;
77 }
78 }
79 }
80 }
81
82 for (DISubprogram *SP : DIF.subprograms()) {
83 if (MDTuple *RN = cast_or_null<MDTuple>(SP->getRawRetainedNodes())) {
84 SmallVector<Metadata *> MDs(RN->operands());
85 MDs.erase(std::remove_if(MDs.begin(), MDs.end(),
86 [](Metadata *M) { return isa<DILabel>(M); }),
87 MDs.end());
88 SP->replaceRetainedNodes(MDTuple::get(M.getContext(), MDs));
89 }
90 }
91
92 // Re-scan the module to account for removed metadata.
93 DIF.reset();
94 DIF.processModule(M);
95
96 // Replace llvm.dbg.value with equivalent DXIL intrinsics.
97 replaceDbgValue(M, Res);
98
99 for (DICompileUnit *CU : DIF.compile_units()) {
100 DISourceLanguageName Lang = CU->getSourceLanguage();
101 if (Lang.hasVersionedName()) {
102 auto LangName = static_cast<dwarf::SourceLanguageName>(Lang.getName());
103 Lang = dwarf::toDW_LANG(LangName, Lang.getVersion())
104 .value_or(dwarf::SourceLanguage{});
105 auto *NewCU = DICompileUnit::getDistinct(
106 M.getContext(), Lang, CU->getFile(), CU->getProducer(),
107 CU->isOptimized(), CU->getFlags(), CU->getRuntimeVersion(),
108 CU->getSplitDebugFilename(), CU->getEmissionKind(),
109 CU->getEnumTypes(), CU->getRetainedTypes(), CU->getGlobalVariables(),
110 CU->getImportedEntities(), CU->getMacros(), CU->getDWOId(),
111 CU->getSplitDebugInlining(), CU->getDebugInfoForProfiling(),
112 CU->getNameTableKind(), CU->getRangesBaseAddress(), CU->getSysRoot(),
113 CU->getSDK());
114 Res.MDReplace.insert({CU, NewCU});
115 }
116 }
117
118 std::vector<std::pair<const DICompileUnit *, const Metadata *>> CUSubprograms;
119
120 for (const Function &F : M) {
121 if (const DISubprogram *SP = F.getSubprogram()) {
122 auto *FunctionMD = ConstantAsMetadata::get(const_cast<Function *>(&F));
123 Res.MDExtra.insert({SP, FunctionMD});
124 }
125 }
126
127 for (const DISubprogram *SP : DIF.subprograms()) {
128 const DISubprogram *NewSP = SP;
129
130 static constexpr auto SupportedDIFlags =
131 static_cast<DISubprogram::DIFlags>(DISubprogram::FlagExportSymbols - 1);
132 static constexpr auto SupportedDISPFlags =
133 static_cast<DISubprogram::DISPFlags>(DISubprogram::SPFlagPure - 1);
134 if (SP->isDistinct() || SP->getFlags() & ~SupportedDIFlags ||
135 SP->getSPFlags() & ~SupportedDISPFlags) {
136 NewSP = DISubprogram::get(
137 M.getContext(), SP->getScope(), SP->getName(), SP->getLinkageName(),
138 SP->getFile(), SP->getLine(), SP->getType(), SP->getScopeLine(),
139 SP->getContainingType(), SP->getVirtualIndex(),
140 SP->getThisAdjustment(), SP->getFlags() & SupportedDIFlags,
141 SP->getSPFlags() & SupportedDISPFlags, SP->getUnit(),
142 SP->getTemplateParams(), SP->getDeclaration(), SP->getRetainedNodes(),
143 SP->getThrownTypes(), SP->getAnnotations(), SP->getTargetFuncName(),
144 SP->getKeyInstructionsEnabled());
145
146 Res.MDReplace.insert({SP, NewSP});
147
148 if (auto It = Res.MDExtra.find(SP); It != Res.MDExtra.end()) {
149 const Metadata *FunctionMD = It->second;
150 Res.MDExtra.erase(It);
151 Res.MDExtra.insert({NewSP, FunctionMD});
152 }
153 }
154
155 if (SP->getUnit())
156 CUSubprograms.push_back(
157 {SP->getUnit(), static_cast<const Metadata *>(SP)});
158 }
159
160 std::stable_sort(
161 CUSubprograms.begin(), CUSubprograms.end(), [](auto &&A, auto &&B) {
162 return std::less<const DICompileUnit *>()(A.first, B.first);
163 });
164 for (auto It = CUSubprograms.begin(), End = CUSubprograms.end(); It != End;) {
165 const DICompileUnit *CU = It->first;
166 const DICompileUnit *NewCU =
168 SmallVector<Metadata *, 16> Subprograms;
169 do {
170 Subprograms.push_back(const_cast<Metadata *>(It->second));
171 } while (++It != End && It->first == CU);
172 const auto *SubprogramsMD = MDTuple::get(M.getContext(), Subprograms);
173 Res.MDExtra.insert({NewCU, SubprogramsMD});
174 }
175
176 for (DIType *T : DIF.types()) {
177 if (auto *SR = dyn_cast<DISubrangeType>(T)) {
178 DIType *BT = SR->getBaseType();
179 if (!BT)
181 SR->getContext(), dwarf::DW_TAG_base_type, SR->getName(),
182 SR->getSizeInBits(), SR->getAlignInBits(), dwarf::DW_ATE_unsigned,
183 SR->getNumExtraInhabitants(), /*DataSizeInBits=*/0, SR->getFlags());
184 Res.MDReplace.insert({T, BT});
185 }
186 }
187
188 return Res;
189}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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
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
DIFlags
Debug info flags.
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 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< subprogram_iterator > subprograms() const
Definition DebugInfo.h:152
iterator_range< type_iterator > types() const
Definition DebugInfo.h:158
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
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 copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
Definition Function.cpp:843
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.
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:1495
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1524
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
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
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
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.
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)
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
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559