LLVM 23.0.0git
DXContainerPDB.cpp
Go to the documentation of this file.
1//===- DXContainerPDB.cpp - DirectX PDB writer pass -----------------------===//
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 "DirectX.h"
10#include "llvm/ADT/StringSet.h"
16#include "llvm/IR/Constants.h"
17#include "llvm/IR/Module.h"
19#include "llvm/Pass.h"
21
22using namespace llvm;
23
24namespace {
25
26class DXContainerPDB : public ModulePass, MCDXContainerBaseWriter {
27 Module *M = nullptr;
29
30 void reset() {
31 M = nullptr;
32 Parts.clear();
33 }
34
35public:
36 static char ID;
37 DXContainerPDB() : ModulePass(ID) {}
38
39 StringRef getPassName() const override { return "DirectX PDB Emitter"; }
40
41 bool runOnModule(Module &M) override;
42
43 void getAnalysisUsage(AnalysisUsage &AU) const override {
44 AU.setPreservesAll();
45 }
46
47 bool shouldSkipSection(StringRef SectionName, size_t SectionSize) override;
48 ArrayRef<MCDXContainerPart> collectParts() override;
49};
50
51} // namespace
52
53bool DXContainerPDB::shouldSkipSection(StringRef SectionName,
54 size_t SectionSize) {
55 if (MCDXContainerBaseWriter::shouldSkipSection(SectionName, SectionSize))
56 return true;
57
58 // Skip sections that are irrelevant for debug info.
59 static const StringSet<> DebugSections{"ILDB", "ILDN", "HASH", "PDBI",
60 "SRCI", "STAT", "RDAT", "VERS"};
61 return !DebugSections.contains(SectionName);
62}
63
65 if (GV.hasInitializer())
66 if (const auto *Data =
68 return Data->getRawDataValues();
69 return {};
70}
71
72ArrayRef<MCDXContainerPart> DXContainerPDB::collectParts() {
73 Parts.clear();
74 for (const GlobalVariable &GV : M->globals()) {
75 StringRef Name = GV.getSection();
76 StringRef Data = getGlobalData(GV);
77
78 if (Data.empty())
79 continue;
80 if (shouldSkipSection(Name, Data.size()))
81 continue;
82
83 Parts.push_back({Name, Data});
84 }
85 return Parts;
86}
87
88bool DXContainerPDB::runOnModule(Module &M) {
89 this->M = &M;
90
91 StringRef DebugFileName;
92 ArrayRef<char> ModuleHash;
93 for (const GlobalVariable &GV : M.globals()) {
94 if (GV.getSection() == PdbFileNameSectionName) {
95 assert(DebugFileName.empty() && "Duplicate PDBNAME section");
96 DebugFileName = getGlobalData(GV);
97 } else if (GV.getSection() == ModuleHashSectionName) {
98 assert(ModuleHash.empty() && "Duplicate PBDHASH section");
99 StringRef Data = getGlobalData(GV);
100 ModuleHash = ArrayRef(Data.data(), Data.size());
101 }
102 }
103
104 // PDB emission was not requested.
105 if (DebugFileName.empty())
106 return false;
107 if (ModuleHash.empty())
108 report_fatal_error("Module hash for PDB not found");
109
111 pdb::PDBFileBuilder Builder(Allocator);
112
113 // DirectXShaderCompiler uses block size 512.
114 if (Error Err = Builder.initialize(512))
115 reportFatalInternalError(std::move(Err));
116
117 // Reserved streams that should be empty.
118 static_assert(pdb::kSpecialStreamCount == 5 &&
119 "First 5 streams should be empty in DirectX PDB file");
120 for (uint32_t I = 0; I < pdb::kSpecialStreamCount; ++I) {
121 if (auto Err = Builder.getMsfBuilder().addStream(0).takeError())
122 reportFatalInternalError(std::move(Err));
123 }
124
125 // Add DXContainer stream.
126 if (auto Err = Builder.getMsfBuilder().addStream(0).takeError())
127 reportFatalInternalError(std::move(Err));
128
129 // InfoStream must be filled. Bitcode hash from HASH part is used for PDB
130 // GUID.
131 codeview::GUID PdbGuid;
132 assert(ModuleHash.size() == std::size(PdbGuid.Guid) &&
133 "Module hash length must be match GUID length");
134 std::copy_n(ModuleHash.begin(), std::size(PdbGuid.Guid), PdbGuid.Guid);
135
136 auto &InfoBuilder = Builder.getInfoBuilder();
137 InfoBuilder.setAge(1);
138 InfoBuilder.setGuid(PdbGuid);
139 InfoBuilder.setSignature(0);
140 InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);
141
142 // Write DXContainer.
143 raw_svector_ostream OS(*Builder.getDXContainerData());
144 write(OS, M.getTargetTriple());
145
146 // Write PDB file.
147 // FIXME(sandboxing): Remove this by routing PDB output through the VFS.
148 auto BypassSandbox = sys::sandbox::scopedDisable();
149 codeview::GUID IgnoredOutGuid;
150 if (Error Err = Builder.commit(DebugFileName, &IgnoredOutGuid))
151 reportFatalUsageError(std::move(Err));
152
153 reset();
154
155 return false;
156}
157
158char DXContainerPDB::ID = 0;
159INITIALIZE_PASS(DXContainerPDB, "dxil-pdb", "DirectX PDB Emitter", false, true)
160
161ModulePass *llvm::createDXContainerPDBPass() { return new DXContainerPDB(); }
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static StringRef getGlobalData(const GlobalVariable &GV)
Module.h This file contains the declarations for the Module class.
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
Basic Register Allocator
StringSet - A set-like wrapper for the StringMap.
void setPreservesAll()
Set by analyses that do not transform their input at all.
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
virtual bool shouldSkipSection(StringRef SectionName, size_t SectionSize)
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
bool contains(StringRef key) const
Check if the set contains the given key.
Definition StringSet.h:60
@ kSpecialStreamCount
ScopedSetting scopedDisable()
Definition IOSandbox.h:36
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
std::array< uint32_t, 5 > ModuleHash
160 bits SHA1
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:173
static constexpr StringLiteral ModuleHashSectionName
Contains module hash.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
ArrayRef(const T &OneElt) -> ArrayRef< T >
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:383
LLVM_ABI Error write(DWPWriter &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue, raw_pwrite_stream *OS=nullptr)
Definition DWP.cpp:721
ModulePass * createDXContainerPDBPass()
Pass for emitting DirectX PDB files.
static constexpr StringLiteral PdbFileNameSectionName
Contains PDB output file name.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
uint8_t Guid[16]
Definition GUID.h:23