1 | //===- DXContainerGlobals.cpp - DXContainer global generator 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 | // DXContainerGlobalsPass implementation. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "DXILShaderFlags.h" |
14 | #include "DirectX.h" |
15 | #include "llvm/ADT/StringExtras.h" |
16 | #include "llvm/ADT/StringRef.h" |
17 | #include "llvm/BinaryFormat/DXContainer.h" |
18 | #include "llvm/CodeGen/Passes.h" |
19 | #include "llvm/IR/Constants.h" |
20 | #include "llvm/InitializePasses.h" |
21 | #include "llvm/Pass.h" |
22 | #include "llvm/Support/MD5.h" |
23 | #include "llvm/Transforms/Utils/ModuleUtils.h" |
24 | |
25 | using namespace llvm; |
26 | using namespace llvm::dxil; |
27 | |
28 | namespace { |
29 | class DXContainerGlobals : public llvm::ModulePass { |
30 | |
31 | GlobalVariable *getFeatureFlags(Module &M); |
32 | GlobalVariable *computeShaderHash(Module &M); |
33 | |
34 | public: |
35 | static char ID; // Pass identification, replacement for typeid |
36 | DXContainerGlobals() : ModulePass(ID) { |
37 | initializeDXContainerGlobalsPass(*PassRegistry::getPassRegistry()); |
38 | } |
39 | |
40 | StringRef getPassName() const override { |
41 | return "DXContainer Global Emitter" ; |
42 | } |
43 | |
44 | bool runOnModule(Module &M) override; |
45 | |
46 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
47 | AU.setPreservesAll(); |
48 | AU.addRequired<ShaderFlagsAnalysisWrapper>(); |
49 | } |
50 | }; |
51 | |
52 | } // namespace |
53 | |
54 | bool DXContainerGlobals::runOnModule(Module &M) { |
55 | llvm::SmallVector<GlobalValue *> Globals; |
56 | Globals.push_back(Elt: getFeatureFlags(M)); |
57 | Globals.push_back(Elt: computeShaderHash(M)); |
58 | |
59 | appendToCompilerUsed(M, Values: Globals); |
60 | return true; |
61 | } |
62 | |
63 | GlobalVariable *DXContainerGlobals::getFeatureFlags(Module &M) { |
64 | const uint64_t FeatureFlags = |
65 | static_cast<uint64_t>(getAnalysis<ShaderFlagsAnalysisWrapper>() |
66 | .getShaderFlags() |
67 | .getFeatureFlags()); |
68 | |
69 | Constant *FeatureFlagsConstant = |
70 | ConstantInt::get(Context&: M.getContext(), V: APInt(64, FeatureFlags)); |
71 | auto *GV = new llvm::GlobalVariable(M, FeatureFlagsConstant->getType(), true, |
72 | GlobalValue::PrivateLinkage, |
73 | FeatureFlagsConstant, "dx.sfi0" ); |
74 | GV->setSection("SFI0" ); |
75 | GV->setAlignment(Align(4)); |
76 | return GV; |
77 | } |
78 | |
79 | GlobalVariable *DXContainerGlobals::computeShaderHash(Module &M) { |
80 | auto *DXILConstant = |
81 | cast<ConstantDataArray>(Val: M.getNamedGlobal(Name: "dx.dxil" )->getInitializer()); |
82 | MD5 Digest; |
83 | Digest.update(Str: DXILConstant->getRawDataValues()); |
84 | MD5::MD5Result Result = Digest.final(); |
85 | |
86 | dxbc::ShaderHash HashData = {.Flags: 0, .Digest: {0}}; |
87 | // The Hash's IncludesSource flag gets set whenever the hashed shader includes |
88 | // debug information. |
89 | if (M.debug_compile_units_begin() != M.debug_compile_units_end()) |
90 | HashData.Flags = static_cast<uint32_t>(dxbc::HashFlags::IncludesSource); |
91 | |
92 | memcpy(dest: reinterpret_cast<void *>(&HashData.Digest), src: Result.data(), n: 16); |
93 | if (sys::IsBigEndianHost) |
94 | HashData.swapBytes(); |
95 | StringRef Data(reinterpret_cast<char *>(&HashData), sizeof(dxbc::ShaderHash)); |
96 | |
97 | Constant *ModuleConstant = |
98 | ConstantDataArray::get(Context&: M.getContext(), Elts: arrayRefFromStringRef(Input: Data)); |
99 | auto *GV = new llvm::GlobalVariable(M, ModuleConstant->getType(), true, |
100 | GlobalValue::PrivateLinkage, |
101 | ModuleConstant, "dx.hash" ); |
102 | GV->setSection("HASH" ); |
103 | GV->setAlignment(Align(4)); |
104 | return GV; |
105 | } |
106 | |
107 | char DXContainerGlobals::ID = 0; |
108 | INITIALIZE_PASS_BEGIN(DXContainerGlobals, "dxil-globals" , |
109 | "DXContainer Global Emitter" , false, true) |
110 | INITIALIZE_PASS_DEPENDENCY(ShaderFlagsAnalysisWrapper) |
111 | INITIALIZE_PASS_END(DXContainerGlobals, "dxil-globals" , |
112 | "DXContainer Global Emitter" , false, true) |
113 | |
114 | ModulePass *llvm::createDXContainerGlobalsPass() { |
115 | return new DXContainerGlobals(); |
116 | } |
117 | |