367 lines · cpp
1//===- AttrOrTypeDef.cpp - AttrOrTypeDef wrapper classes ------------------===//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#include "mlir/TableGen/AttrOrTypeDef.h"10#include "mlir/TableGen/Dialect.h"11#include "llvm/ADT/FunctionExtras.h"12#include "llvm/ADT/SmallPtrSet.h"13#include "llvm/ADT/StringExtras.h"14#include "llvm/Support/ErrorHandling.h"15#include "llvm/TableGen/Error.h"16#include "llvm/TableGen/Record.h"17 18using namespace mlir;19using namespace mlir::tblgen;20using llvm::DefInit;21using llvm::Init;22using llvm::ListInit;23using llvm::Record;24using llvm::RecordVal;25using llvm::StringInit;26 27//===----------------------------------------------------------------------===//28// AttrOrTypeBuilder29//===----------------------------------------------------------------------===//30 31std::optional<StringRef> AttrOrTypeBuilder::getReturnType() const {32 std::optional<StringRef> type = def->getValueAsOptionalString("returnType");33 return type && !type->empty() ? type : std::nullopt;34}35 36bool AttrOrTypeBuilder::hasInferredContextParameter() const {37 return def->getValueAsBit("hasInferredContextParam");38}39 40//===----------------------------------------------------------------------===//41// AttrOrTypeDef42//===----------------------------------------------------------------------===//43 44AttrOrTypeDef::AttrOrTypeDef(const Record *def) : def(def) {45 // Populate the builders.46 const auto *builderList =47 dyn_cast_or_null<ListInit>(def->getValueInit("builders"));48 if (builderList && !builderList->empty()) {49 for (const Init *init : builderList->getElements()) {50 AttrOrTypeBuilder builder(cast<DefInit>(init)->getDef(), def->getLoc());51 52 // Ensure that all parameters have names.53 for (const AttrOrTypeBuilder::Parameter ¶m :54 builder.getParameters()) {55 if (!param.getName())56 PrintFatalError(def->getLoc(), "builder parameters must have a name");57 }58 builders.emplace_back(builder);59 }60 }61 62 // Populate the traits.63 if (auto *traitList = def->getValueAsListInit("traits")) {64 SmallPtrSet<const Init *, 32> traitSet;65 traits.reserve(traitSet.size());66 llvm::unique_function<void(const ListInit *)> processTraitList =67 [&](const ListInit *traitList) {68 for (auto *traitInit : *traitList) {69 if (!traitSet.insert(traitInit).second)70 continue;71 72 // If this is an interface, add any bases to the trait list.73 auto *traitDef = cast<DefInit>(traitInit)->getDef();74 if (traitDef->isSubClassOf("Interface")) {75 if (auto *bases = traitDef->getValueAsListInit("baseInterfaces"))76 processTraitList(bases);77 }78 79 traits.push_back(Trait::create(traitInit));80 }81 };82 processTraitList(traitList);83 }84 85 // Populate the parameters.86 if (auto *parametersDag = def->getValueAsDag("parameters")) {87 for (unsigned i = 0, e = parametersDag->getNumArgs(); i < e; ++i)88 parameters.push_back(AttrOrTypeParameter(parametersDag, i));89 }90 91 // Verify the use of the mnemonic field.92 bool hasCppFormat = hasCustomAssemblyFormat();93 bool hasDeclarativeFormat = getAssemblyFormat().has_value();94 if (getMnemonic()) {95 if (hasCppFormat && hasDeclarativeFormat) {96 PrintFatalError(getLoc(), "cannot specify both 'assemblyFormat' "97 "and 'hasCustomAssemblyFormat'");98 }99 if (!parameters.empty() && !hasCppFormat && !hasDeclarativeFormat) {100 PrintFatalError(getLoc(),101 "must specify either 'assemblyFormat' or "102 "'hasCustomAssemblyFormat' when 'mnemonic' is set");103 }104 } else if (hasCppFormat || hasDeclarativeFormat) {105 PrintFatalError(getLoc(),106 "'assemblyFormat' or 'hasCustomAssemblyFormat' can only be "107 "used when 'mnemonic' is set");108 }109 // Assembly format printer requires accessors to be generated.110 if (hasDeclarativeFormat && !genAccessors()) {111 PrintFatalError(getLoc(),112 "'assemblyFormat' requires 'genAccessors' to be true");113 }114 // TODO: Ensure that a suitable builder prototype can be generated:115 // https://llvm.org/PR56415116}117 118Dialect AttrOrTypeDef::getDialect() const {119 const auto *dialect = dyn_cast<DefInit>(def->getValue("dialect")->getValue());120 return Dialect(dialect ? dialect->getDef() : nullptr);121}122 123StringRef AttrOrTypeDef::getName() const { return def->getName(); }124 125StringRef AttrOrTypeDef::getCppClassName() const {126 return def->getValueAsString("cppClassName");127}128 129StringRef AttrOrTypeDef::getCppBaseClassName() const {130 return def->getValueAsString("cppBaseClassName");131}132 133bool AttrOrTypeDef::hasDescription() const {134 const RecordVal *desc = def->getValue("description");135 return desc && isa<StringInit>(desc->getValue());136}137 138StringRef AttrOrTypeDef::getDescription() const {139 return def->getValueAsString("description");140}141 142bool AttrOrTypeDef::hasSummary() const {143 const RecordVal *summary = def->getValue("summary");144 return summary && isa<StringInit>(summary->getValue());145}146 147StringRef AttrOrTypeDef::getSummary() const {148 return def->getValueAsString("summary");149}150 151StringRef AttrOrTypeDef::getStorageClassName() const {152 return def->getValueAsString("storageClass");153}154 155StringRef AttrOrTypeDef::getStorageNamespace() const {156 return def->getValueAsString("storageNamespace");157}158 159bool AttrOrTypeDef::genStorageClass() const {160 return def->getValueAsBit("genStorageClass");161}162 163bool AttrOrTypeDef::hasStorageCustomConstructor() const {164 return def->getValueAsBit("hasStorageCustomConstructor");165}166 167unsigned AttrOrTypeDef::getNumParameters() const {168 auto *parametersDag = def->getValueAsDag("parameters");169 return parametersDag ? parametersDag->getNumArgs() : 0;170}171 172std::optional<StringRef> AttrOrTypeDef::getMnemonic() const {173 return def->getValueAsOptionalString("mnemonic");174}175 176bool AttrOrTypeDef::hasCustomAssemblyFormat() const {177 return def->getValueAsBit("hasCustomAssemblyFormat");178}179 180std::optional<StringRef> AttrOrTypeDef::getAssemblyFormat() const {181 return def->getValueAsOptionalString("assemblyFormat");182}183 184bool AttrOrTypeDef::genAccessors() const {185 return def->getValueAsBit("genAccessors");186}187 188bool AttrOrTypeDef::genVerifyDecl() const {189 return def->getValueAsBit("genVerifyDecl");190}191 192bool AttrOrTypeDef::genVerifyInvariantsImpl() const {193 return any_of(parameters, [](const AttrOrTypeParameter &p) {194 return p.getConstraint() != std::nullopt;195 });196}197 198std::optional<StringRef> AttrOrTypeDef::getExtraDecls() const {199 auto value = def->getValueAsString("extraClassDeclaration");200 return value.empty() ? std::optional<StringRef>() : value;201}202 203std::optional<StringRef> AttrOrTypeDef::getExtraDefs() const {204 auto value = def->getValueAsString("extraClassDefinition");205 return value.empty() ? std::optional<StringRef>() : value;206}207 208bool AttrOrTypeDef::genMnemonicAlias() const {209 return def->getValueAsBit("genMnemonicAlias");210}211 212ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); }213 214bool AttrOrTypeDef::skipDefaultBuilders() const {215 return def->getValueAsBit("skipDefaultBuilders");216}217 218bool AttrOrTypeDef::operator==(const AttrOrTypeDef &other) const {219 return def == other.def;220}221 222bool AttrOrTypeDef::operator<(const AttrOrTypeDef &other) const {223 return getName() < other.getName();224}225 226//===----------------------------------------------------------------------===//227// AttrDef228//===----------------------------------------------------------------------===//229 230std::optional<StringRef> AttrDef::getTypeBuilder() const {231 return def->getValueAsOptionalString("typeBuilder");232}233 234bool AttrDef::classof(const AttrOrTypeDef *def) {235 return def->getDef()->isSubClassOf("AttrDef");236}237 238StringRef AttrDef::getAttrName() const {239 return def->getValueAsString("attrName");240}241 242//===----------------------------------------------------------------------===//243// TypeDef244//===----------------------------------------------------------------------===//245 246bool TypeDef::classof(const AttrOrTypeDef *def) {247 return def->getDef()->isSubClassOf("TypeDef");248}249 250StringRef TypeDef::getTypeName() const {251 return def->getValueAsString("typeName");252}253 254//===----------------------------------------------------------------------===//255// AttrOrTypeParameter256//===----------------------------------------------------------------------===//257 258template <typename InitT>259auto AttrOrTypeParameter::getDefValue(StringRef name) const {260 std::optional<decltype(std::declval<InitT>().getValue())> result;261 if (const auto *param = dyn_cast<DefInit>(getDef()))262 if (const auto *init = param->getDef()->getValue(name))263 if (const auto *value = dyn_cast_or_null<InitT>(init->getValue()))264 result = value->getValue();265 return result;266}267 268bool AttrOrTypeParameter::isAnonymous() const {269 return !def->getArgName(index);270}271 272StringRef AttrOrTypeParameter::getName() const {273 return def->getArgName(index)->getValue();274}275 276std::string AttrOrTypeParameter::getAccessorName() const {277 return "get" +278 llvm::convertToCamelFromSnakeCase(getName(), /*capitalizeFirst=*/true);279}280 281std::optional<StringRef> AttrOrTypeParameter::getAllocator() const {282 return getDefValue<StringInit>("allocator");283}284 285bool AttrOrTypeParameter::hasCustomComparator() const {286 return getDefValue<StringInit>("comparator").has_value();287}288 289StringRef AttrOrTypeParameter::getComparator() const {290 return getDefValue<StringInit>("comparator").value_or("$_lhs == $_rhs");291}292 293StringRef AttrOrTypeParameter::getCppType() const {294 if (auto *stringType = dyn_cast<StringInit>(getDef()))295 return stringType->getValue();296 auto cppType = getDefValue<StringInit>("cppType");297 if (cppType)298 return *cppType;299 if (const auto *init = dyn_cast<DefInit>(getDef()))300 llvm::PrintFatalError(301 init->getDef()->getLoc(),302 Twine("Missing `cppType` field in Attribute/Type parameter: ") +303 init->getAsString());304 llvm::reportFatalUsageError(305 Twine("Missing `cppType` field in Attribute/Type parameter: ") +306 getDef()->getAsString());307}308 309StringRef AttrOrTypeParameter::getCppAccessorType() const {310 return getDefValue<StringInit>("cppAccessorType").value_or(getCppType());311}312 313StringRef AttrOrTypeParameter::getCppStorageType() const {314 return getDefValue<StringInit>("cppStorageType").value_or(getCppType());315}316 317StringRef AttrOrTypeParameter::getConvertFromStorage() const {318 return getDefValue<StringInit>("convertFromStorage").value_or("$_self");319}320 321std::optional<StringRef> AttrOrTypeParameter::getParser() const {322 return getDefValue<StringInit>("parser");323}324 325std::optional<StringRef> AttrOrTypeParameter::getPrinter() const {326 return getDefValue<StringInit>("printer");327}328 329std::optional<StringRef> AttrOrTypeParameter::getSummary() const {330 return getDefValue<StringInit>("summary");331}332 333StringRef AttrOrTypeParameter::getSyntax() const {334 if (auto *stringType = dyn_cast<StringInit>(getDef()))335 return stringType->getValue();336 return getDefValue<StringInit>("syntax").value_or(getCppType());337}338 339bool AttrOrTypeParameter::isOptional() const {340 return getDefaultValue().has_value();341}342 343std::optional<StringRef> AttrOrTypeParameter::getDefaultValue() const {344 std::optional<StringRef> result = getDefValue<StringInit>("defaultValue");345 return result && !result->empty() ? result : std::nullopt;346}347 348const Init *AttrOrTypeParameter::getDef() const { return def->getArg(index); }349 350std::optional<Constraint> AttrOrTypeParameter::getConstraint() const {351 if (const auto *param = dyn_cast<DefInit>(getDef()))352 if (param->getDef()->isSubClassOf("Constraint"))353 return Constraint(param->getDef());354 return std::nullopt;355}356 357//===----------------------------------------------------------------------===//358// AttributeSelfTypeParameter359//===----------------------------------------------------------------------===//360 361bool AttributeSelfTypeParameter::classof(const AttrOrTypeParameter *param) {362 const Init *paramDef = param->getDef();363 if (const auto *paramDefInit = dyn_cast<DefInit>(paramDef))364 return paramDefInit->getDef()->isSubClassOf("AttributeSelfTypeParameter");365 return false;366}367