xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1*81ad6265SDimitry Andric //===- DXILTranslateMetadata.cpp - Pass to emit DXIL metadata ---*- C++ -*-===//
2*81ad6265SDimitry Andric //
3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*81ad6265SDimitry Andric //
7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
8*81ad6265SDimitry Andric ///
9*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
10*81ad6265SDimitry Andric 
11*81ad6265SDimitry Andric #include "DirectX.h"
12*81ad6265SDimitry Andric #include "llvm/ADT/StringSet.h"
13*81ad6265SDimitry Andric #include "llvm/ADT/Triple.h"
14*81ad6265SDimitry Andric #include "llvm/IR/Constants.h"
15*81ad6265SDimitry Andric #include "llvm/IR/Metadata.h"
16*81ad6265SDimitry Andric #include "llvm/IR/Module.h"
17*81ad6265SDimitry Andric #include "llvm/Pass.h"
18*81ad6265SDimitry Andric 
19*81ad6265SDimitry Andric using namespace llvm;
20*81ad6265SDimitry Andric 
21*81ad6265SDimitry Andric static uint32_t ConstMDToUint32(const MDOperand &MDO) {
22*81ad6265SDimitry Andric   ConstantInt *pConst = mdconst::extract<ConstantInt>(MDO);
23*81ad6265SDimitry Andric   return (uint32_t)pConst->getZExtValue();
24*81ad6265SDimitry Andric }
25*81ad6265SDimitry Andric 
26*81ad6265SDimitry Andric static ConstantAsMetadata *Uint32ToConstMD(unsigned v, LLVMContext &Ctx) {
27*81ad6265SDimitry Andric   return ConstantAsMetadata::get(
28*81ad6265SDimitry Andric       Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v)));
29*81ad6265SDimitry Andric }
30*81ad6265SDimitry Andric 
31*81ad6265SDimitry Andric constexpr StringLiteral ValVerKey = "dx.valver";
32*81ad6265SDimitry Andric constexpr unsigned DXILVersionNumFields = 2;
33*81ad6265SDimitry Andric 
34*81ad6265SDimitry Andric static void emitDXILValidatorVersion(Module &M, VersionTuple &ValidatorVer) {
35*81ad6265SDimitry Andric   NamedMDNode *DXILValidatorVersionMD = M.getNamedMetadata(ValVerKey);
36*81ad6265SDimitry Andric 
37*81ad6265SDimitry Andric   // Allow re-writing the validator version, since this can be changed at
38*81ad6265SDimitry Andric   // later points.
39*81ad6265SDimitry Andric   if (DXILValidatorVersionMD)
40*81ad6265SDimitry Andric     M.eraseNamedMetadata(DXILValidatorVersionMD);
41*81ad6265SDimitry Andric 
42*81ad6265SDimitry Andric   DXILValidatorVersionMD = M.getOrInsertNamedMetadata(ValVerKey);
43*81ad6265SDimitry Andric 
44*81ad6265SDimitry Andric   auto &Ctx = M.getContext();
45*81ad6265SDimitry Andric   Metadata *MDVals[DXILVersionNumFields];
46*81ad6265SDimitry Andric   MDVals[0] = Uint32ToConstMD(ValidatorVer.getMajor(), Ctx);
47*81ad6265SDimitry Andric   MDVals[1] = Uint32ToConstMD(ValidatorVer.getMinor().value_or(0), Ctx);
48*81ad6265SDimitry Andric 
49*81ad6265SDimitry Andric   DXILValidatorVersionMD->addOperand(MDNode::get(Ctx, MDVals));
50*81ad6265SDimitry Andric }
51*81ad6265SDimitry Andric 
52*81ad6265SDimitry Andric static VersionTuple loadDXILValidatorVersion(MDNode *ValVerMD) {
53*81ad6265SDimitry Andric   if (ValVerMD->getNumOperands() != DXILVersionNumFields)
54*81ad6265SDimitry Andric     return VersionTuple();
55*81ad6265SDimitry Andric 
56*81ad6265SDimitry Andric   unsigned Major = ConstMDToUint32(ValVerMD->getOperand(0));
57*81ad6265SDimitry Andric   unsigned Minor = ConstMDToUint32(ValVerMD->getOperand(1));
58*81ad6265SDimitry Andric   return VersionTuple(Major, Minor);
59*81ad6265SDimitry Andric }
60*81ad6265SDimitry Andric 
61*81ad6265SDimitry Andric static void cleanModuleFlags(Module &M) {
62*81ad6265SDimitry Andric   constexpr StringLiteral DeadKeys[] = {ValVerKey};
63*81ad6265SDimitry Andric   // Collect DeadKeys in ModuleFlags.
64*81ad6265SDimitry Andric   StringSet<> DeadKeySet;
65*81ad6265SDimitry Andric   for (auto &Key : DeadKeys) {
66*81ad6265SDimitry Andric     if (M.getModuleFlag(Key))
67*81ad6265SDimitry Andric       DeadKeySet.insert(Key);
68*81ad6265SDimitry Andric   }
69*81ad6265SDimitry Andric   if (DeadKeySet.empty())
70*81ad6265SDimitry Andric     return;
71*81ad6265SDimitry Andric 
72*81ad6265SDimitry Andric   SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
73*81ad6265SDimitry Andric   M.getModuleFlagsMetadata(ModuleFlags);
74*81ad6265SDimitry Andric   NamedMDNode *MDFlags = M.getModuleFlagsMetadata();
75*81ad6265SDimitry Andric   MDFlags->eraseFromParent();
76*81ad6265SDimitry Andric   // Add ModuleFlag which not dead.
77*81ad6265SDimitry Andric   for (auto &Flag : ModuleFlags) {
78*81ad6265SDimitry Andric     StringRef Key = Flag.Key->getString();
79*81ad6265SDimitry Andric     if (DeadKeySet.contains(Key))
80*81ad6265SDimitry Andric       continue;
81*81ad6265SDimitry Andric     M.addModuleFlag(Flag.Behavior, Key, Flag.Val);
82*81ad6265SDimitry Andric   }
83*81ad6265SDimitry Andric }
84*81ad6265SDimitry Andric 
85*81ad6265SDimitry Andric static void cleanModule(Module &M) { cleanModuleFlags(M); }
86*81ad6265SDimitry Andric 
87*81ad6265SDimitry Andric namespace {
88*81ad6265SDimitry Andric class DXILTranslateMetadata : public ModulePass {
89*81ad6265SDimitry Andric public:
90*81ad6265SDimitry Andric   static char ID; // Pass identification, replacement for typeid
91*81ad6265SDimitry Andric   explicit DXILTranslateMetadata() : ModulePass(ID), ValidatorVer(1, 0) {}
92*81ad6265SDimitry Andric 
93*81ad6265SDimitry Andric   StringRef getPassName() const override { return "DXIL Metadata Emit"; }
94*81ad6265SDimitry Andric 
95*81ad6265SDimitry Andric   bool runOnModule(Module &M) override;
96*81ad6265SDimitry Andric 
97*81ad6265SDimitry Andric private:
98*81ad6265SDimitry Andric   VersionTuple ValidatorVer;
99*81ad6265SDimitry Andric };
100*81ad6265SDimitry Andric 
101*81ad6265SDimitry Andric } // namespace
102*81ad6265SDimitry Andric 
103*81ad6265SDimitry Andric bool DXILTranslateMetadata::runOnModule(Module &M) {
104*81ad6265SDimitry Andric   if (MDNode *ValVerMD = cast_or_null<MDNode>(M.getModuleFlag(ValVerKey))) {
105*81ad6265SDimitry Andric     auto ValVer = loadDXILValidatorVersion(ValVerMD);
106*81ad6265SDimitry Andric     if (!ValVer.empty())
107*81ad6265SDimitry Andric       ValidatorVer = ValVer;
108*81ad6265SDimitry Andric   }
109*81ad6265SDimitry Andric   emitDXILValidatorVersion(M, ValidatorVer);
110*81ad6265SDimitry Andric   cleanModule(M);
111*81ad6265SDimitry Andric   return false;
112*81ad6265SDimitry Andric }
113*81ad6265SDimitry Andric 
114*81ad6265SDimitry Andric char DXILTranslateMetadata::ID = 0;
115*81ad6265SDimitry Andric 
116*81ad6265SDimitry Andric ModulePass *llvm::createDXILTranslateMetadataPass() {
117*81ad6265SDimitry Andric   return new DXILTranslateMetadata();
118*81ad6265SDimitry Andric }
119*81ad6265SDimitry Andric 
120*81ad6265SDimitry Andric INITIALIZE_PASS(DXILTranslateMetadata, "dxil-metadata-emit",
121*81ad6265SDimitry Andric                 "DXIL Metadata Emit", false, false)
122