diff --git a/llvm/lib/Target/DirectX/CMakeLists.txt b/llvm/lib/Target/DirectX/CMakeLists.txt --- a/llvm/lib/Target/DirectX/CMakeLists.txt +++ b/llvm/lib/Target/DirectX/CMakeLists.txt @@ -17,6 +17,7 @@ DirectXRegisterInfo.cpp DirectXSubtarget.cpp DirectXTargetMachine.cpp + DXILMetadata.cpp DXILOpBuilder.cpp DXILOpLowering.cpp DXILPrepare.cpp diff --git a/llvm/lib/Target/DirectX/DXILMetadata.h b/llvm/lib/Target/DirectX/DXILMetadata.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/DirectX/DXILMetadata.h @@ -0,0 +1,36 @@ +//===- DXILMetadata.h - DXIL Metadata helper objects ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file This file contains helper objects for working with DXIL metadata. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_DIRECTX_DXILMETADATA_H +#define LLVM_TARGET_DIRECTX_DXILMETADATA_H + +namespace llvm { +class Module; +class NamedMDNode; +class VersionTuple; +namespace dxil { + +class ValidatorVersionMD { + NamedMDNode *Entry; + +public: + ValidatorVersionMD(Module &M); + + void update(VersionTuple ValidatorVer); + + bool isEmpty(); +}; + +} // namespace dxil +} // namespace llvm + +#endif // LLVM_TARGET_DIRECTX_DXILMETADATA_H diff --git a/llvm/lib/Target/DirectX/DXILMetadata.cpp b/llvm/lib/Target/DirectX/DXILMetadata.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/DirectX/DXILMetadata.cpp @@ -0,0 +1,40 @@ +//===- DXILMetadata.cpp - DXIL Metadata helper objects --------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file This file contains helper objects for working with DXIL metadata. +/// +//===----------------------------------------------------------------------===// + +#include "DXILMetadata.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/VersionTuple.h" + +using namespace llvm; +using namespace llvm::dxil; + +ValidatorVersionMD::ValidatorVersionMD(Module &M) + : Entry(M.getOrInsertNamedMetadata("dx.valver")) {} + +void ValidatorVersionMD::update(VersionTuple ValidatorVer) { + auto &Ctx = Entry->getParent()->getContext(); + IRBuilder<> B(Ctx); + Metadata *MDVals[2]; + + MDVals[0] = ConstantAsMetadata::get(B.getInt32(ValidatorVer.getMajor())); + MDVals[1] = + ConstantAsMetadata::get(B.getInt32(ValidatorVer.getMinor().value_or(0))); + + if (isEmpty()) + Entry->addOperand(MDNode::get(Ctx, MDVals)); + else + Entry->setOperand(0, MDNode::get(Ctx, MDVals)); +} + +bool ValidatorVersionMD::isEmpty() { return Entry->getNumOperands() == 0; } diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp --- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp @@ -8,6 +8,7 @@ /// //===----------------------------------------------------------------------===// +#include "DXILMetadata.h" #include "DirectX.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/Triple.h" @@ -18,69 +19,24 @@ using namespace llvm; -static uint32_t ConstMDToUint32(const MDOperand &MDO) { - ConstantInt *pConst = mdconst::extract(MDO); - return (uint32_t)pConst->getZExtValue(); -} - -static ConstantAsMetadata *Uint32ToConstMD(unsigned v, LLVMContext &Ctx) { - return ConstantAsMetadata::get( - Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v))); -} - -constexpr StringLiteral ValVerKey = "dx.valver"; -constexpr unsigned DXILVersionNumFields = 2; - -static void emitDXILValidatorVersion(Module &M, VersionTuple &ValidatorVer) { - NamedMDNode *DXILValidatorVersionMD = M.getNamedMetadata(ValVerKey); - - // Allow re-writing the validator version, since this can be changed at - // later points. - if (DXILValidatorVersionMD) - M.eraseNamedMetadata(DXILValidatorVersionMD); - - DXILValidatorVersionMD = M.getOrInsertNamedMetadata(ValVerKey); - - auto &Ctx = M.getContext(); - Metadata *MDVals[DXILVersionNumFields]; - MDVals[0] = Uint32ToConstMD(ValidatorVer.getMajor(), Ctx); - MDVals[1] = Uint32ToConstMD(ValidatorVer.getMinor().value_or(0), Ctx); - - DXILValidatorVersionMD->addOperand(MDNode::get(Ctx, MDVals)); -} - -static VersionTuple loadDXILValidatorVersion(MDNode *ValVerMD) { - if (ValVerMD->getNumOperands() != DXILVersionNumFields) - return VersionTuple(); - - unsigned Major = ConstMDToUint32(ValVerMD->getOperand(0)); - unsigned Minor = ConstMDToUint32(ValVerMD->getOperand(1)); - return VersionTuple(Major, Minor); -} - namespace { class DXILTranslateMetadata : public ModulePass { public: static char ID; // Pass identification, replacement for typeid - explicit DXILTranslateMetadata() : ModulePass(ID), ValidatorVer(1, 0) {} + explicit DXILTranslateMetadata() : ModulePass(ID) {} StringRef getPassName() const override { return "DXIL Metadata Emit"; } bool runOnModule(Module &M) override; - -private: - VersionTuple ValidatorVer; }; } // namespace bool DXILTranslateMetadata::runOnModule(Module &M) { - if (NamedMDNode *ValVerMD = M.getNamedMetadata(ValVerKey)) { - VersionTuple ValVer = loadDXILValidatorVersion(ValVerMD->getOperand(0)); - if (!ValVer.empty()) - ValidatorVer = ValVer; - } - emitDXILValidatorVersion(M, ValidatorVer); + + dxil::ValidatorVersionMD ValVerMD(M); + if (ValVerMD.isEmpty()) + ValVerMD.update(VersionTuple(1, 0)); return false; }