1 //===- DXILTranslateMetadata.cpp - Pass to emit DXIL metadata ---*- C++ -*-===// 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 //===----------------------------------------------------------------------===// 10 11 #include "DirectX.h" 12 #include "llvm/ADT/Triple.h" 13 #include "llvm/IR/Constants.h" 14 #include "llvm/IR/Module.h" 15 #include "llvm/Pass.h" 16 17 using namespace llvm; 18 19 static uint32_t ConstMDToUint32(const MDOperand &MDO) { 20 ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO); 21 return (uint32_t)pConst->getZExtValue(); 22 } 23 24 static ConstantAsMetadata *Uint32ToConstMD(unsigned v, LLVMContext &Ctx) { 25 return ConstantAsMetadata::get( 26 Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v))); 27 } 28 29 constexpr StringLiteral ValVerKey = "dx.valver"; 30 constexpr unsigned DXILVersionNumFields = 2; 31 32 static void emitDXILValidatorVersion(Module &M, VersionTuple &ValidatorVer) { 33 NamedMDNode *DXILValidatorVersionMD = M.getNamedMetadata(ValVerKey); 34 35 // Allow re-writing the validator version, since this can be changed at 36 // later points. 37 if (DXILValidatorVersionMD) 38 M.eraseNamedMetadata(DXILValidatorVersionMD); 39 40 DXILValidatorVersionMD = M.getOrInsertNamedMetadata(ValVerKey); 41 42 auto &Ctx = M.getContext(); 43 Metadata *MDVals[DXILVersionNumFields]; 44 MDVals[0] = Uint32ToConstMD(ValidatorVer.getMajor(), Ctx); 45 MDVals[1] = Uint32ToConstMD(ValidatorVer.getMinor().getValueOr(0), Ctx); 46 47 DXILValidatorVersionMD->addOperand(MDNode::get(Ctx, MDVals)); 48 } 49 50 static VersionTuple loadDXILValidatorVersion(MDNode *ValVerMD) { 51 if (ValVerMD->getNumOperands() != DXILVersionNumFields) 52 return VersionTuple(); 53 54 unsigned Major = ConstMDToUint32(ValVerMD->getOperand(0)); 55 unsigned Minor = ConstMDToUint32(ValVerMD->getOperand(1)); 56 return VersionTuple(Major, Minor); 57 } 58 59 static void cleanModule(Module &M) { 60 M.getOrInsertModuleFlagsMetadata()->eraseFromParent(); 61 } 62 63 namespace { 64 class DXILTranslateMetadata : public ModulePass { 65 public: 66 static char ID; // Pass identification, replacement for typeid 67 explicit DXILTranslateMetadata() : ModulePass(ID), ValidatorVer(1, 0) {} 68 69 StringRef getPassName() const override { return "DXIL Metadata Emit"; } 70 71 bool runOnModule(Module &M) override; 72 73 private: 74 VersionTuple ValidatorVer; 75 }; 76 77 } // namespace 78 79 bool DXILTranslateMetadata::runOnModule(Module &M) { 80 if (MDNode *ValVerMD = cast_or_null<MDNode>(M.getModuleFlag(ValVerKey))) { 81 auto ValVer = loadDXILValidatorVersion(ValVerMD); 82 if (!ValVer.empty()) 83 ValidatorVer = ValVer; 84 } 85 emitDXILValidatorVersion(M, ValidatorVer); 86 cleanModule(M); 87 return false; 88 } 89 90 char DXILTranslateMetadata::ID = 0; 91 92 ModulePass *llvm::createDXILTranslateMetadataPass() { 93 return new DXILTranslateMetadata(); 94 } 95 96 INITIALIZE_PASS(DXILTranslateMetadata, "dxil-metadata-emit", 97 "DXIL Metadata Emit", false, false) 98