LLVM 24.0.0git
DXILDebugInfoMap.cpp
Go to the documentation of this file.
1//===- DXILDebugInfoMap.cpp - DXIL debug info serialization --------------===//
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 "DXILDebugInfoMap.h"
11#include "llvm/IR/DebugInfo.h"
13#include "llvm/IR/Module.h"
15
16using namespace llvm;
17using namespace llvm::dxil;
18
20 DXILDebugInfoMap &Res) {
21 if (DVI->getIntrinsicID() != Intrinsic::dbg_value)
22 return;
23
24 Type *Int64Ty = Type::getInt64Ty(DVI->getContext());
25 Constant *ZeroOffset = ConstantInt::get(Int64Ty, 0);
26 Value *NewOps[] = {DVI->getOperand(0), ZeroOffset, DVI->getOperand(1),
27 DVI->getOperand(2)};
28
29 CallInst *NewI = CallInst::Create(NewF->getFunctionType(), NewF, NewOps);
30 NewI->setTailCall(DVI->isTailCall());
31 NewI->setDebugLoc(DVI->getDebugLoc());
32 Res.InstReplace.insert({DVI, decltype(Res.InstReplace)::mapped_type(NewI)});
33}
34
36 Function *F = getDeclarationIfExists(&M, Intrinsic::dbg_value);
37 if (!F)
38 return;
39
40 FunctionType *FT = F->getFunctionType();
41 Type *Int64Ty = Type::getInt64Ty(F->getContext());
43 FT->getReturnType(),
44 {FT->getParamType(0), Int64Ty, FT->getParamType(1), FT->getParamType(2)},
45 /*isVarArg=*/false);
46 Function *NewF = Function::Create(NewFT, F->getLinkage(), F->getName());
47 NewF->copyAttributesFrom(F);
48 Res.FuncReplace.insert({F, decltype(Res.FuncReplace)::mapped_type(NewF)});
49
50 for (User *U : F->users())
52}
53
57 DIF.processModule(M);
58
59 replaceDbgValue(M, Res);
60
61 for (DICompileUnit *CU : DIF.compile_units()) {
62 DISourceLanguageName Lang = CU->getSourceLanguage();
63 if (Lang.hasVersionedName()) {
64 auto LangName = static_cast<dwarf::SourceLanguageName>(Lang.getName());
65 Lang = dwarf::toDW_LANG(LangName, Lang.getVersion())
66 .value_or(dwarf::SourceLanguage{});
67 auto *NewCU = DICompileUnit::getDistinct(
68 M.getContext(), Lang, CU->getFile(), CU->getProducer(),
69 CU->isOptimized(), CU->getFlags(), CU->getRuntimeVersion(),
70 CU->getSplitDebugFilename(), CU->getEmissionKind(),
71 CU->getEnumTypes(), CU->getRetainedTypes(), CU->getGlobalVariables(),
72 CU->getImportedEntities(), CU->getMacros(), CU->getDWOId(),
73 CU->getSplitDebugInlining(), CU->getDebugInfoForProfiling(),
74 CU->getNameTableKind(), CU->getRangesBaseAddress(), CU->getSysRoot(),
75 CU->getSDK());
76 Res.MDReplace.insert({CU, NewCU});
77 }
78 }
79
80 std::vector<std::pair<const DICompileUnit *, const Metadata *>> CUSubprograms;
81
82 for (const Function &F : M) {
83 if (const DISubprogram *SP = F.getSubprogram()) {
84 auto *FunctionMD = ConstantAsMetadata::get(const_cast<Function *>(&F));
85 Res.MDExtra.insert({SP, FunctionMD});
86 }
87 }
88
89 for (const DISubprogram *SP : DIF.subprograms()) {
90 const DISubprogram *NewSP = SP;
91
92 static constexpr auto SupportedDIFlags =
93 static_cast<DISubprogram::DIFlags>(DISubprogram::FlagExportSymbols - 1);
94 static constexpr auto SupportedDISPFlags =
95 static_cast<DISubprogram::DISPFlags>(DISubprogram::SPFlagPure - 1);
96 if (SP->isDistinct() || SP->getFlags() & ~SupportedDIFlags ||
97 SP->getSPFlags() & ~SupportedDISPFlags) {
98 NewSP = DISubprogram::get(
99 M.getContext(), SP->getScope(), SP->getName(), SP->getLinkageName(),
100 SP->getFile(), SP->getLine(), SP->getType(), SP->getScopeLine(),
101 SP->getContainingType(), SP->getVirtualIndex(),
102 SP->getThisAdjustment(), SP->getFlags() & SupportedDIFlags,
103 SP->getSPFlags() & SupportedDISPFlags, SP->getUnit(),
104 SP->getTemplateParams(), SP->getDeclaration(), SP->getRetainedNodes(),
105 SP->getThrownTypes(), SP->getAnnotations(), SP->getTargetFuncName(),
106 SP->getKeyInstructionsEnabled());
107
108 Res.MDReplace.insert({SP, NewSP});
109 if (auto It = Res.MDExtra.find(SP); It != Res.MDExtra.end()) {
110 const Metadata *FunctionMD = It->second;
111 Res.MDExtra.erase(It);
112 Res.MDExtra.insert({NewSP, FunctionMD});
113 }
114 }
115
116 if (SP->getUnit())
117 CUSubprograms.push_back({SP->getUnit(), SP});
118 }
119
120 std::stable_sort(
121 CUSubprograms.begin(), CUSubprograms.end(), [](auto &&A, auto &&B) {
122 return std::less<const DICompileUnit *>()(A.first, B.first);
123 });
124 for (auto It = CUSubprograms.begin(), End = CUSubprograms.end(); It != End;) {
125 const DICompileUnit *CU = It->first;
126 const DICompileUnit *NewCU =
128 SmallVector<Metadata *, 16> Subprograms;
129 do {
130 Subprograms.push_back(const_cast<Metadata *>(It->second));
131 } while (++It != End && It->first == CU);
132 const auto *SubprogramsMD = MDTuple::get(M.getContext(), Subprograms);
133 Res.MDExtra.insert({NewCU, SubprogramsMD});
134 }
135
136 for (const GlobalVariable &GV : M.globals()) {
138 GV.getDebugInfo(GVEs);
139 for (DIGlobalVariableExpression *GVE : GVEs) {
140 if (GVE->getExpression()->getNumElements())
141 continue;
142 auto [It, Inserted] = Res.MDExtra.insert(
143 {GVE->getVariable(),
144 ValueAsMetadata::get(const_cast<GlobalVariable *>(&GV))});
145 if (!Inserted)
146 It->second = nullptr;
147 }
148 }
149
151 Res.MDReplace.insert({GVE, GVE->getVariable()});
152
153 for (DIScope *S : DIF.scopes()) {
154 if (auto *CB = dyn_cast<DICommonBlock>(S)) {
155 const Metadata *Scope = CB->getScope();
156 Scope = Res.MDReplace.lookup_or(Scope, Scope);
157 Res.MDReplace.insert({CB, Scope});
158 }
159 }
160
161 for (DIType *T : DIF.types()) {
162 if (auto *SR = dyn_cast<DISubrangeType>(T)) {
163 DIType *BT = SR->getBaseType();
164 if (!BT)
165 BT = DIBasicType::get(SR->getContext(), dwarf::DW_TAG_base_type,
166 SR->getName(), SR->getSizeInBits(),
167 SR->getAlignInBits(), dwarf::DW_ATE_unsigned,
168 SR->getNumExtraInhabitants(),
169 /*DataSizeInBits=*/0, SR->getFlags());
170 Res.MDReplace.insert({T, BT});
171 }
172 }
173
174 return Res;
175}
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 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
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 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.
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
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 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.
static MDTuple * getDistinct(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1575
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1567
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1513
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
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
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
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 collectDXILDebugInfo(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
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559