1 //===- MlirTblgenMain.cpp - MLIR Tablegen Driver main -----------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Main entry function for mlir-tblgen for when built as standalone binary.
11 //===----------------------------------------------------------------------===//
13 #include "mlir/Tools/mlir-tblgen/MlirTblgenMain.h"
15 #include "mlir/TableGen/GenInfo.h"
16 #include "mlir/TableGen/GenNameParser.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"
28 enum DeprecatedAction
{ None
, Warn
, Error
};
30 static DeprecatedAction actionOnDeprecatedValue
;
32 // Returns if there is a use of `deprecatedInit` in `field`.
33 static bool findUse(const Init
*field
, const Init
*deprecatedInit
,
34 llvm::DenseMap
<const Init
*, bool> &known
) {
35 if (field
== deprecatedInit
)
38 auto it
= known
.find(field
);
39 if (it
!= known
.end())
42 auto memoize
= [&](bool val
) {
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.
58 llvm::any_of(defInit
->getDef()->getValues(), [&](const RecordVal
&val
) {
59 return findUse(val
.getValue(), deprecatedInit
, known
);
63 if (auto *dagInit
= dyn_cast
<DagInit
>(field
)) {
64 if (findUse(dagInit
->getOperator(), deprecatedInit
, known
))
67 return memoize(llvm::any_of(dagInit
->getArgs(), [&](const Init
*arg
) {
68 return findUse(arg
, deprecatedInit
, known
);
72 if (const ListInit
*li
= dyn_cast
<ListInit
>(field
)) {
73 return memoize(llvm::any_of(li
->getValues(), [&](const Init
*jt
) {
74 return findUse(jt
, deprecatedInit
, known
);
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.
85 // Returns if there is a use of `deprecatedInit` in `record`.
86 static bool findUse(Record
&record
, const Init
*deprecatedInit
,
87 llvm::DenseMap
<const Init
*, bool> &known
) {
88 return llvm::any_of(record
.getValues(), [&](const RecordVal
&val
) {
89 return findUse(val
.getValue(), deprecatedInit
, known
);
93 static void warnOfDeprecatedUses(const 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())
103 llvm::DenseMap
<const Init
*, bool> hasUse
;
104 if (auto *si
= dyn_cast
<StringInit
>(r
->getValue())) {
105 for (auto &jt
: records
.getDefs()) {
106 // Skip anonymous defs.
107 if (jt
.second
->isAnonymous())
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;
119 if (deprecatedDefsFounds
&&
120 actionOnDeprecatedValue
== DeprecatedAction::Error
)
121 PrintFatalNote("Error'ing out due to deprecated defs");
124 // Generator to invoke.
125 static const mlir::GenInfo
*generator
;
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
, const RecordKeeper
&records
) {
130 if (actionOnDeprecatedValue
!= DeprecatedAction::None
)
131 warnOfDeprecatedUses(records
);
137 return generator
->invoke(records
, os
);
140 int mlir::MlirTblgenMain(int argc
, char **argv
) {
142 llvm::InitLLVM
y(argc
, argv
);
144 llvm::cl::opt
<DeprecatedAction
, true> actionOnDeprecated(
145 "on-deprecated", llvm::cl::desc("Action to perform on deprecated def"),
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
));
152 llvm::cl::opt
<const mlir::GenInfo
*, true, mlir::GenNameParser
> generator(
153 "", llvm::cl::desc("Generator to run"), cl::location(::generator
));
155 cl::ParseCommandLineOptions(argc
, argv
);
157 return TableGenMain(argv
[0], &mlirTableGenMain
);