MLIR  19.0.0git
MlirTblgenMain.cpp
Go to the documentation of this file.
1 //===- MlirTblgenMain.cpp - MLIR Tablegen Driver main -----------*- 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 // Main entry function for mlir-tblgen for when built as standalone binary.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 
15 #include "mlir/TableGen/GenInfo.h"
17 #include "llvm/Support/CommandLine.h"
18 #include "llvm/Support/FormatVariadic.h"
19 #include "llvm/Support/InitLLVM.h"
20 #include "llvm/Support/Signals.h"
21 #include "llvm/TableGen/Error.h"
22 #include "llvm/TableGen/Main.h"
23 #include "llvm/TableGen/Record.h"
24 
25 using namespace mlir;
26 using namespace llvm;
27 
29 
31 
32 // Returns if there is a use of `deprecatedInit` in `field`.
33 static bool findUse(Init *field, Init *deprecatedInit,
35  if (field == deprecatedInit)
36  return true;
37 
38  auto it = known.find(field);
39  if (it != known.end())
40  return it->second;
41 
42  auto memoize = [&](bool val) {
43  known[field] = val;
44  return val;
45  };
46 
47  if (auto *defInit = dyn_cast<DefInit>(field)) {
48  // Only recurse into defs if they are anonymous.
49  // Non-anonymous defs are handled by the main loop, with a proper
50  // deprecation warning for each. Returning true here, would cause
51  // all users of a def to also emit a deprecation warning.
52  if (!defInit->getDef()->isAnonymous())
53  // Purposefully not memoize as to not include every def use in the map.
54  // This is also a trivial case we return false for in constant time.
55  return false;
56 
57  return memoize(
58  llvm::any_of(defInit->getDef()->getValues(), [&](const RecordVal &val) {
59  return findUse(val.getValue(), deprecatedInit, known);
60  }));
61  }
62 
63  if (auto *dagInit = dyn_cast<DagInit>(field)) {
64  if (findUse(dagInit->getOperator(), deprecatedInit, known))
65  return memoize(true);
66 
67  return memoize(llvm::any_of(dagInit->getArgs(), [&](Init *arg) {
68  return findUse(arg, deprecatedInit, known);
69  }));
70  }
71 
72  if (ListInit *li = dyn_cast<ListInit>(field)) {
73  return memoize(llvm::any_of(li->getValues(), [&](Init *jt) {
74  return findUse(jt, deprecatedInit, known);
75  }));
76  }
77 
78  // Purposefully don't use memoize here. There is no need to cache the result
79  // for every kind of init (e.g. BitInit or StringInit), which will always
80  // return false. Doing so would grow the DenseMap to include almost every Init
81  // within the main file.
82  return false;
83 }
84 
85 // Returns if there is a use of `deprecatedInit` in `record`.
86 static bool findUse(Record &record, Init *deprecatedInit,
88  return llvm::any_of(record.getValues(), [&](const RecordVal &val) {
89  return findUse(val.getValue(), deprecatedInit, known);
90  });
91 }
92 
93 static void warnOfDeprecatedUses(RecordKeeper &records) {
94  // This performs a direct check for any def marked as deprecated and then
95  // finds all uses of deprecated def. Deprecated defs are not expected to be
96  // either numerous or long lived.
97  bool deprecatedDefsFounds = false;
98  for (auto &it : records.getDefs()) {
99  const RecordVal *r = it.second->getValue("odsDeprecated");
100  if (!r || !r->getValue())
101  continue;
102 
104  if (auto *si = dyn_cast<StringInit>(r->getValue())) {
105  for (auto &jt : records.getDefs()) {
106  // Skip anonymous defs.
107  if (jt.second->isAnonymous())
108  continue;
109 
110  if (findUse(*jt.second, it.second->getDefInit(), hasUse)) {
111  PrintWarning(jt.second->getLoc(),
112  "Using deprecated def `" + it.first + "`");
113  PrintNote(si->getAsUnquotedString());
114  deprecatedDefsFounds = true;
115  }
116  }
117  }
118  }
119  if (deprecatedDefsFounds &&
121  PrintFatalNote("Error'ing out due to deprecated defs");
122 }
123 
124 // Generator to invoke.
125 static const mlir::GenInfo *generator;
126 
127 // TableGenMain requires a function pointer so this function is passed in which
128 // simply wraps the call to the generator.
129 static bool mlirTableGenMain(raw_ostream &os, RecordKeeper &records) {
131  warnOfDeprecatedUses(records);
132 
133  if (!generator) {
134  os << records;
135  return false;
136  }
137  return generator->invoke(records, os);
138 }
139 
140 int mlir::MlirTblgenMain(int argc, char **argv) {
141 
142  llvm::InitLLVM y(argc, argv);
143 
144  llvm::cl::opt<DeprecatedAction, true> actionOnDeprecated(
145  "on-deprecated", llvm::cl::desc("Action to perform on deprecated def"),
146  llvm::cl::values(
147  clEnumValN(DeprecatedAction::None, "none", "No action"),
148  clEnumValN(DeprecatedAction::Warn, "warn", "Warn on use"),
149  clEnumValN(DeprecatedAction::Error, "error", "Error on use")),
150  cl::location(actionOnDeprecatedValue), llvm::cl::init(Warn));
151 
152  llvm::cl::opt<const mlir::GenInfo *, true, mlir::GenNameParser> generator(
153  "", llvm::cl::desc("Generator to run"), cl::location(::generator));
154 
155  cl::ParseCommandLineOptions(argc, argv);
156 
157  return TableGenMain(argv[0], &mlirTableGenMain);
158 }
static DeprecatedAction actionOnDeprecatedValue
static const mlir::GenInfo * generator
static bool findUse(Init *field, Init *deprecatedInit, llvm::DenseMap< Init *, bool > &known)
static bool mlirTableGenMain(raw_ostream &os, RecordKeeper &records)
DeprecatedAction
@ Error
@ Warn
@ None
static void warnOfDeprecatedUses(RecordKeeper &records)
Structure to group information about a generator (argument to invoke via mlir-tblgen,...
Definition: GenInfo.h:29
bool invoke(const llvm::RecordKeeper &recordKeeper, raw_ostream &os) const
Invokes the generator and returns whether the generator failed.
Definition: GenInfo.h:37
Include the generated interface declarations.
Definition: CallGraph.h:229
Include the generated interface declarations.
int MlirTblgenMain(int argc, char **argv)
Main Program for tools like 'mlir-tblgen' with custom backends.