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-exception 6 // 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 18 using namespace mlir; 19 using namespace mlir::tblgen; 20 using llvm::DefInit; 21 using llvm::Init; 22 using llvm::ListInit; 23 using llvm::Record; 24 using llvm::RecordVal; 25 using llvm::StringInit; 26 27 //===----------------------------------------------------------------------===// 28 // AttrOrTypeBuilder 29 //===----------------------------------------------------------------------===// 30 31 std::optional<StringRef> AttrOrTypeBuilder::getReturnType() const { 32 std::optional<StringRef> type = def->getValueAsOptionalString("returnType"); 33 return type && !type->empty() ? type : std::nullopt; 34 } 35 36 bool AttrOrTypeBuilder::hasInferredContextParameter() const { 37 return def->getValueAsBit("hasInferredContextParam"); 38 } 39 40 //===----------------------------------------------------------------------===// 41 // AttrOrTypeDef 42 //===----------------------------------------------------------------------===// 43 44 AttrOrTypeDef::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->getValues()) { 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/PR56415 116 } 117 118 Dialect AttrOrTypeDef::getDialect() const { 119 const auto *dialect = dyn_cast<DefInit>(def->getValue("dialect")->getValue()); 120 return Dialect(dialect ? dialect->getDef() : nullptr); 121 } 122 123 StringRef AttrOrTypeDef::getName() const { return def->getName(); } 124 125 StringRef AttrOrTypeDef::getCppClassName() const { 126 return def->getValueAsString("cppClassName"); 127 } 128 129 StringRef AttrOrTypeDef::getCppBaseClassName() const { 130 return def->getValueAsString("cppBaseClassName"); 131 } 132 133 bool AttrOrTypeDef::hasDescription() const { 134 const RecordVal *desc = def->getValue("description"); 135 return desc && isa<StringInit>(desc->getValue()); 136 } 137 138 StringRef AttrOrTypeDef::getDescription() const { 139 return def->getValueAsString("description"); 140 } 141 142 bool AttrOrTypeDef::hasSummary() const { 143 const RecordVal *summary = def->getValue("summary"); 144 return summary && isa<StringInit>(summary->getValue()); 145 } 146 147 StringRef AttrOrTypeDef::getSummary() const { 148 return def->getValueAsString("summary"); 149 } 150 151 StringRef AttrOrTypeDef::getStorageClassName() const { 152 return def->getValueAsString("storageClass"); 153 } 154 155 StringRef AttrOrTypeDef::getStorageNamespace() const { 156 return def->getValueAsString("storageNamespace"); 157 } 158 159 bool AttrOrTypeDef::genStorageClass() const { 160 return def->getValueAsBit("genStorageClass"); 161 } 162 163 bool AttrOrTypeDef::hasStorageCustomConstructor() const { 164 return def->getValueAsBit("hasStorageCustomConstructor"); 165 } 166 167 unsigned AttrOrTypeDef::getNumParameters() const { 168 auto *parametersDag = def->getValueAsDag("parameters"); 169 return parametersDag ? parametersDag->getNumArgs() : 0; 170 } 171 172 std::optional<StringRef> AttrOrTypeDef::getMnemonic() const { 173 return def->getValueAsOptionalString("mnemonic"); 174 } 175 176 bool AttrOrTypeDef::hasCustomAssemblyFormat() const { 177 return def->getValueAsBit("hasCustomAssemblyFormat"); 178 } 179 180 std::optional<StringRef> AttrOrTypeDef::getAssemblyFormat() const { 181 return def->getValueAsOptionalString("assemblyFormat"); 182 } 183 184 bool AttrOrTypeDef::genAccessors() const { 185 return def->getValueAsBit("genAccessors"); 186 } 187 188 bool AttrOrTypeDef::genVerifyDecl() const { 189 return def->getValueAsBit("genVerifyDecl"); 190 } 191 192 bool AttrOrTypeDef::genVerifyInvariantsImpl() const { 193 return any_of(parameters, [](const AttrOrTypeParameter &p) { 194 return p.getConstraint() != std::nullopt; 195 }); 196 } 197 198 std::optional<StringRef> AttrOrTypeDef::getExtraDecls() const { 199 auto value = def->getValueAsString("extraClassDeclaration"); 200 return value.empty() ? std::optional<StringRef>() : value; 201 } 202 203 std::optional<StringRef> AttrOrTypeDef::getExtraDefs() const { 204 auto value = def->getValueAsString("extraClassDefinition"); 205 return value.empty() ? std::optional<StringRef>() : value; 206 } 207 208 ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); } 209 210 bool AttrOrTypeDef::skipDefaultBuilders() const { 211 return def->getValueAsBit("skipDefaultBuilders"); 212 } 213 214 bool AttrOrTypeDef::operator==(const AttrOrTypeDef &other) const { 215 return def == other.def; 216 } 217 218 bool AttrOrTypeDef::operator<(const AttrOrTypeDef &other) const { 219 return getName() < other.getName(); 220 } 221 222 //===----------------------------------------------------------------------===// 223 // AttrDef 224 //===----------------------------------------------------------------------===// 225 226 std::optional<StringRef> AttrDef::getTypeBuilder() const { 227 return def->getValueAsOptionalString("typeBuilder"); 228 } 229 230 bool AttrDef::classof(const AttrOrTypeDef *def) { 231 return def->getDef()->isSubClassOf("AttrDef"); 232 } 233 234 StringRef AttrDef::getAttrName() const { 235 return def->getValueAsString("attrName"); 236 } 237 238 //===----------------------------------------------------------------------===// 239 // TypeDef 240 //===----------------------------------------------------------------------===// 241 242 bool TypeDef::classof(const AttrOrTypeDef *def) { 243 return def->getDef()->isSubClassOf("TypeDef"); 244 } 245 246 StringRef TypeDef::getTypeName() const { 247 return def->getValueAsString("typeName"); 248 } 249 250 //===----------------------------------------------------------------------===// 251 // AttrOrTypeParameter 252 //===----------------------------------------------------------------------===// 253 254 template <typename InitT> 255 auto AttrOrTypeParameter::getDefValue(StringRef name) const { 256 std::optional<decltype(std::declval<InitT>().getValue())> result; 257 if (const auto *param = dyn_cast<DefInit>(getDef())) 258 if (const auto *init = param->getDef()->getValue(name)) 259 if (const auto *value = dyn_cast_or_null<InitT>(init->getValue())) 260 result = value->getValue(); 261 return result; 262 } 263 264 bool AttrOrTypeParameter::isAnonymous() const { 265 return !def->getArgName(index); 266 } 267 268 StringRef AttrOrTypeParameter::getName() const { 269 return def->getArgName(index)->getValue(); 270 } 271 272 std::string AttrOrTypeParameter::getAccessorName() const { 273 return "get" + 274 llvm::convertToCamelFromSnakeCase(getName(), /*capitalizeFirst=*/true); 275 } 276 277 std::optional<StringRef> AttrOrTypeParameter::getAllocator() const { 278 return getDefValue<StringInit>("allocator"); 279 } 280 281 StringRef AttrOrTypeParameter::getComparator() const { 282 return getDefValue<StringInit>("comparator").value_or("$_lhs == $_rhs"); 283 } 284 285 StringRef AttrOrTypeParameter::getCppType() const { 286 if (auto *stringType = dyn_cast<StringInit>(getDef())) 287 return stringType->getValue(); 288 auto cppType = getDefValue<StringInit>("cppType"); 289 if (cppType) 290 return *cppType; 291 if (const auto *init = dyn_cast<DefInit>(getDef())) 292 llvm::PrintFatalError( 293 init->getDef()->getLoc(), 294 Twine("Missing `cppType` field in Attribute/Type parameter: ") + 295 init->getAsString()); 296 llvm::report_fatal_error( 297 Twine("Missing `cppType` field in Attribute/Type parameter: ") + 298 getDef()->getAsString(), 299 /*gen_crash_diag=*/false); 300 } 301 302 StringRef AttrOrTypeParameter::getCppAccessorType() const { 303 return getDefValue<StringInit>("cppAccessorType").value_or(getCppType()); 304 } 305 306 StringRef AttrOrTypeParameter::getCppStorageType() const { 307 return getDefValue<StringInit>("cppStorageType").value_or(getCppType()); 308 } 309 310 StringRef AttrOrTypeParameter::getConvertFromStorage() const { 311 return getDefValue<StringInit>("convertFromStorage").value_or("$_self"); 312 } 313 314 std::optional<StringRef> AttrOrTypeParameter::getParser() const { 315 return getDefValue<StringInit>("parser"); 316 } 317 318 std::optional<StringRef> AttrOrTypeParameter::getPrinter() const { 319 return getDefValue<StringInit>("printer"); 320 } 321 322 std::optional<StringRef> AttrOrTypeParameter::getSummary() const { 323 return getDefValue<StringInit>("summary"); 324 } 325 326 StringRef AttrOrTypeParameter::getSyntax() const { 327 if (auto *stringType = dyn_cast<StringInit>(getDef())) 328 return stringType->getValue(); 329 return getDefValue<StringInit>("syntax").value_or(getCppType()); 330 } 331 332 bool AttrOrTypeParameter::isOptional() const { 333 return getDefaultValue().has_value(); 334 } 335 336 std::optional<StringRef> AttrOrTypeParameter::getDefaultValue() const { 337 std::optional<StringRef> result = getDefValue<StringInit>("defaultValue"); 338 return result && !result->empty() ? result : std::nullopt; 339 } 340 341 const Init *AttrOrTypeParameter::getDef() const { return def->getArg(index); } 342 343 std::optional<Constraint> AttrOrTypeParameter::getConstraint() const { 344 if (const auto *param = dyn_cast<DefInit>(getDef())) 345 if (param->getDef()->isSubClassOf("Constraint")) 346 return Constraint(param->getDef()); 347 return std::nullopt; 348 } 349 350 //===----------------------------------------------------------------------===// 351 // AttributeSelfTypeParameter 352 //===----------------------------------------------------------------------===// 353 354 bool AttributeSelfTypeParameter::classof(const AttrOrTypeParameter *param) { 355 const Init *paramDef = param->getDef(); 356 if (const auto *paramDefInit = dyn_cast<DefInit>(paramDef)) 357 return paramDefInit->getDef()->isSubClassOf("AttributeSelfTypeParameter"); 358 return false; 359 } 360