//===- AttrOrTypeDef.cpp - AttrOrTypeDef wrapper classes ------------------===// // // 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 // //===----------------------------------------------------------------------===// #include "mlir/TableGen/AttrOrTypeDef.h" #include "mlir/TableGen/Dialect.h" #include "llvm/ADT/FunctionExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" using namespace mlir; using namespace mlir::tblgen; //===----------------------------------------------------------------------===// // AttrOrTypeBuilder //===----------------------------------------------------------------------===// std::optional AttrOrTypeBuilder::getReturnType() const { std::optional type = def->getValueAsOptionalString("returnType"); return type && !type->empty() ? type : std::nullopt; } bool AttrOrTypeBuilder::hasInferredContextParameter() const { return def->getValueAsBit("hasInferredContextParam"); } //===----------------------------------------------------------------------===// // AttrOrTypeDef //===----------------------------------------------------------------------===// AttrOrTypeDef::AttrOrTypeDef(const llvm::Record *def) : def(def) { // Populate the builders. auto *builderList = dyn_cast_or_null(def->getValueInit("builders")); if (builderList && !builderList->empty()) { for (llvm::Init *init : builderList->getValues()) { AttrOrTypeBuilder builder(cast(init)->getDef(), def->getLoc()); // Ensure that all parameters have names. for (const AttrOrTypeBuilder::Parameter ¶m : builder.getParameters()) { if (!param.getName()) PrintFatalError(def->getLoc(), "builder parameters must have a name"); } builders.emplace_back(builder); } } // Populate the traits. if (auto *traitList = def->getValueAsListInit("traits")) { SmallPtrSet traitSet; traits.reserve(traitSet.size()); llvm::unique_function processTraitList = [&](llvm::ListInit *traitList) { for (auto *traitInit : *traitList) { if (!traitSet.insert(traitInit).second) continue; // If this is an interface, add any bases to the trait list. auto *traitDef = cast(traitInit)->getDef(); if (traitDef->isSubClassOf("Interface")) { if (auto *bases = traitDef->getValueAsListInit("baseInterfaces")) processTraitList(bases); } traits.push_back(Trait::create(traitInit)); } }; processTraitList(traitList); } // Populate the parameters. if (auto *parametersDag = def->getValueAsDag("parameters")) { for (unsigned i = 0, e = parametersDag->getNumArgs(); i < e; ++i) parameters.push_back(AttrOrTypeParameter(parametersDag, i)); } // Verify the use of the mnemonic field. bool hasCppFormat = hasCustomAssemblyFormat(); bool hasDeclarativeFormat = getAssemblyFormat().has_value(); if (getMnemonic()) { if (hasCppFormat && hasDeclarativeFormat) { PrintFatalError(getLoc(), "cannot specify both 'assemblyFormat' " "and 'hasCustomAssemblyFormat'"); } if (!parameters.empty() && !hasCppFormat && !hasDeclarativeFormat) { PrintFatalError(getLoc(), "must specify either 'assemblyFormat' or " "'hasCustomAssemblyFormat' when 'mnemonic' is set"); } } else if (hasCppFormat || hasDeclarativeFormat) { PrintFatalError(getLoc(), "'assemblyFormat' or 'hasCustomAssemblyFormat' can only be " "used when 'mnemonic' is set"); } // Assembly format printer requires accessors to be generated. if (hasDeclarativeFormat && !genAccessors()) { PrintFatalError(getLoc(), "'assemblyFormat' requires 'genAccessors' to be true"); } // TODO: Ensure that a suitable builder prototype can be generated: // https://llvm.org/PR56415 } Dialect AttrOrTypeDef::getDialect() const { auto *dialect = dyn_cast(def->getValue("dialect")->getValue()); return Dialect(dialect ? dialect->getDef() : nullptr); } StringRef AttrOrTypeDef::getName() const { return def->getName(); } StringRef AttrOrTypeDef::getCppClassName() const { return def->getValueAsString("cppClassName"); } StringRef AttrOrTypeDef::getCppBaseClassName() const { return def->getValueAsString("cppBaseClassName"); } bool AttrOrTypeDef::hasDescription() const { const llvm::RecordVal *desc = def->getValue("description"); return desc && isa(desc->getValue()); } StringRef AttrOrTypeDef::getDescription() const { return def->getValueAsString("description"); } bool AttrOrTypeDef::hasSummary() const { const llvm::RecordVal *summary = def->getValue("summary"); return summary && isa(summary->getValue()); } StringRef AttrOrTypeDef::getSummary() const { return def->getValueAsString("summary"); } StringRef AttrOrTypeDef::getStorageClassName() const { return def->getValueAsString("storageClass"); } StringRef AttrOrTypeDef::getStorageNamespace() const { return def->getValueAsString("storageNamespace"); } bool AttrOrTypeDef::genStorageClass() const { return def->getValueAsBit("genStorageClass"); } bool AttrOrTypeDef::hasStorageCustomConstructor() const { return def->getValueAsBit("hasStorageCustomConstructor"); } unsigned AttrOrTypeDef::getNumParameters() const { auto *parametersDag = def->getValueAsDag("parameters"); return parametersDag ? parametersDag->getNumArgs() : 0; } std::optional AttrOrTypeDef::getMnemonic() const { return def->getValueAsOptionalString("mnemonic"); } bool AttrOrTypeDef::hasCustomAssemblyFormat() const { return def->getValueAsBit("hasCustomAssemblyFormat"); } std::optional AttrOrTypeDef::getAssemblyFormat() const { return def->getValueAsOptionalString("assemblyFormat"); } bool AttrOrTypeDef::genAccessors() const { return def->getValueAsBit("genAccessors"); } bool AttrOrTypeDef::genVerifyDecl() const { return def->getValueAsBit("genVerifyDecl"); } std::optional AttrOrTypeDef::getExtraDecls() const { auto value = def->getValueAsString("extraClassDeclaration"); return value.empty() ? std::optional() : value; } std::optional AttrOrTypeDef::getExtraDefs() const { auto value = def->getValueAsString("extraClassDefinition"); return value.empty() ? std::optional() : value; } ArrayRef AttrOrTypeDef::getLoc() const { return def->getLoc(); } bool AttrOrTypeDef::skipDefaultBuilders() const { return def->getValueAsBit("skipDefaultBuilders"); } bool AttrOrTypeDef::operator==(const AttrOrTypeDef &other) const { return def == other.def; } bool AttrOrTypeDef::operator<(const AttrOrTypeDef &other) const { return getName() < other.getName(); } //===----------------------------------------------------------------------===// // AttrDef //===----------------------------------------------------------------------===// std::optional AttrDef::getTypeBuilder() const { return def->getValueAsOptionalString("typeBuilder"); } bool AttrDef::classof(const AttrOrTypeDef *def) { return def->getDef()->isSubClassOf("AttrDef"); } //===----------------------------------------------------------------------===// // AttrOrTypeParameter //===----------------------------------------------------------------------===// template auto AttrOrTypeParameter::getDefValue(StringRef name) const { std::optional().getValue())> result; if (auto *param = dyn_cast(getDef())) if (auto *init = param->getDef()->getValue(name)) if (auto *value = dyn_cast_or_null(init->getValue())) result = value->getValue(); return result; } bool AttrOrTypeParameter::isAnonymous() const { return !def->getArgName(index); } StringRef AttrOrTypeParameter::getName() const { return def->getArgName(index)->getValue(); } std::string AttrOrTypeParameter::getAccessorName() const { return "get" + llvm::convertToCamelFromSnakeCase(getName(), /*capitalizeFirst=*/true); } std::optional AttrOrTypeParameter::getAllocator() const { return getDefValue("allocator"); } StringRef AttrOrTypeParameter::getComparator() const { return getDefValue("comparator").value_or("$_lhs == $_rhs"); } StringRef AttrOrTypeParameter::getCppType() const { if (auto *stringType = dyn_cast(getDef())) return stringType->getValue(); return *getDefValue("cppType"); } StringRef AttrOrTypeParameter::getCppAccessorType() const { return getDefValue("cppAccessorType") .value_or(getCppType()); } StringRef AttrOrTypeParameter::getCppStorageType() const { return getDefValue("cppStorageType").value_or(getCppType()); } StringRef AttrOrTypeParameter::getConvertFromStorage() const { return getDefValue("convertFromStorage").value_or("$_self"); } std::optional AttrOrTypeParameter::getParser() const { return getDefValue("parser"); } std::optional AttrOrTypeParameter::getPrinter() const { return getDefValue("printer"); } std::optional AttrOrTypeParameter::getSummary() const { return getDefValue("summary"); } StringRef AttrOrTypeParameter::getSyntax() const { if (auto *stringType = dyn_cast(getDef())) return stringType->getValue(); return getDefValue("syntax").value_or(getCppType()); } bool AttrOrTypeParameter::isOptional() const { return getDefaultValue().has_value(); } std::optional AttrOrTypeParameter::getDefaultValue() const { std::optional result = getDefValue("defaultValue"); return result && !result->empty() ? result : std::nullopt; } llvm::Init *AttrOrTypeParameter::getDef() const { return def->getArg(index); } //===----------------------------------------------------------------------===// // AttributeSelfTypeParameter //===----------------------------------------------------------------------===// bool AttributeSelfTypeParameter::classof(const AttrOrTypeParameter *param) { llvm::Init *paramDef = param->getDef(); if (auto *paramDefInit = dyn_cast(paramDef)) return paramDefInit->getDef()->isSubClassOf("AttributeSelfTypeParameter"); return false; }