brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.6 KiB · 64e86f2 Raw
165 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// Main entry function for mlir-tblgen for when built as standalone binary.10//11//===----------------------------------------------------------------------===//12 13#include "mlir/Tools/mlir-tblgen/MlirTblgenMain.h"14 15#include "mlir/TableGen/GenInfo.h"16#include "mlir/TableGen/GenNameParser.h"17#include "llvm/Support/CommandLine.h"18#include "llvm/Support/InitLLVM.h"19#include "llvm/Support/Signals.h"20#include "llvm/TableGen/Error.h"21#include "llvm/TableGen/Main.h"22#include "llvm/TableGen/Record.h"23 24using namespace mlir;25using namespace llvm;26 27enum DeprecatedAction { None, Warn, Error };28 29static DeprecatedAction actionOnDeprecatedValue;30 31// Returns if there is a use of `deprecatedInit` in `field`.32static bool findUse(const Init *field, const Init *deprecatedInit,33                    llvm::DenseMap<const Init *, bool> &known) {34  if (field == deprecatedInit)35    return true;36 37  auto it = known.find(field);38  if (it != known.end())39    return it->second;40 41  auto memoize = [&](bool val) {42    known[field] = val;43    return val;44  };45 46  if (auto *defInit = dyn_cast<DefInit>(field)) {47    // Only recurse into defs if they are anonymous.48    // Non-anonymous defs are handled by the main loop, with a proper49    // deprecation warning for each. Returning true here, would cause50    // all users of a def to also emit a deprecation warning.51    if (!defInit->getDef()->isAnonymous())52      // Purposefully not memoize as to not include every def use in the map.53      // This is also a trivial case we return false for in constant time.54      return false;55 56    return memoize(57        llvm::any_of(defInit->getDef()->getValues(), [&](const RecordVal &val) {58          return findUse(val.getValue(), deprecatedInit, known);59        }));60  }61 62  if (auto *dagInit = dyn_cast<DagInit>(field)) {63    if (findUse(dagInit->getOperator(), deprecatedInit, known))64      return memoize(true);65 66    return memoize(llvm::any_of(dagInit->getArgs(), [&](const Init *arg) {67      return findUse(arg, deprecatedInit, known);68    }));69  }70 71  if (const ListInit *li = dyn_cast<ListInit>(field)) {72    return memoize(llvm::any_of(li->getElements(), [&](const Init *jt) {73      return findUse(jt, deprecatedInit, known);74    }));75  }76 77  // Purposefully don't use memoize here. There is no need to cache the result78  // for every kind of init (e.g. BitInit or StringInit), which will always79  // return false. Doing so would grow the DenseMap to include almost every Init80  // within the main file.81  return false;82}83 84// Returns if there is a use of `deprecatedInit` in `record`.85static bool findUse(Record &record, const Init *deprecatedInit,86                    llvm::DenseMap<const Init *, bool> &known) {87  return llvm::any_of(record.getValues(), [&](const RecordVal &val) {88    return findUse(val.getValue(), deprecatedInit, known);89  });90}91 92static void warnOfDeprecatedUses(const RecordKeeper &records) {93  // This performs a direct check for any def marked as deprecated and then94  // finds all uses of deprecated def. Deprecated defs are not expected to be95  // either numerous or long lived.96  bool deprecatedDefsFounds = false;97  for (auto &it : records.getDefs()) {98    const RecordVal *r = it.second->getValue("odsDeprecated");99    if (!r || !r->getValue())100      continue;101 102    llvm::DenseMap<const Init *, bool> hasUse;103    if (auto *si = dyn_cast<StringInit>(r->getValue())) {104      for (auto &jt : records.getDefs()) {105        // Skip anonymous defs.106        if (jt.second->isAnonymous())107          continue;108 109        if (findUse(*jt.second, it.second->getDefInit(), hasUse)) {110          PrintWarning(jt.second->getLoc(),111                       "Using deprecated def `" + it.first + "`");112          PrintNote(si->getAsUnquotedString());113          deprecatedDefsFounds = true;114        }115      }116    }117  }118  if (deprecatedDefsFounds &&119      actionOnDeprecatedValue == DeprecatedAction::Error)120    PrintFatalNote("Error'ing out due to deprecated defs");121}122 123// Generator to invoke.124static const mlir::GenInfo *generator;125 126// TableGenMain requires a function pointer so this function is passed in which127// simply wraps the call to the generator.128static bool mlirTableGenMain(raw_ostream &os, const RecordKeeper &records) {129  if (actionOnDeprecatedValue != DeprecatedAction::None)130    warnOfDeprecatedUses(records);131 132  if (!generator) {133    os << records;134    return false;135  }136  return generator->invoke(records, os);137}138 139int mlir::MlirTblgenMain(int argc, char **argv) {140 141  llvm::InitLLVM y(argc, argv);142 143  llvm::cl::opt<DeprecatedAction, true> actionOnDeprecated(144      "on-deprecated", llvm::cl::desc("Action to perform on deprecated def"),145      llvm::cl::values(146          clEnumValN(DeprecatedAction::None, "none", "No action"),147          clEnumValN(DeprecatedAction::Warn, "warn", "Warn on use"),148          clEnumValN(DeprecatedAction::Error, "error", "Error on use")),149      cl::location(actionOnDeprecatedValue), llvm::cl::init(Warn));150 151  llvm::cl::opt<const mlir::GenInfo *, true, mlir::GenNameParser> generator(152      "", llvm::cl::desc("Generator to run"), cl::location(::generator));153 154  cl::ParseCommandLineOptions(argc, argv);155 156  return TableGenMain(157      argv[0], [](TableGenOutputFiles &OutFiles, const RecordKeeper &RK) {158        std::string S;159        raw_string_ostream OS(S);160        bool Res = mlirTableGenMain(OS, RK);161        OutFiles = {S, {}};162        return Res;163      });164}165