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/SmallPtrSet.h" 12 #include "llvm/ADT/StringExtras.h" 13 #include "llvm/TableGen/Error.h" 14 #include "llvm/TableGen/Record.h" 15 16 using namespace mlir; 17 using namespace mlir::tblgen; 18 19 //===----------------------------------------------------------------------===// 20 // AttrOrTypeBuilder 21 //===----------------------------------------------------------------------===// 22 23 /// Returns true if this builder is able to infer the MLIRContext parameter. 24 bool AttrOrTypeBuilder::hasInferredContextParameter() const { 25 return def->getValueAsBit("hasInferredContextParam"); 26 } 27 28 //===----------------------------------------------------------------------===// 29 // AttrOrTypeDef 30 //===----------------------------------------------------------------------===// 31 32 AttrOrTypeDef::AttrOrTypeDef(const llvm::Record *def) : def(def) { 33 // Populate the builders. 34 auto *builderList = 35 dyn_cast_or_null<llvm::ListInit>(def->getValueInit("builders")); 36 if (builderList && !builderList->empty()) { 37 for (llvm::Init *init : builderList->getValues()) { 38 AttrOrTypeBuilder builder(cast<llvm::DefInit>(init)->getDef(), 39 def->getLoc()); 40 41 // Ensure that all parameters have names. 42 for (const AttrOrTypeBuilder::Parameter ¶m : 43 builder.getParameters()) { 44 if (!param.getName()) 45 PrintFatalError(def->getLoc(), "builder parameters must have a name"); 46 } 47 builders.emplace_back(builder); 48 } 49 } 50 51 // Populate the traits. 52 if (auto *traitList = def->getValueAsListInit("traits")) { 53 SmallPtrSet<const llvm::Init *, 32> traitSet; 54 traits.reserve(traitSet.size()); 55 for (auto *traitInit : *traitList) 56 if (traitSet.insert(traitInit).second) 57 traits.push_back(Trait::create(traitInit)); 58 } 59 60 // Populate the parameters. 61 if (auto *parametersDag = def->getValueAsDag("parameters")) { 62 for (unsigned i = 0, e = parametersDag->getNumArgs(); i < e; ++i) 63 parameters.push_back(AttrOrTypeParameter(parametersDag, i)); 64 } 65 66 // Verify the use of the mnemonic field. 67 bool hasCppFormat = hasCustomAssemblyFormat(); 68 bool hasDeclarativeFormat = getAssemblyFormat().has_value(); 69 if (getMnemonic()) { 70 if (hasCppFormat && hasDeclarativeFormat) { 71 PrintFatalError(getLoc(), "cannot specify both 'assemblyFormat' " 72 "and 'hasCustomAssemblyFormat'"); 73 } 74 if (!parameters.empty() && !hasCppFormat && !hasDeclarativeFormat) { 75 PrintFatalError(getLoc(), 76 "must specify either 'assemblyFormat' or " 77 "'hasCustomAssemblyFormat' when 'mnemonic' is set"); 78 } 79 } else if (hasCppFormat || hasDeclarativeFormat) { 80 PrintFatalError(getLoc(), 81 "'assemblyFormat' or 'hasCustomAssemblyFormat' can only be " 82 "used when 'mnemonic' is set"); 83 } 84 // Assembly format parser requires default builders to be generated. 85 if (hasDeclarativeFormat && skipDefaultBuilders()) { 86 PrintFatalError( 87 getLoc(), 88 "'assemblyFormat' requires 'skipDefaultBuilders' to be false"); 89 } 90 // Assembly format printer requires accessors to be generated. 91 if (hasDeclarativeFormat && !genAccessors()) { 92 PrintFatalError(getLoc(), 93 "'assemblyFormat' requires 'genAccessors' to be true"); 94 } 95 } 96 97 Dialect AttrOrTypeDef::getDialect() const { 98 auto *dialect = dyn_cast<llvm::DefInit>(def->getValue("dialect")->getValue()); 99 return Dialect(dialect ? dialect->getDef() : nullptr); 100 } 101 102 StringRef AttrOrTypeDef::getName() const { return def->getName(); } 103 104 StringRef AttrOrTypeDef::getCppClassName() const { 105 return def->getValueAsString("cppClassName"); 106 } 107 108 StringRef AttrOrTypeDef::getCppBaseClassName() const { 109 return def->getValueAsString("cppBaseClassName"); 110 } 111 112 bool AttrOrTypeDef::hasDescription() const { 113 const llvm::RecordVal *desc = def->getValue("description"); 114 return desc && isa<llvm::StringInit>(desc->getValue()); 115 } 116 117 StringRef AttrOrTypeDef::getDescription() const { 118 return def->getValueAsString("description"); 119 } 120 121 bool AttrOrTypeDef::hasSummary() const { 122 const llvm::RecordVal *summary = def->getValue("summary"); 123 return summary && isa<llvm::StringInit>(summary->getValue()); 124 } 125 126 StringRef AttrOrTypeDef::getSummary() const { 127 return def->getValueAsString("summary"); 128 } 129 130 StringRef AttrOrTypeDef::getStorageClassName() const { 131 return def->getValueAsString("storageClass"); 132 } 133 134 StringRef AttrOrTypeDef::getStorageNamespace() const { 135 return def->getValueAsString("storageNamespace"); 136 } 137 138 bool AttrOrTypeDef::genStorageClass() const { 139 return def->getValueAsBit("genStorageClass"); 140 } 141 142 bool AttrOrTypeDef::hasStorageCustomConstructor() const { 143 return def->getValueAsBit("hasStorageCustomConstructor"); 144 } 145 146 unsigned AttrOrTypeDef::getNumParameters() const { 147 auto *parametersDag = def->getValueAsDag("parameters"); 148 return parametersDag ? parametersDag->getNumArgs() : 0; 149 } 150 151 Optional<StringRef> AttrOrTypeDef::getMnemonic() const { 152 return def->getValueAsOptionalString("mnemonic"); 153 } 154 155 bool AttrOrTypeDef::hasCustomAssemblyFormat() const { 156 return def->getValueAsBit("hasCustomAssemblyFormat"); 157 } 158 159 Optional<StringRef> AttrOrTypeDef::getAssemblyFormat() const { 160 return def->getValueAsOptionalString("assemblyFormat"); 161 } 162 163 bool AttrOrTypeDef::genAccessors() const { 164 return def->getValueAsBit("genAccessors"); 165 } 166 167 bool AttrOrTypeDef::genVerifyDecl() const { 168 return def->getValueAsBit("genVerifyDecl"); 169 } 170 171 Optional<StringRef> AttrOrTypeDef::getExtraDecls() const { 172 auto value = def->getValueAsString("extraClassDeclaration"); 173 return value.empty() ? Optional<StringRef>() : value; 174 } 175 176 ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); } 177 178 bool AttrOrTypeDef::skipDefaultBuilders() const { 179 return def->getValueAsBit("skipDefaultBuilders"); 180 } 181 182 bool AttrOrTypeDef::operator==(const AttrOrTypeDef &other) const { 183 return def == other.def; 184 } 185 186 bool AttrOrTypeDef::operator<(const AttrOrTypeDef &other) const { 187 return getName() < other.getName(); 188 } 189 190 //===----------------------------------------------------------------------===// 191 // AttrDef 192 //===----------------------------------------------------------------------===// 193 194 Optional<StringRef> AttrDef::getTypeBuilder() const { 195 return def->getValueAsOptionalString("typeBuilder"); 196 } 197 198 bool AttrDef::classof(const AttrOrTypeDef *def) { 199 return def->getDef()->isSubClassOf("AttrDef"); 200 } 201 202 //===----------------------------------------------------------------------===// 203 // AttrOrTypeParameter 204 //===----------------------------------------------------------------------===// 205 206 template <typename InitT> 207 auto AttrOrTypeParameter::getDefValue(StringRef name) const { 208 Optional<decltype(std::declval<InitT>().getValue())> result; 209 if (auto *param = dyn_cast<llvm::DefInit>(getDef())) 210 if (auto *init = param->getDef()->getValue(name)) 211 if (auto *value = dyn_cast_or_null<InitT>(init->getValue())) 212 result = value->getValue(); 213 return result; 214 } 215 216 bool AttrOrTypeParameter::isAnonymous() const { 217 return !def->getArgName(index); 218 } 219 220 StringRef AttrOrTypeParameter::getName() const { 221 return def->getArgName(index)->getValue(); 222 } 223 224 std::string AttrOrTypeParameter::getAccessorName() const { 225 return "get" + 226 llvm::convertToCamelFromSnakeCase(getName(), /*capitalizeFirst=*/true); 227 } 228 229 Optional<StringRef> AttrOrTypeParameter::getAllocator() const { 230 return getDefValue<llvm::StringInit>("allocator"); 231 } 232 233 StringRef AttrOrTypeParameter::getComparator() const { 234 return getDefValue<llvm::StringInit>("comparator").value_or("$_lhs == $_rhs"); 235 } 236 237 StringRef AttrOrTypeParameter::getCppType() const { 238 if (auto *stringType = dyn_cast<llvm::StringInit>(getDef())) 239 return stringType->getValue(); 240 return getDefValue<llvm::StringInit>("cppType").getValue(); 241 } 242 243 StringRef AttrOrTypeParameter::getCppAccessorType() const { 244 return getDefValue<llvm::StringInit>("cppAccessorType") 245 .value_or(getCppType()); 246 } 247 248 StringRef AttrOrTypeParameter::getCppStorageType() const { 249 return getDefValue<llvm::StringInit>("cppStorageType").value_or(getCppType()); 250 } 251 252 StringRef AttrOrTypeParameter::getConvertFromStorage() const { 253 return getDefValue<llvm::StringInit>("convertFromStorage").value_or("$_self"); 254 } 255 256 Optional<StringRef> AttrOrTypeParameter::getParser() const { 257 return getDefValue<llvm::StringInit>("parser"); 258 } 259 260 Optional<StringRef> AttrOrTypeParameter::getPrinter() const { 261 return getDefValue<llvm::StringInit>("printer"); 262 } 263 264 Optional<StringRef> AttrOrTypeParameter::getSummary() const { 265 return getDefValue<llvm::StringInit>("summary"); 266 } 267 268 StringRef AttrOrTypeParameter::getSyntax() const { 269 if (auto *stringType = dyn_cast<llvm::StringInit>(getDef())) 270 return stringType->getValue(); 271 return getDefValue<llvm::StringInit>("syntax").value_or(getCppType()); 272 } 273 274 bool AttrOrTypeParameter::isOptional() const { 275 // Parameters with default values are automatically optional. 276 return getDefValue<llvm::BitInit>("isOptional").value_or(false) || 277 getDefaultValue(); 278 } 279 280 Optional<StringRef> AttrOrTypeParameter::getDefaultValue() const { 281 return getDefValue<llvm::StringInit>("defaultValue"); 282 } 283 284 llvm::Init *AttrOrTypeParameter::getDef() const { return def->getArg(index); } 285 286 //===----------------------------------------------------------------------===// 287 // AttributeSelfTypeParameter 288 //===----------------------------------------------------------------------===// 289 290 bool AttributeSelfTypeParameter::classof(const AttrOrTypeParameter *param) { 291 llvm::Init *paramDef = param->getDef(); 292 if (auto *paramDefInit = dyn_cast<llvm::DefInit>(paramDef)) 293 return paramDefInit->getDef()->isSubClassOf("AttributeSelfTypeParameter"); 294 return false; 295 } 296