|
| 1 | +//===- DxilEmitMetadata.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 | +namespace { |
| 20 | +unsigned ConstMDToUint32(const MDOperand &MDO) { |
| 21 | + ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO); |
| 22 | + return (unsigned)pConst->getZExtValue(); |
| 23 | +} |
| 24 | +ConstantAsMetadata *Uint32ToConstMD(unsigned v, LLVMContext &Ctx) { |
| 25 | + return ConstantAsMetadata::get( |
| 26 | + Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v))); |
| 27 | +} |
| 28 | +const StringRef ValVerKey = "dx.valver"; |
| 29 | +const unsigned DxilVersionNumFields = 2; |
| 30 | +const unsigned DxilVersionMajorIdx = 0; // DXIL version major. |
| 31 | +const unsigned DxilVersionMinorIdx = 1; // DXIL version minor. |
| 32 | + |
| 33 | +void emitDxilValidatorVersion(Module &M, VersionTuple &ValidatorVer) { |
| 34 | + NamedMDNode *DxilValidatorVersionMD = M.getNamedMetadata(ValVerKey); |
| 35 | + |
| 36 | + // Allow re-writing the validator version, since this can be changed at |
| 37 | + // later points. |
| 38 | + if (DxilValidatorVersionMD) |
| 39 | + M.eraseNamedMetadata(DxilValidatorVersionMD); |
| 40 | + |
| 41 | + DxilValidatorVersionMD = M.getOrInsertNamedMetadata(ValVerKey); |
| 42 | + |
| 43 | + auto &Ctx = M.getContext(); |
| 44 | + Metadata *MDVals[DxilVersionNumFields]; |
| 45 | + MDVals[DxilVersionMajorIdx] = Uint32ToConstMD(ValidatorVer.getMajor(), Ctx); |
| 46 | + MDVals[DxilVersionMinorIdx] = |
| 47 | + Uint32ToConstMD(ValidatorVer.getMinor().getValueOr(0), Ctx); |
| 48 | + |
| 49 | + DxilValidatorVersionMD->addOperand(MDNode::get(Ctx, MDVals)); |
| 50 | +} |
| 51 | + |
| 52 | +VersionTuple loadDxilValidatorVersion(MDNode *ValVerMD) { |
| 53 | + if (ValVerMD->getNumOperands() != DxilVersionNumFields) |
| 54 | + return VersionTuple(); |
| 55 | + |
| 56 | + unsigned Major = ConstMDToUint32(ValVerMD->getOperand(DxilVersionMajorIdx)); |
| 57 | + unsigned Minor = ConstMDToUint32(ValVerMD->getOperand(DxilVersionMinorIdx)); |
| 58 | + return VersionTuple(Major, Minor); |
| 59 | +} |
| 60 | + |
| 61 | +void cleanModule(Module &M) { |
| 62 | + M.getOrInsertModuleFlagsMetadata()->eraseFromParent(); |
| 63 | +} |
| 64 | +} // namespace |
| 65 | + |
| 66 | +namespace { |
| 67 | +class DxilEmitMetadata : public ModulePass { |
| 68 | +public: |
| 69 | + static char ID; // Pass identification, replacement for typeid |
| 70 | + explicit DxilEmitMetadata() : ModulePass(ID), ValidatorVer(1, 0) {} |
| 71 | + |
| 72 | + StringRef getPassName() const override { return "HLSL DXIL Metadata Emit"; } |
| 73 | + |
| 74 | + bool runOnModule(Module &M) override; |
| 75 | + |
| 76 | +private: |
| 77 | + VersionTuple ValidatorVer; |
| 78 | + void emitDXILVersion(Module &M); |
| 79 | +}; |
| 80 | + |
| 81 | +bool DxilEmitMetadata::runOnModule(Module &M) { |
| 82 | + if (MDNode *ValVerMD = cast_or_null<MDNode>(M.getModuleFlag(ValVerKey))) { |
| 83 | + auto ValVer = loadDxilValidatorVersion(ValVerMD); |
| 84 | + if (!ValVer.empty()) |
| 85 | + ValidatorVer = ValVer; |
| 86 | + } |
| 87 | + emitDxilValidatorVersion(M, ValidatorVer); |
| 88 | + cleanModule(M); |
| 89 | + return false; |
| 90 | +} |
| 91 | + |
| 92 | +void DxilEmitMetadata::emitDXILVersion(Module &M) {} |
| 93 | + |
| 94 | +} // namespace |
| 95 | + |
| 96 | +char DxilEmitMetadata::ID = 0; |
| 97 | + |
| 98 | +ModulePass *llvm::createDxilEmitMetadataPass() { |
| 99 | + return new DxilEmitMetadata(); |
| 100 | +} |
| 101 | + |
| 102 | +INITIALIZE_PASS(DxilEmitMetadata, "hlsl-dxilemit", "HLSL DXIL Metadata Emit", |
| 103 | + false, false) |
0 commit comments