diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -13,10 +13,12 @@ #include "DXILShaderFlags.h" #include "DirectX.h" #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/DXContainer.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/Constants.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" +#include "llvm/Support/MD5.h" #include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; @@ -25,6 +27,9 @@ namespace { class DXContainerGlobals : public llvm::ModulePass { + GlobalVariable *getShaderFlags(Module &M); + GlobalVariable *computeShaderHash(Module &M); + public: static char ID; // Pass identification, replacement for typeid DXContainerGlobals() : ModulePass(ID) { @@ -46,6 +51,15 @@ } // namespace bool DXContainerGlobals::runOnModule(Module &M) { + llvm::SmallVector Globals; + Globals.push_back(getShaderFlags(M)); + Globals.push_back(computeShaderHash(M)); + + appendToCompilerUsed(M, Globals); + return true; +} + +GlobalVariable *DXContainerGlobals::getShaderFlags(Module &M) { const uint64_t Flags = (uint64_t)(getAnalysis().getShaderFlags()); @@ -55,8 +69,33 @@ FlagsConstant, "dx.sfi0"); GV->setSection("SFI0"); GV->setAlignment(Align(4)); - appendToCompilerUsed(M, {GV}); - return true; + return GV; +} + +GlobalVariable *DXContainerGlobals::computeShaderHash(Module &M) { + auto *DXILConstant = + cast(M.getNamedGlobal("dx.dxil")->getInitializer()); + MD5 Digest; + Digest.update(DXILConstant->getRawDataValues()); + MD5::MD5Result Result = Digest.final(); + + dxbc::ShaderHash HashData = {0, {0}}; + // The Hash's IncludesSource flag gets set whenever the hashed shader includes + // debug information. + if (M.debug_compile_units_begin() != M.debug_compile_units_end()) + HashData.Flags = static_cast(dxbc::HashFlags::IncludesSource); + + memcpy(reinterpret_cast(&HashData.Digest), Result.data(), 16); + StringRef Data(reinterpret_cast(&HashData), sizeof(dxbc::ShaderHash)); + + Constant *ModuleConstant = + ConstantDataArray::get(M.getContext(), arrayRefFromStringRef(Data)); + auto *GV = new llvm::GlobalVariable(M, ModuleConstant->getType(), true, + GlobalValue::PrivateLinkage, + ModuleConstant, "dx.hash"); + GV->setSection("HASH"); + GV->setAlignment(Align(4)); + return GV; } char DXContainerGlobals::ID = 0; diff --git a/llvm/test/CodeGen/DirectX/ContainerData/DebugShaderHash.ll b/llvm/test/CodeGen/DirectX/ContainerData/DebugShaderHash.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ContainerData/DebugShaderHash.ll @@ -0,0 +1,25 @@ +; RUN: llc %s --filetype=asm -o - | FileCheck %s +; RUN: llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC +target triple = "dxil-unknown-shadermodel6.5-library" + +; CHECK: @dx.hash = private constant [20 x i8] c"\01\00\00\00{{.*}}", section "HASH", align 4 + +define i32 @add(i32 %a, i32 %b) { + %sum = add i32 %a, %b + ret i32 %sum +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Some Compiler", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "hlsl.hlsl", directory: "/some-path") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 2} +!4 = !{i32 2, !"Debug Info Version", i32 3} + +; DXC: - Name: HASH +; DXC: Size: 28 +; DXC: Hash: +; DXC: IncludesSource: true +; DXC: Digest: [ diff --git a/llvm/test/CodeGen/DirectX/ContainerData/ShaderHash.ll b/llvm/test/CodeGen/DirectX/ContainerData/ShaderHash.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ContainerData/ShaderHash.ll @@ -0,0 +1,16 @@ +; RUN: llc %s --filetype=asm -o - | FileCheck %s +; RUN: llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC +target triple = "dxil-unknown-shadermodel6.5-library" + +; CHECK: @dx.hash = private constant [20 x i8] c"\00\00\00\00{{.*}}", section "HASH", align 4 + +define i32 @add(i32 %a, i32 %b) { + %sum = add i32 %a, %b + ret i32 %sum +} + +; DXC: - Name: HASH +; DXC: Size: 28 +; DXC: Hash: +; DXC: IncludesSource: false +; DXC: Digest: [