diff --git a/llvm/lib/Target/DirectX/DXILWriter/CMakeLists.txt b/llvm/lib/Target/DirectX/DXILWriter/CMakeLists.txt --- a/llvm/lib/Target/DirectX/DXILWriter/CMakeLists.txt +++ b/llvm/lib/Target/DirectX/DXILWriter/CMakeLists.txt @@ -14,4 +14,5 @@ MC Object Support + TransformUtils ) diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.h b/llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.h --- a/llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.h +++ b/llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.h @@ -27,6 +27,11 @@ /// manager. ModulePass *createDXILWriterPass(raw_ostream &Str); +/// Create and return a pass that writes the module to a global variable in the +/// module for later emission in the MCStreamer. Note that this pass is designed +/// for use with the legacy pass manager because it is run in CodeGen only. +ModulePass *createDXILEmbedderPass(); + } // namespace llvm #endif diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.cpp --- a/llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.cpp +++ b/llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.cpp @@ -15,10 +15,14 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/ModuleSummaryAnalysis.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" +#include "llvm/Support/Alignment.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; using namespace llvm::dxil; @@ -47,6 +51,39 @@ AU.setPreservesAll(); } }; + +class EmbedDXILPass : public llvm::ModulePass { +public: + static char ID; // Pass identification, replacement for typeid + EmbedDXILPass() : ModulePass(ID) { + initializeEmbedDXILPassPass(*PassRegistry::getPassRegistry()); + } + + StringRef getPassName() const override { return "DXIL Embedder"; } + + bool runOnModule(Module &M) override { + std::string Data; + llvm::raw_string_ostream OS(Data); + WriteDXILToFile(M, OS); + + ArrayRef ModuleData = + ArrayRef((const uint8_t *)Data.data(), Data.size()); + + Constant *ModuleConstant = + ConstantDataArray::get(M.getContext(), ModuleData); + GlobalVariable *GV = + new llvm::GlobalVariable(M, ModuleConstant->getType(), true, + GlobalValue::PrivateLinkage, ModuleConstant); + GV->setSection("DXIL"); + GV->setAlignment(Align(4)); + appendToCompilerUsed(M, {GV}); + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } +}; } // namespace char WriteDXILPass::ID = 0; @@ -59,3 +96,8 @@ ModulePass *llvm::createDXILWriterPass(raw_ostream &Str) { return new WriteDXILPass(Str); } + +char EmbedDXILPass::ID = 0; +INITIALIZE_PASS(EmbedDXILPass, "embed-dxil", "Embed DXIL", false, true) + +ModulePass *llvm::createDXILEmbedderPass() { return new EmbedDXILPass(); } diff --git a/llvm/lib/Target/DirectX/DirectX.h b/llvm/lib/Target/DirectX/DirectX.h --- a/llvm/lib/Target/DirectX/DirectX.h +++ b/llvm/lib/Target/DirectX/DirectX.h @@ -18,6 +18,9 @@ /// Initializer for dxil writer pass void initializeWriteDXILPassPass(PassRegistry &); +/// Initializer for dxil embedder pass +void initializeEmbedDXILPassPass(PassRegistry &); + /// Initializer for DXIL-prepare void initializeDXILPrepareModulePass(PassRegistry &); diff --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp --- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp +++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp @@ -87,6 +87,9 @@ PM.add(createDXILPrepareModulePass()); switch (FileType) { case CGFT_AssemblyFile: + if (TargetPassConfig::willCompleteCodeGenPipeline()) { + PM.add(createDXILEmbedderPass()); + } PM.add(createPrintModulePass(Out, "", true)); break; case CGFT_ObjectFile: diff --git a/llvm/test/CodeGen/DirectX/embed-dxil.ll b/llvm/test/CodeGen/DirectX/embed-dxil.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/embed-dxil.ll @@ -0,0 +1,12 @@ +; RUN: llc %s --filetype=asm -o - | FileCheck %s +target triple = "dxil-unknown-unknown" + +define i32 @add(i32 %a, i32 %b) { + %sum = add i32 %a, %b + ret i32 %sum +} + +; CHECK: @0 = private constant [[BC_TYPE:\[[0-9]+ x i8\]]] c"BC\C0\DE{{[^"]+}}", section "DXIL", align 4 +; CHECK: @llvm.compiler.used = appending global [1 x i8*] [i8* getelementptr +; inbounds ([[BC_TYPE]], [[BC_TYPE]]* @0, i32 0, i32 0)], section +; "llvm.metadata"