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 Optional<StringRef> AttrOrTypeBuilder::getReturnType() const { 24 Optional<StringRef> type = def->getValueAsOptionalString("returnType"); 25 return type && !type->empty() ? type : llvm::None; 26 } 27 28 bool AttrOrTypeBuilder::hasInferredContextParameter() const { 29 return def->getValueAsBit("hasInferredContextParam"); 30 } 31 32 //===----------------------------------------------------------------------===// 33 // AttrOrTypeDef 34 //===----------------------------------------------------------------------===// 35 36 AttrOrTypeDef::AttrOrTypeDef(const llvm::Record *def) : def(def) { 37 // Populate the builders. 38 auto *builderList = 39 dyn_cast_or_null<llvm::ListInit>(def->getValueInit("builders")); 40 if (builderList && !builderList->empty()) { 41 for (llvm::Init *init : builderList->getValues()) { 42 AttrOrTypeBuilder builder(cast<llvm::DefInit>(init)->getDef(), 43 def->getLoc()); 44 45 // Ensure that all parameters have names. 46 for (const AttrOrTypeBuilder::Parameter ¶m : 47 builder.getParameters()) { 48 if (!param.getName()) 49 PrintFatalError(def->getLoc(), "builder parameters must have a name"); 50 } 51 builders.emplace_back(builder); 52 } 53 } 54 55 // Populate the traits. 56 if (auto *traitList = def->getValueAsListInit("traits")) { 57 SmallPtrSet<const llvm::Init *, 32> traitSet; 58 traits.reserve(traitSet.size()); 59 for (auto *traitInit : *traitList) 60 if (traitSet.insert(traitInit).second) 61 traits.push_back(Trait::create(traitInit)); 62 } 63 64 // Populate the parameters. 65 if (auto *parametersDag = def->getValueAsDag("parameters")) { 66 for (unsigned i = 0, e = parametersDag->getNumArgs(); i < e; ++i) 67 parameters.push_back(AttrOrTypeParameter(parametersDag, i)); 68 } 69 70 // Verify the use of the mnemonic field. 71 bool hasCppFormat = hasCustomAssemblyFormat(); 72 bool hasDeclarativeFormat = getAssemblyFormat().has_value(); 73 if (getMnemonic()) { 74 if (hasCppFormat && hasDeclarativeFormat) { 75 PrintFatalError(getLoc(), "cannot specify both 'assemblyFormat' " 76 "and 'hasCustomAssemblyFormat'"); 77 } 78 if (!parameters.empty() && !hasCppFormat && !hasDeclarativeFormat) { 79 PrintFatalError(getLoc(), 80 "must specify either 'assemblyFormat' or " 81 "'hasCustomAssemblyFormat' when 'mnemonic' is set"); 82 } 83 } else if (hasCppFormat || hasDeclarativeFormat) { 84 PrintFatalError(getLoc(), 85 "'assemblyFormat' or 'hasCustomAssemblyFormat' can only be " 86 "used when 'mnemonic' is set"); 87 } 88 // Assembly format printer requires accessors to be generated. 89 if (hasDeclarativeFormat && !genAccessors()) { 90 PrintFatalError(getLoc(), 91 "'assemblyFormat' requires 'genAccessors' to be true"); 92 } 93 // TODO: Ensure that a suitable builder prototype can be generated: 94 // https://llvm.org/PR56415 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 Optional<StringRef> AttrOrTypeDef::getExtraDefs() const { 177 auto value = def->getValueAsString("extraClassDefinition"); 178 return value.empty() ? Optional<StringRef>() : value; 179 } 180 181 ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); } 182 183 bool AttrOrTypeDef::skipDefaultBuilders() const { 184 return def->getValueAsBit("skipDefaultBuilders"); 185 } 186 187 bool AttrOrTypeDef::operator==(const AttrOrTypeDef &other) const { 188 return def == other.def; 189 } 190 191 bool AttrOrTypeDef::operator<(const AttrOrTypeDef &other) const { 192 return getName() < other.getName(); 193 } 194 195 //===----------------------------------------------------------------------===// 196 // AttrDef 197 //===----------------------------------------------------------------------===// 198 199 Optional<StringRef> AttrDef::getTypeBuilder() const { 200 return def->getValueAsOptionalString("typeBuilder"); 201 } 202 203 bool AttrDef::classof(const AttrOrTypeDef *def) { 204 return def->getDef()->isSubClassOf("AttrDef"); 205 } 206 207 //===----------------------------------------------------------------------===// 208 // AttrOrTypeParameter 209 //===----------------------------------------------------------------------===// 210 211 template <typename InitT> 212 auto AttrOrTypeParameter::getDefValue(StringRef name) const { 213 Optional<decltype(std::declval<InitT>().getValue())> result; 214 if (auto *param = dyn_cast<llvm::DefInit>(getDef())) 215 if (auto *init = param->getDef()->getValue(name)) 216 if (auto *value = dyn_cast_or_null<InitT>(init->getValue())) 217 result = value->getValue(); 218 return result; 219 } 220 221 bool AttrOrTypeParameter::isAnonymous() const { 222 return !def->getArgName(index); 223 } 224 225 StringRef AttrOrTypeParameter::getName() const { 226 return def->getArgName(index)->getValue(); 227 } 228 229 std::string AttrOrTypeParameter::getAccessorName() const { 230 return "get" + 231 llvm::convertToCamelFromSnakeCase(getName(), /*capitalizeFirst=*/true); 232 } 233 234 Optional<StringRef> AttrOrTypeParameter::getAllocator() const { 235 return getDefValue<llvm::StringInit>("allocator"); 236 } 237 238 StringRef AttrOrTypeParameter::getComparator() const { 239 return getDefValue<llvm::StringInit>("comparator").value_or("$_lhs == $_rhs"); 240 } 241 242 StringRef AttrOrTypeParameter::getCppType() const { 243 if (auto *stringType = dyn_cast<llvm::StringInit>(getDef())) 244 return stringType->getValue(); 245 return getDefValue<llvm::StringInit>("cppType").value(); 246 } 247 248 StringRef AttrOrTypeParameter::getCppAccessorType() const { 249 return getDefValue<llvm::StringInit>("cppAccessorType") 250 .value_or(getCppType()); 251 } 252 253 StringRef AttrOrTypeParameter::getCppStorageType() const { 254 return getDefValue<llvm::StringInit>("cppStorageType").value_or(getCppType()); 255 } 256 257 StringRef AttrOrTypeParameter::getConvertFromStorage() const { 258 return getDefValue<llvm::StringInit>("convertFromStorage").value_or("$_self"); 259 } 260 261 Optional<StringRef> AttrOrTypeParameter::getParser() const { 262 return getDefValue<llvm::StringInit>("parser"); 263 } 264 265 Optional<StringRef> AttrOrTypeParameter::getPrinter() const { 266 return getDefValue<llvm::StringInit>("printer"); 267 } 268 269 Optional<StringRef> AttrOrTypeParameter::getSummary() const { 270 return getDefValue<llvm::StringInit>("summary"); 271 } 272 273 StringRef AttrOrTypeParameter::getSyntax() const { 274 if (auto *stringType = dyn_cast<llvm::StringInit>(getDef())) 275 return stringType->getValue(); 276 return getDefValue<llvm::StringInit>("syntax").value_or(getCppType()); 277 } 278 279 bool AttrOrTypeParameter::isOptional() const { 280 // Parameters with default values are automatically optional. 281 return getDefValue<llvm::BitInit>("isOptional").value_or(false) || 282 getDefaultValue(); 283 } 284 285 Optional<StringRef> AttrOrTypeParameter::getDefaultValue() const { 286 return getDefValue<llvm::StringInit>("defaultValue"); 287 } 288 289 llvm::Init *AttrOrTypeParameter::getDef() const { return def->getArg(index); } 290 291 //===----------------------------------------------------------------------===// 292 // AttributeSelfTypeParameter 293 //===----------------------------------------------------------------------===// 294 295 bool AttributeSelfTypeParameter::classof(const AttrOrTypeParameter *param) { 296 llvm::Init *paramDef = param->getDef(); 297 if (auto *paramDefInit = dyn_cast<llvm::DefInit>(paramDef)) 298 return paramDefInit->getDef()->isSubClassOf("AttributeSelfTypeParameter"); 299 return false; 300 } 301