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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
//===- MlirTblgenMain.cpp - MLIR Tablegen Driver main -----------*- 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
//
//===----------------------------------------------------------------------===//
//
// Main entry function for mlir-tblgen for when built as standalone binary.
//
//===----------------------------------------------------------------------===//
#include "mlir/Tools/mlir-tblgen/MlirTblgenMain.h"
#include "mlir/TableGen/GenInfo.h"
#include "mlir/TableGen/GenNameParser.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Signals.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Main.h"
#include "llvm/TableGen/Record.h"
using namespace mlir;
using namespace llvm;
enum DeprecatedAction { None, Warn, Error };
static DeprecatedAction actionOnDeprecatedValue;
// Returns if there is a use of `deprecatedInit` in `field`.
static bool findUse(Init *field, Init *deprecatedInit,
llvm::DenseMap<Init *, bool> &known) {
if (field == deprecatedInit)
return true;
auto it = known.find(field);
if (it != known.end())
return it->second;
auto memoize = [&](bool val) {
known[field] = val;
return val;
};
if (auto *defInit = dyn_cast<DefInit>(field)) {
// Only recurse into defs if they are anonymous.
// Non-anonymous defs are handled by the main loop, with a proper
// deprecation warning for each. Returning true here, would cause
// all users of a def to also emit a deprecation warning.
if (!defInit->getDef()->isAnonymous())
// Purposefully not memoize as to not include every def use in the map.
// This is also a trivial case we return false for in constant time.
return false;
return memoize(
llvm::any_of(defInit->getDef()->getValues(), [&](const RecordVal &val) {
return findUse(val.getValue(), deprecatedInit, known);
}));
}
if (auto *dagInit = dyn_cast<DagInit>(field)) {
if (findUse(dagInit->getOperator(), deprecatedInit, known))
return memoize(true);
return memoize(llvm::any_of(dagInit->getArgs(), [&](Init *arg) {
return findUse(arg, deprecatedInit, known);
}));
}
if (ListInit *li = dyn_cast<ListInit>(field)) {
return memoize(llvm::any_of(li->getValues(), [&](Init *jt) {
return findUse(jt, deprecatedInit, known);
}));
}
// Purposefully don't use memoize here. There is no need to cache the result
// for every kind of init (e.g. BitInit or StringInit), which will always
// return false. Doing so would grow the DenseMap to include almost every Init
// within the main file.
return false;
}
// Returns if there is a use of `deprecatedInit` in `record`.
static bool findUse(Record &record, Init *deprecatedInit,
llvm::DenseMap<Init *, bool> &known) {
return llvm::any_of(record.getValues(), [&](const RecordVal &val) {
return findUse(val.getValue(), deprecatedInit, known);
});
}
static void warnOfDeprecatedUses(RecordKeeper &records) {
// This performs a direct check for any def marked as deprecated and then
// finds all uses of deprecated def. Deprecated defs are not expected to be
// either numerous or long lived.
bool deprecatedDefsFounds = false;
for (auto &it : records.getDefs()) {
const RecordVal *r = it.second->getValue("odsDeprecated");
if (!r || !r->getValue())
continue;
llvm::DenseMap<Init *, bool> hasUse;
if (auto *si = dyn_cast<StringInit>(r->getValue())) {
for (auto &jt : records.getDefs()) {
// Skip anonymous defs.
if (jt.second->isAnonymous())
continue;
if (findUse(*jt.second, it.second->getDefInit(), hasUse)) {
PrintWarning(jt.second->getLoc(),
"Using deprecated def `" + it.first + "`");
PrintNote(si->getAsUnquotedString());
deprecatedDefsFounds = true;
}
}
}
}
if (deprecatedDefsFounds &&
actionOnDeprecatedValue == DeprecatedAction::Error)
PrintFatalNote("Error'ing out due to deprecated defs");
}
// Generator to invoke.
static const mlir::GenInfo *generator;
// TableGenMain requires a function pointer so this function is passed in which
// simply wraps the call to the generator.
static bool mlirTableGenMain(raw_ostream &os, RecordKeeper &records) {
if (actionOnDeprecatedValue != DeprecatedAction::None)
warnOfDeprecatedUses(records);
if (!generator) {
os << records;
return false;
}
return generator->invoke(records, os);
}
int mlir::MlirTblgenMain(int argc, char **argv) {
llvm::InitLLVM y(argc, argv);
llvm::cl::opt<DeprecatedAction, true> actionOnDeprecated(
"on-deprecated", llvm::cl::desc("Action to perform on deprecated def"),
llvm::cl::values(
clEnumValN(DeprecatedAction::None, "none", "No action"),
clEnumValN(DeprecatedAction::Warn, "warn", "Warn on use"),
clEnumValN(DeprecatedAction::Error, "error", "Error on use")),
cl::location(actionOnDeprecatedValue), llvm::cl::init(Warn));
llvm::cl::opt<const mlir::GenInfo *, true, mlir::GenNameParser> generator(
"", llvm::cl::desc("Generator to run"), cl::location(::generator));
cl::ParseCommandLineOptions(argc, argv);
return TableGenMain(argv[0], &mlirTableGenMain);
}
|