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 parser requires builders with the same prototype 89 // as the default-builders. 90 // TODO: attempt to detect when a custom builder matches the prototype. 91 if (hasDeclarativeFormat && skipDefaultBuilders()) { 92 PrintWarning(getLoc(), 93 "using 'assemblyFormat' with 'skipDefaultBuilders=1' may " 94 "result in C++ compilation errors"); 95 } 96 // Assembly format printer requires accessors to be generated. 97 if (hasDeclarativeFormat && !genAccessors()) { 98 PrintFatalError(getLoc(), 99 "'assemblyFormat' requires 'genAccessors' to be true"); 100 } 101 } 102 103 Dialect AttrOrTypeDef::getDialect() const { 104 auto *dialect = dyn_cast<llvm::DefInit>(def->getValue("dialect")->getValue()); 105 return Dialect(dialect ? dialect->getDef() : nullptr); 106 } 107 108 StringRef AttrOrTypeDef::getName() const { return def->getName(); } 109 110 StringRef AttrOrTypeDef::getCppClassName() const { 111 return def->getValueAsString("cppClassName"); 112 } 113 114 StringRef AttrOrTypeDef::getCppBaseClassName() const { 115 return def->getValueAsString("cppBaseClassName"); 116 } 117 118 bool AttrOrTypeDef::hasDescription() const { 119 const llvm::RecordVal *desc = def->getValue("description"); 120 return desc && isa<llvm::StringInit>(desc->getValue()); 121 } 122 123 StringRef AttrOrTypeDef::getDescription() const { 124 return def->getValueAsString("description"); 125 } 126 127 bool AttrOrTypeDef::hasSummary() const { 128 const llvm::RecordVal *summary = def->getValue("summary"); 129 return summary && isa<llvm::StringInit>(summary->getValue()); 130 } 131 132 StringRef AttrOrTypeDef::getSummary() const { 133 return def->getValueAsString("summary"); 134 } 135 136 StringRef AttrOrTypeDef::getStorageClassName() const { 137 return def->getValueAsString("storageClass"); 138 } 139 140 StringRef AttrOrTypeDef::getStorageNamespace() const { 141 return def->getValueAsString("storageNamespace"); 142 } 143 144 bool AttrOrTypeDef::genStorageClass() const { 145 return def->getValueAsBit("genStorageClass"); 146 } 147 148 bool AttrOrTypeDef::hasStorageCustomConstructor() const { 149 return def->getValueAsBit("hasStorageCustomConstructor"); 150 } 151 152 unsigned AttrOrTypeDef::getNumParameters() const { 153 auto *parametersDag = def->getValueAsDag("parameters"); 154 return parametersDag ? parametersDag->getNumArgs() : 0; 155 } 156 157 Optional<StringRef> AttrOrTypeDef::getMnemonic() const { 158 return def->getValueAsOptionalString("mnemonic"); 159 } 160 161 bool AttrOrTypeDef::hasCustomAssemblyFormat() const { 162 return def->getValueAsBit("hasCustomAssemblyFormat"); 163 } 164 165 Optional<StringRef> AttrOrTypeDef::getAssemblyFormat() const { 166 return def->getValueAsOptionalString("assemblyFormat"); 167 } 168 169 bool AttrOrTypeDef::genAccessors() const { 170 return def->getValueAsBit("genAccessors"); 171 } 172 173 bool AttrOrTypeDef::genVerifyDecl() const { 174 return def->getValueAsBit("genVerifyDecl"); 175 } 176 177 Optional<StringRef> AttrOrTypeDef::getExtraDecls() const { 178 auto value = def->getValueAsString("extraClassDeclaration"); 179 return value.empty() ? Optional<StringRef>() : value; 180 } 181 182 Optional<StringRef> AttrOrTypeDef::getExtraDefs() const { 183 auto value = def->getValueAsString("extraClassDefinition"); 184 return value.empty() ? Optional<StringRef>() : value; 185 } 186 187 ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); } 188 189 bool AttrOrTypeDef::skipDefaultBuilders() const { 190 return def->getValueAsBit("skipDefaultBuilders"); 191 } 192 193 bool AttrOrTypeDef::operator==(const AttrOrTypeDef &other) const { 194 return def == other.def; 195 } 196 197 bool AttrOrTypeDef::operator<(const AttrOrTypeDef &other) const { 198 return getName() < other.getName(); 199 } 200 201 //===----------------------------------------------------------------------===// 202 // AttrDef 203 //===----------------------------------------------------------------------===// 204 205 Optional<StringRef> AttrDef::getTypeBuilder() const { 206 return def->getValueAsOptionalString("typeBuilder"); 207 } 208 209 bool AttrDef::classof(const AttrOrTypeDef *def) { 210 return def->getDef()->isSubClassOf("AttrDef"); 211 } 212 213 //===----------------------------------------------------------------------===// 214 // AttrOrTypeParameter 215 //===----------------------------------------------------------------------===// 216 217 template <typename InitT> 218 auto AttrOrTypeParameter::getDefValue(StringRef name) const { 219 Optional<decltype(std::declval<InitT>().getValue())> result; 220 if (auto *param = dyn_cast<llvm::DefInit>(getDef())) 221 if (auto *init = param->getDef()->getValue(name)) 222 if (auto *value = dyn_cast_or_null<InitT>(init->getValue())) 223 result = value->getValue(); 224 return result; 225 } 226 227 bool AttrOrTypeParameter::isAnonymous() const { 228 return !def->getArgName(index); 229 } 230 231 StringRef AttrOrTypeParameter::getName() const { 232 return def->getArgName(index)->getValue(); 233 } 234 235 std::string AttrOrTypeParameter::getAccessorName() const { 236 return "get" + 237 llvm::convertToCamelFromSnakeCase(getName(), /*capitalizeFirst=*/true); 238 } 239 240 Optional<StringRef> AttrOrTypeParameter::getAllocator() const { 241 return getDefValue<llvm::StringInit>("allocator"); 242 } 243 244 StringRef AttrOrTypeParameter::getComparator() const { 245 return getDefValue<llvm::StringInit>("comparator").value_or("$_lhs == $_rhs"); 246 } 247 248 StringRef AttrOrTypeParameter::getCppType() const { 249 if (auto *stringType = dyn_cast<llvm::StringInit>(getDef())) 250 return stringType->getValue(); 251 return getDefValue<llvm::StringInit>("cppType").value(); 252 } 253 254 StringRef AttrOrTypeParameter::getCppAccessorType() const { 255 return getDefValue<llvm::StringInit>("cppAccessorType") 256 .value_or(getCppType()); 257 } 258 259 StringRef AttrOrTypeParameter::getCppStorageType() const { 260 return getDefValue<llvm::StringInit>("cppStorageType").value_or(getCppType()); 261 } 262 263 StringRef AttrOrTypeParameter::getConvertFromStorage() const { 264 return getDefValue<llvm::StringInit>("convertFromStorage").value_or("$_self"); 265 } 266 267 Optional<StringRef> AttrOrTypeParameter::getParser() const { 268 return getDefValue<llvm::StringInit>("parser"); 269 } 270 271 Optional<StringRef> AttrOrTypeParameter::getPrinter() const { 272 return getDefValue<llvm::StringInit>("printer"); 273 } 274 275 Optional<StringRef> AttrOrTypeParameter::getSummary() const { 276 return getDefValue<llvm::StringInit>("summary"); 277 } 278 279 StringRef AttrOrTypeParameter::getSyntax() const { 280 if (auto *stringType = dyn_cast<llvm::StringInit>(getDef())) 281 return stringType->getValue(); 282 return getDefValue<llvm::StringInit>("syntax").value_or(getCppType()); 283 } 284 285 bool AttrOrTypeParameter::isOptional() const { 286 // Parameters with default values are automatically optional. 287 return getDefValue<llvm::BitInit>("isOptional").value_or(false) || 288 getDefaultValue(); 289 } 290 291 Optional<StringRef> AttrOrTypeParameter::getDefaultValue() const { 292 return getDefValue<llvm::StringInit>("defaultValue"); 293 } 294 295 llvm::Init *AttrOrTypeParameter::getDef() const { return def->getArg(index); } 296 297 //===----------------------------------------------------------------------===// 298 // AttributeSelfTypeParameter 299 //===----------------------------------------------------------------------===// 300 301 bool AttributeSelfTypeParameter::classof(const AttrOrTypeParameter *param) { 302 llvm::Init *paramDef = param->getDef(); 303 if (auto *paramDefInit = dyn_cast<llvm::DefInit>(paramDef)) 304 return paramDefInit->getDef()->isSubClassOf("AttributeSelfTypeParameter"); 305 return false; 306 } 307