183ef862fSRiver Riddle //===- AttrOrTypeDef.cpp - AttrOrTypeDef wrapper classes ------------------===//
283ef862fSRiver Riddle //
383ef862fSRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
483ef862fSRiver Riddle // See https://llvm.org/LICENSE.txt for license information.
583ef862fSRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
683ef862fSRiver Riddle //
783ef862fSRiver Riddle //===----------------------------------------------------------------------===//
883ef862fSRiver Riddle 
983ef862fSRiver Riddle #include "mlir/TableGen/AttrOrTypeDef.h"
1083ef862fSRiver Riddle #include "mlir/TableGen/Dialect.h"
1194662ee0SRiver Riddle #include "llvm/ADT/SmallPtrSet.h"
1283ef862fSRiver Riddle #include "llvm/ADT/StringExtras.h"
1383ef862fSRiver Riddle #include "llvm/TableGen/Error.h"
1483ef862fSRiver Riddle #include "llvm/TableGen/Record.h"
1583ef862fSRiver Riddle 
1683ef862fSRiver Riddle using namespace mlir;
1783ef862fSRiver Riddle using namespace mlir::tblgen;
1883ef862fSRiver Riddle 
1983ef862fSRiver Riddle //===----------------------------------------------------------------------===//
2083ef862fSRiver Riddle // AttrOrTypeBuilder
2183ef862fSRiver Riddle //===----------------------------------------------------------------------===//
2283ef862fSRiver Riddle 
getReturnType() const237fe2294eSJeff Niu Optional<StringRef> AttrOrTypeBuilder::getReturnType() const {
247fe2294eSJeff Niu   Optional<StringRef> type = def->getValueAsOptionalString("returnType");
257fe2294eSJeff Niu   return type && !type->empty() ? type : llvm::None;
267fe2294eSJeff Niu }
277fe2294eSJeff Niu 
hasInferredContextParameter() const2883ef862fSRiver Riddle bool AttrOrTypeBuilder::hasInferredContextParameter() const {
2983ef862fSRiver Riddle   return def->getValueAsBit("hasInferredContextParam");
3083ef862fSRiver Riddle }
3183ef862fSRiver Riddle 
3283ef862fSRiver Riddle //===----------------------------------------------------------------------===//
3383ef862fSRiver Riddle // AttrOrTypeDef
3483ef862fSRiver Riddle //===----------------------------------------------------------------------===//
3583ef862fSRiver Riddle 
AttrOrTypeDef(const llvm::Record * def)3683ef862fSRiver Riddle AttrOrTypeDef::AttrOrTypeDef(const llvm::Record *def) : def(def) {
3783ef862fSRiver Riddle   // Populate the builders.
3883ef862fSRiver Riddle   auto *builderList =
3983ef862fSRiver Riddle       dyn_cast_or_null<llvm::ListInit>(def->getValueInit("builders"));
4083ef862fSRiver Riddle   if (builderList && !builderList->empty()) {
4183ef862fSRiver Riddle     for (llvm::Init *init : builderList->getValues()) {
4283ef862fSRiver Riddle       AttrOrTypeBuilder builder(cast<llvm::DefInit>(init)->getDef(),
4383ef862fSRiver Riddle                                 def->getLoc());
4483ef862fSRiver Riddle 
4583ef862fSRiver Riddle       // Ensure that all parameters have names.
4683ef862fSRiver Riddle       for (const AttrOrTypeBuilder::Parameter &param :
4783ef862fSRiver Riddle            builder.getParameters()) {
4883ef862fSRiver Riddle         if (!param.getName())
4983ef862fSRiver Riddle           PrintFatalError(def->getLoc(), "builder parameters must have a name");
5083ef862fSRiver Riddle       }
5183ef862fSRiver Riddle       builders.emplace_back(builder);
5283ef862fSRiver Riddle     }
5383ef862fSRiver Riddle   }
5494662ee0SRiver Riddle 
5594662ee0SRiver Riddle   // Populate the traits.
5694662ee0SRiver Riddle   if (auto *traitList = def->getValueAsListInit("traits")) {
5794662ee0SRiver Riddle     SmallPtrSet<const llvm::Init *, 32> traitSet;
5894662ee0SRiver Riddle     traits.reserve(traitSet.size());
5994662ee0SRiver Riddle     for (auto *traitInit : *traitList)
6094662ee0SRiver Riddle       if (traitSet.insert(traitInit).second)
6194662ee0SRiver Riddle         traits.push_back(Trait::create(traitInit));
6294662ee0SRiver Riddle   }
63ca6bd9cdSMogball 
64ca6bd9cdSMogball   // Populate the parameters.
65ca6bd9cdSMogball   if (auto *parametersDag = def->getValueAsDag("parameters")) {
66ca6bd9cdSMogball     for (unsigned i = 0, e = parametersDag->getNumArgs(); i < e; ++i)
67ca6bd9cdSMogball       parameters.push_back(AttrOrTypeParameter(parametersDag, i));
68ca6bd9cdSMogball   }
6923e3cbe2SRiver Riddle 
7023e3cbe2SRiver Riddle   // Verify the use of the mnemonic field.
7123e3cbe2SRiver Riddle   bool hasCppFormat = hasCustomAssemblyFormat();
720916d96dSKazu Hirata   bool hasDeclarativeFormat = getAssemblyFormat().has_value();
7323e3cbe2SRiver Riddle   if (getMnemonic()) {
7423e3cbe2SRiver Riddle     if (hasCppFormat && hasDeclarativeFormat) {
7523e3cbe2SRiver Riddle       PrintFatalError(getLoc(), "cannot specify both 'assemblyFormat' "
7623e3cbe2SRiver Riddle                                 "and 'hasCustomAssemblyFormat'");
7723e3cbe2SRiver Riddle     }
7823e3cbe2SRiver Riddle     if (!parameters.empty() && !hasCppFormat && !hasDeclarativeFormat) {
7923e3cbe2SRiver Riddle       PrintFatalError(getLoc(),
8023e3cbe2SRiver Riddle                       "must specify either 'assemblyFormat' or "
8123e3cbe2SRiver Riddle                       "'hasCustomAssemblyFormat' when 'mnemonic' is set");
8223e3cbe2SRiver Riddle     }
8323e3cbe2SRiver Riddle   } else if (hasCppFormat || hasDeclarativeFormat) {
8423e3cbe2SRiver Riddle     PrintFatalError(getLoc(),
8523e3cbe2SRiver Riddle                     "'assemblyFormat' or 'hasCustomAssemblyFormat' can only be "
8623e3cbe2SRiver Riddle                     "used when 'mnemonic' is set");
8723e3cbe2SRiver Riddle   }
8846394861Swren romano   // Assembly format printer requires accessors to be generated.
8923e3cbe2SRiver Riddle   if (hasDeclarativeFormat && !genAccessors()) {
9023e3cbe2SRiver Riddle     PrintFatalError(getLoc(),
9123e3cbe2SRiver Riddle                     "'assemblyFormat' requires 'genAccessors' to be true");
9223e3cbe2SRiver Riddle   }
93*edfc4bb9SJeff Niu   // TODO: Ensure that a suitable builder prototype can be generated:
94*edfc4bb9SJeff Niu   // https://llvm.org/PR56415
9583ef862fSRiver Riddle }
9683ef862fSRiver Riddle 
getDialect() const9783ef862fSRiver Riddle Dialect AttrOrTypeDef::getDialect() const {
9883ef862fSRiver Riddle   auto *dialect = dyn_cast<llvm::DefInit>(def->getValue("dialect")->getValue());
9983ef862fSRiver Riddle   return Dialect(dialect ? dialect->getDef() : nullptr);
10083ef862fSRiver Riddle }
10183ef862fSRiver Riddle 
getName() const10283ef862fSRiver Riddle StringRef AttrOrTypeDef::getName() const { return def->getName(); }
10383ef862fSRiver Riddle 
getCppClassName() const10483ef862fSRiver Riddle StringRef AttrOrTypeDef::getCppClassName() const {
10583ef862fSRiver Riddle   return def->getValueAsString("cppClassName");
10683ef862fSRiver Riddle }
10783ef862fSRiver Riddle 
getCppBaseClassName() const10883ef862fSRiver Riddle StringRef AttrOrTypeDef::getCppBaseClassName() const {
10983ef862fSRiver Riddle   return def->getValueAsString("cppBaseClassName");
11083ef862fSRiver Riddle }
11183ef862fSRiver Riddle 
hasDescription() const11283ef862fSRiver Riddle bool AttrOrTypeDef::hasDescription() const {
11383ef862fSRiver Riddle   const llvm::RecordVal *desc = def->getValue("description");
11483ef862fSRiver Riddle   return desc && isa<llvm::StringInit>(desc->getValue());
11583ef862fSRiver Riddle }
11683ef862fSRiver Riddle 
getDescription() const11783ef862fSRiver Riddle StringRef AttrOrTypeDef::getDescription() const {
11883ef862fSRiver Riddle   return def->getValueAsString("description");
11983ef862fSRiver Riddle }
12083ef862fSRiver Riddle 
hasSummary() const12183ef862fSRiver Riddle bool AttrOrTypeDef::hasSummary() const {
12283ef862fSRiver Riddle   const llvm::RecordVal *summary = def->getValue("summary");
12383ef862fSRiver Riddle   return summary && isa<llvm::StringInit>(summary->getValue());
12483ef862fSRiver Riddle }
12583ef862fSRiver Riddle 
getSummary() const12683ef862fSRiver Riddle StringRef AttrOrTypeDef::getSummary() const {
12783ef862fSRiver Riddle   return def->getValueAsString("summary");
12883ef862fSRiver Riddle }
12983ef862fSRiver Riddle 
getStorageClassName() const13083ef862fSRiver Riddle StringRef AttrOrTypeDef::getStorageClassName() const {
13183ef862fSRiver Riddle   return def->getValueAsString("storageClass");
13283ef862fSRiver Riddle }
13383ef862fSRiver Riddle 
getStorageNamespace() const13483ef862fSRiver Riddle StringRef AttrOrTypeDef::getStorageNamespace() const {
13583ef862fSRiver Riddle   return def->getValueAsString("storageNamespace");
13683ef862fSRiver Riddle }
13783ef862fSRiver Riddle 
genStorageClass() const13883ef862fSRiver Riddle bool AttrOrTypeDef::genStorageClass() const {
13983ef862fSRiver Riddle   return def->getValueAsBit("genStorageClass");
14083ef862fSRiver Riddle }
14183ef862fSRiver Riddle 
hasStorageCustomConstructor() const14283ef862fSRiver Riddle bool AttrOrTypeDef::hasStorageCustomConstructor() const {
14383ef862fSRiver Riddle   return def->getValueAsBit("hasStorageCustomConstructor");
14483ef862fSRiver Riddle }
14583ef862fSRiver Riddle 
getNumParameters() const14683ef862fSRiver Riddle unsigned AttrOrTypeDef::getNumParameters() const {
14783ef862fSRiver Riddle   auto *parametersDag = def->getValueAsDag("parameters");
14883ef862fSRiver Riddle   return parametersDag ? parametersDag->getNumArgs() : 0;
14983ef862fSRiver Riddle }
15083ef862fSRiver Riddle 
getMnemonic() const15183ef862fSRiver Riddle Optional<StringRef> AttrOrTypeDef::getMnemonic() const {
15283ef862fSRiver Riddle   return def->getValueAsOptionalString("mnemonic");
15383ef862fSRiver Riddle }
15483ef862fSRiver Riddle 
hasCustomAssemblyFormat() const15523e3cbe2SRiver Riddle bool AttrOrTypeDef::hasCustomAssemblyFormat() const {
15623e3cbe2SRiver Riddle   return def->getValueAsBit("hasCustomAssemblyFormat");
15783ef862fSRiver Riddle }
15883ef862fSRiver Riddle 
getAssemblyFormat() const1599a2fdc36SJeff Niu Optional<StringRef> AttrOrTypeDef::getAssemblyFormat() const {
1609a2fdc36SJeff Niu   return def->getValueAsOptionalString("assemblyFormat");
1619a2fdc36SJeff Niu }
1629a2fdc36SJeff Niu 
genAccessors() const16383ef862fSRiver Riddle bool AttrOrTypeDef::genAccessors() const {
16483ef862fSRiver Riddle   return def->getValueAsBit("genAccessors");
16583ef862fSRiver Riddle }
16683ef862fSRiver Riddle 
genVerifyDecl() const16783ef862fSRiver Riddle bool AttrOrTypeDef::genVerifyDecl() const {
16883ef862fSRiver Riddle   return def->getValueAsBit("genVerifyDecl");
16983ef862fSRiver Riddle }
17083ef862fSRiver Riddle 
getExtraDecls() const17183ef862fSRiver Riddle Optional<StringRef> AttrOrTypeDef::getExtraDecls() const {
17283ef862fSRiver Riddle   auto value = def->getValueAsString("extraClassDeclaration");
17383ef862fSRiver Riddle   return value.empty() ? Optional<StringRef>() : value;
17483ef862fSRiver Riddle }
17583ef862fSRiver Riddle 
getExtraDefs() const1767f76471eSbhatuzdaname Optional<StringRef> AttrOrTypeDef::getExtraDefs() const {
1777f76471eSbhatuzdaname   auto value = def->getValueAsString("extraClassDefinition");
1787f76471eSbhatuzdaname   return value.empty() ? Optional<StringRef>() : value;
1797f76471eSbhatuzdaname }
1807f76471eSbhatuzdaname 
getLoc() const1816842ec42SRiver Riddle ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); }
18283ef862fSRiver Riddle 
skipDefaultBuilders() const18383ef862fSRiver Riddle bool AttrOrTypeDef::skipDefaultBuilders() const {
18483ef862fSRiver Riddle   return def->getValueAsBit("skipDefaultBuilders");
18583ef862fSRiver Riddle }
18683ef862fSRiver Riddle 
operator ==(const AttrOrTypeDef & other) const18783ef862fSRiver Riddle bool AttrOrTypeDef::operator==(const AttrOrTypeDef &other) const {
18883ef862fSRiver Riddle   return def == other.def;
18983ef862fSRiver Riddle }
19083ef862fSRiver Riddle 
operator <(const AttrOrTypeDef & other) const19183ef862fSRiver Riddle bool AttrOrTypeDef::operator<(const AttrOrTypeDef &other) const {
19283ef862fSRiver Riddle   return getName() < other.getName();
19383ef862fSRiver Riddle }
19483ef862fSRiver Riddle 
19583ef862fSRiver Riddle //===----------------------------------------------------------------------===//
1961447ec51SRiver Riddle // AttrDef
1971447ec51SRiver Riddle //===----------------------------------------------------------------------===//
1981447ec51SRiver Riddle 
getTypeBuilder() const1991447ec51SRiver Riddle Optional<StringRef> AttrDef::getTypeBuilder() const {
2001447ec51SRiver Riddle   return def->getValueAsOptionalString("typeBuilder");
2011447ec51SRiver Riddle }
2021447ec51SRiver Riddle 
classof(const AttrOrTypeDef * def)2031447ec51SRiver Riddle bool AttrDef::classof(const AttrOrTypeDef *def) {
2041447ec51SRiver Riddle   return def->getDef()->isSubClassOf("AttrDef");
2051447ec51SRiver Riddle }
2061447ec51SRiver Riddle 
2071447ec51SRiver Riddle //===----------------------------------------------------------------------===//
20883ef862fSRiver Riddle // AttrOrTypeParameter
20983ef862fSRiver Riddle //===----------------------------------------------------------------------===//
21083ef862fSRiver Riddle 
21107486395SMogball template <typename InitT>
getDefValue(StringRef name) const21207486395SMogball auto AttrOrTypeParameter::getDefValue(StringRef name) const {
21307486395SMogball   Optional<decltype(std::declval<InitT>().getValue())> result;
21407486395SMogball   if (auto *param = dyn_cast<llvm::DefInit>(getDef()))
21507486395SMogball     if (auto *init = param->getDef()->getValue(name))
21607486395SMogball       if (auto *value = dyn_cast_or_null<InitT>(init->getValue()))
21707486395SMogball         result = value->getValue();
21807486395SMogball   return result;
21907486395SMogball }
22007486395SMogball 
isAnonymous() const221761bc83aSMogball bool AttrOrTypeParameter::isAnonymous() const {
222761bc83aSMogball   return !def->getArgName(index);
223761bc83aSMogball }
224761bc83aSMogball 
getName() const22583ef862fSRiver Riddle StringRef AttrOrTypeParameter::getName() const {
22683ef862fSRiver Riddle   return def->getArgName(index)->getValue();
22783ef862fSRiver Riddle }
22883ef862fSRiver Riddle 
getAccessorName() const229baca1c1aSMogball std::string AttrOrTypeParameter::getAccessorName() const {
230baca1c1aSMogball   return "get" +
231baca1c1aSMogball          llvm::convertToCamelFromSnakeCase(getName(), /*capitalizeFirst=*/true);
232baca1c1aSMogball }
233baca1c1aSMogball 
getAllocator() const23483ef862fSRiver Riddle Optional<StringRef> AttrOrTypeParameter::getAllocator() const {
23507486395SMogball   return getDefValue<llvm::StringInit>("allocator");
23683ef862fSRiver Riddle }
23783ef862fSRiver Riddle 
getComparator() const238761bc83aSMogball StringRef AttrOrTypeParameter::getComparator() const {
23930c67587SKazu Hirata   return getDefValue<llvm::StringInit>("comparator").value_or("$_lhs == $_rhs");
24083ef862fSRiver Riddle }
24183ef862fSRiver Riddle 
getCppType() const24283ef862fSRiver Riddle StringRef AttrOrTypeParameter::getCppType() const {
24392bdc5c3SMogball   if (auto *stringType = dyn_cast<llvm::StringInit>(getDef()))
24483ef862fSRiver Riddle     return stringType->getValue();
245c27d8152SKazu Hirata   return getDefValue<llvm::StringInit>("cppType").value();
24683ef862fSRiver Riddle }
24783ef862fSRiver Riddle 
getCppAccessorType() const248c8d9e1ceSRiver Riddle StringRef AttrOrTypeParameter::getCppAccessorType() const {
24907486395SMogball   return getDefValue<llvm::StringInit>("cppAccessorType")
25030c67587SKazu Hirata       .value_or(getCppType());
251c8d9e1ceSRiver Riddle }
252c8d9e1ceSRiver Riddle 
getCppStorageType() const2539a2fdc36SJeff Niu StringRef AttrOrTypeParameter::getCppStorageType() const {
25430c67587SKazu Hirata   return getDefValue<llvm::StringInit>("cppStorageType").value_or(getCppType());
2559a2fdc36SJeff Niu }
2569a2fdc36SJeff Niu 
getConvertFromStorage() const25792bdc5c3SMogball StringRef AttrOrTypeParameter::getConvertFromStorage() const {
25867854f9eSFangrui Song   return getDefValue<llvm::StringInit>("convertFromStorage").value_or("$_self");
25992bdc5c3SMogball }
26092bdc5c3SMogball 
getParser() const2619a2fdc36SJeff Niu Optional<StringRef> AttrOrTypeParameter::getParser() const {
26207486395SMogball   return getDefValue<llvm::StringInit>("parser");
2639a2fdc36SJeff Niu }
2649a2fdc36SJeff Niu 
getPrinter() const2659a2fdc36SJeff Niu Optional<StringRef> AttrOrTypeParameter::getPrinter() const {
26607486395SMogball   return getDefValue<llvm::StringInit>("printer");
2679a2fdc36SJeff Niu }
2689a2fdc36SJeff Niu 
getSummary() const26983ef862fSRiver Riddle Optional<StringRef> AttrOrTypeParameter::getSummary() const {
27007486395SMogball   return getDefValue<llvm::StringInit>("summary");
27183ef862fSRiver Riddle }
27283ef862fSRiver Riddle 
getSyntax() const27383ef862fSRiver Riddle StringRef AttrOrTypeParameter::getSyntax() const {
27407486395SMogball   if (auto *stringType = dyn_cast<llvm::StringInit>(getDef()))
27583ef862fSRiver Riddle     return stringType->getValue();
27630c67587SKazu Hirata   return getDefValue<llvm::StringInit>("syntax").value_or(getCppType());
27783ef862fSRiver Riddle }
2781447ec51SRiver Riddle 
isOptional() const27907486395SMogball bool AttrOrTypeParameter::isOptional() const {
280761bc83aSMogball   // Parameters with default values are automatically optional.
28130c67587SKazu Hirata   return getDefValue<llvm::BitInit>("isOptional").value_or(false) ||
2820916d96dSKazu Hirata          getDefaultValue();
283761bc83aSMogball }
284761bc83aSMogball 
getDefaultValue() const285761bc83aSMogball Optional<StringRef> AttrOrTypeParameter::getDefaultValue() const {
286761bc83aSMogball   return getDefValue<llvm::StringInit>("defaultValue");
2871447ec51SRiver Riddle }
2881447ec51SRiver Riddle 
getDef() const28907486395SMogball llvm::Init *AttrOrTypeParameter::getDef() const { return def->getArg(index); }
29007486395SMogball 
2911447ec51SRiver Riddle //===----------------------------------------------------------------------===//
2921447ec51SRiver Riddle // AttributeSelfTypeParameter
2931447ec51SRiver Riddle //===----------------------------------------------------------------------===//
2941447ec51SRiver Riddle 
classof(const AttrOrTypeParameter * param)2951447ec51SRiver Riddle bool AttributeSelfTypeParameter::classof(const AttrOrTypeParameter *param) {
29607486395SMogball   llvm::Init *paramDef = param->getDef();
2971447ec51SRiver Riddle   if (auto *paramDefInit = dyn_cast<llvm::DefInit>(paramDef))
2981447ec51SRiver Riddle     return paramDefInit->getDef()->isSubClassOf("AttributeSelfTypeParameter");
2991447ec51SRiver Riddle   return false;
3001447ec51SRiver Riddle }
301