File: DXILTranslateMetadata.cpp

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (121 lines) | stat: -rw-r--r-- 3,803 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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)