aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp')
-rw-r--r--llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp121
1 files changed, 121 insertions, 0 deletions
diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
new file mode 100644
index 000000000000..634ead98a6ae
--- /dev/null
+++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
@@ -0,0 +1,121 @@
+//===- DXILTranslateMetadata.cpp - Pass to emit DXIL metadata ---*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+//===----------------------------------------------------------------------===//
+
+#include "DirectX.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+
+using namespace llvm;
+
+static uint32_t ConstMDToUint32(const MDOperand &MDO) {
+ ConstantInt *pConst = mdconst::extract<ConstantInt>(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);
+}
+
+static void cleanModuleFlags(Module &M) {
+ constexpr StringLiteral DeadKeys[] = {ValVerKey};
+ // Collect DeadKeys in ModuleFlags.
+ StringSet<> DeadKeySet;
+ for (auto &Key : DeadKeys) {
+ if (M.getModuleFlag(Key))
+ DeadKeySet.insert(Key);
+ }
+ if (DeadKeySet.empty())
+ return;
+
+ SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
+ M.getModuleFlagsMetadata(ModuleFlags);
+ NamedMDNode *MDFlags = M.getModuleFlagsMetadata();
+ MDFlags->eraseFromParent();
+ // Add ModuleFlag which not dead.
+ for (auto &Flag : ModuleFlags) {
+ StringRef Key = Flag.Key->getString();
+ if (DeadKeySet.contains(Key))
+ continue;
+ M.addModuleFlag(Flag.Behavior, Key, Flag.Val);
+ }
+}
+
+static void cleanModule(Module &M) { cleanModuleFlags(M); }
+
+namespace {
+class DXILTranslateMetadata : public ModulePass {
+public:
+ static char ID; // Pass identification, replacement for typeid
+ explicit DXILTranslateMetadata() : ModulePass(ID), ValidatorVer(1, 0) {}
+
+ StringRef getPassName() const override { return "DXIL Metadata Emit"; }
+
+ bool runOnModule(Module &M) override;
+
+private:
+ VersionTuple ValidatorVer;
+};
+
+} // namespace
+
+bool DXILTranslateMetadata::runOnModule(Module &M) {
+ if (MDNode *ValVerMD = cast_or_null<MDNode>(M.getModuleFlag(ValVerKey))) {
+ auto ValVer = loadDXILValidatorVersion(ValVerMD);
+ if (!ValVer.empty())
+ ValidatorVer = ValVer;
+ }
+ emitDXILValidatorVersion(M, ValidatorVer);
+ cleanModule(M);
+ return false;
+}
+
+char DXILTranslateMetadata::ID = 0;
+
+ModulePass *llvm::createDXILTranslateMetadataPass() {
+ return new DXILTranslateMetadata();
+}
+
+INITIALIZE_PASS(DXILTranslateMetadata, "dxil-metadata-emit",
+ "DXIL Metadata Emit", false, false)