brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · dc8cc58 Raw
216 lines · cpp
1//===----------------------------------------------------------------------===//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// TosaUtilsGen generates common utility functions for Tosa validation.10//11//===----------------------------------------------------------------------===//12 13#include "mlir/TableGen/Attribute.h"14#include "mlir/TableGen/CodeGenHelpers.h"15#include "mlir/TableGen/EnumInfo.h"16#include "mlir/TableGen/Format.h"17#include "mlir/TableGen/GenInfo.h"18#include "mlir/TableGen/Operator.h"19#include "llvm/ADT/STLExtras.h"20#include "llvm/ADT/Sequence.h"21#include "llvm/ADT/SmallVector.h"22#include "llvm/ADT/StringExtras.h"23#include "llvm/ADT/StringMap.h"24#include "llvm/ADT/StringRef.h"25#include "llvm/ADT/StringSet.h"26#include "llvm/Support/FormatVariadic.h"27#include "llvm/Support/raw_ostream.h"28#include "llvm/TableGen/Error.h"29#include "llvm/TableGen/Record.h"30#include "llvm/TableGen/TableGenBackend.h"31 32#include <list>33#include <optional>34 35using llvm::formatv;36using llvm::raw_ostream;37using llvm::Record;38using llvm::RecordKeeper;39using llvm::StringMap;40using llvm::StringRef;41using mlir::tblgen::Operator;42 43//===----------------------------------------------------------------------===//44// Availability Wrapper Class45//===----------------------------------------------------------------------===//46 47namespace {48// Wrapper class with helper methods for accessing availability defined in49// TableGen.50class Availability {51public:52  explicit Availability(const Record *def);53 54  // Returns the name of the direct TableGen class for this availability55  // instance.56  StringRef getClass() const;57 58  // Returns the name of the query function insided the generated C++ interface.59  StringRef getQueryFnName() const;60 61  // Returns the return type of the query function insided the generated C++62  // interface.63  StringRef getQueryFnRetType() const;64 65  // Returns the code for merging availability requirements.66  StringRef getMergeActionCode() const;67 68  // Returns the initializer expression for initializing the final availability69  // requirements.70  StringRef getMergeInitializer() const;71 72  // Returns the C++ statements for preparing availability instance.73  StringRef getMergeInstancePreparation() const;74 75  // Returns the concrete availability instance carried in this case.76  StringRef getMergeInstance() const;77 78  // Returns the underlying LLVM TableGen Record.79  const llvm::Record *getDef() const { return def; }80 81private:82  // The TableGen definition of this availability.83  const llvm::Record *def;84};85} // namespace86 87Availability::Availability(const llvm::Record *def) : def(def) {88  assert(def->isSubClassOf("Availability") &&89         "must be subclass of TableGen 'Availability' class");90}91 92StringRef Availability::getClass() const {93  if (def->getDirectSuperClasses().size() != 1) {94    PrintFatalError(def->getLoc(),95                    "expected to only have one direct superclass");96  }97  return def->getDirectSuperClasses().front().first->getName();98}99 100StringRef Availability::getQueryFnRetType() const {101  return def->getValueAsString("queryFnRetType");102}103 104StringRef Availability::getQueryFnName() const {105  return def->getValueAsString("queryFnName");106}107 108StringRef Availability::getMergeActionCode() const {109  return def->getValueAsString("mergeAction");110}111 112StringRef Availability::getMergeInitializer() const {113  return def->getValueAsString("initializer");114}115 116StringRef Availability::getMergeInstancePreparation() const {117  return def->getValueAsString("instancePreparation");118}119 120StringRef Availability::getMergeInstance() const {121  return def->getValueAsString("instance");122}123 124// Returns the availability spec of the given `def`.125static std::vector<Availability> getAvailabilities(const Record &def) {126  std::vector<Availability> availabilities;127 128  if (def.getValue("availability")) {129    std::vector<const Record *> availDefs =130        def.getValueAsListOfDefs("availability");131    availabilities.reserve(availDefs.size());132    for (const Record *avail : availDefs)133      availabilities.emplace_back(avail);134  }135 136  return availabilities;137}138 139//===----------------------------------------------------------------------===//140// Tosa Availability Impl AutoGen141//===----------------------------------------------------------------------===//142 143static void emitAvailabilityImpl(const Operator &srcOp, raw_ostream &os) {144  mlir::tblgen::FmtContext fctx;145  fctx.addSubst("overall", "tblgen_overall");146 147  std::vector<Availability> opAvailabilities =148      getAvailabilities(srcOp.getDef());149 150  // First collect all availability classes this op should implement.151  // All availability instances keep information for the generated interface and152  // the instance's specific requirement. Here we remember a random instance so153  // we can get the information regarding the generated interface.154  llvm::StringMap<Availability> availClasses;155  for (const Availability &avail : opAvailabilities)156    availClasses.try_emplace(avail.getClass(), avail);157 158  // Then generate implementation for each availability class.159  for (const auto &availClass : availClasses) {160    StringRef availClassName = availClass.getKey();161    Availability avail = availClass.getValue();162 163    // Generate the implementation method signature.164    os << formatv("{0} {1}::{2}() {{\n", avail.getQueryFnRetType(),165                  srcOp.getCppClassName(), avail.getQueryFnName());166 167    // Create the variable for the final requirement and initialize it.168    os << formatv("  {0} tblgen_overall = {1};\n", avail.getQueryFnRetType(),169                  avail.getMergeInitializer());170 171    // Update with the op's specific availability spec.172    for (const Availability &avail : opAvailabilities)173      if (avail.getClass() == availClassName &&174          (!avail.getMergeInstancePreparation().empty() ||175           !avail.getMergeActionCode().empty())) {176        os << "  {\n    "177           // Prepare this instance.178           << avail.getMergeInstancePreparation()179           << "\n    "180           // Merge this instance.181           << std::string(182                  tgfmt(avail.getMergeActionCode(),183                        &fctx.addSubst("instance", avail.getMergeInstance())))184           << ";\n  }\n";185      }186 187    os << "  return tblgen_overall;\n";188    os << "}\n";189  }190}191 192static bool emitAvailabilityImpl(const RecordKeeper &recordKeeper,193                                 raw_ostream &os) {194  llvm::emitSourceFileHeader("Tosa Op Availability Implementations", os,195                             recordKeeper);196 197  auto defs = recordKeeper.getAllDerivedDefinitions("Tosa_Op");198  for (const auto *def : defs) {199    Operator op(def);200    if (def->getValueAsBit("autogenAvailability"))201      emitAvailabilityImpl(op, os);202  }203  return false;204}205 206//===----------------------------------------------------------------------===//207// Op Availability Implementation Hook Registration208//===----------------------------------------------------------------------===//209 210static mlir::GenRegistration211    genOpAvailabilityImpl("gen-tosa-avail-impls",212                          "Generate Tosa operation utility definitions",213                          [](const RecordKeeper &records, raw_ostream &os) {214                            return emitAvailabilityImpl(records, os);215                          });216