682 lines · cpp
1//===- DLTI.cpp - Data Layout And Target Info MLIR Dialect Implementation -===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/Dialect/DLTI/DLTI.h"10#include "mlir/IR/Builders.h"11#include "mlir/IR/BuiltinAttributes.h"12#include "mlir/IR/BuiltinDialect.h"13#include "mlir/IR/BuiltinOps.h"14#include "mlir/IR/BuiltinTypes.h"15#include "mlir/IR/Dialect.h"16#include "mlir/IR/DialectImplementation.h"17 18#include "llvm/ADT/MapVector.h"19#include "llvm/ADT/TypeSwitch.h"20 21using namespace mlir;22 23#include "mlir/Dialect/DLTI/DLTIDialect.cpp.inc"24 25#define GET_ATTRDEF_CLASSES26#include "mlir/Dialect/DLTI/DLTIAttrs.cpp.inc"27 28#define DEBUG_TYPE "dlti"29 30//===----------------------------------------------------------------------===//31// Common parsing utility functions.32//===----------------------------------------------------------------------===//33 34/// Parse an entry which can either be of the form `key = value` or a35/// #dlti.dl_entry attribute. When `tryType=true` the key can be a type,36/// otherwise only quoted strings are allowed. The grammar is as follows:37/// entry ::= ((type | quoted-string) `=` attr) | dl-entry-attr38static ParseResult parseKeyValuePair(AsmParser &parser,39 DataLayoutEntryInterface &entry,40 bool tryType = false) {41 Attribute value;42 43 if (tryType) {44 Type type;45 OptionalParseResult parsedType = parser.parseOptionalType(type);46 if (parsedType.has_value()) {47 if (failed(parsedType.value()))48 return parser.emitError(parser.getCurrentLocation())49 << "error while parsing type DLTI key";50 51 if (failed(parser.parseEqual()) || failed(parser.parseAttribute(value)))52 return failure();53 54 entry = DataLayoutEntryAttr::get(type, value);55 return ParseResult::success();56 }57 }58 59 std::string ident;60 OptionalParseResult parsedStr = parser.parseOptionalString(&ident);61 if (parsedStr.has_value() && succeeded(parsedStr.value())) {62 if (failed(parser.parseEqual()) || failed(parser.parseAttribute(value)))63 return failure(); // Assume that an error has already been emitted.64 65 entry = DataLayoutEntryAttr::get(66 StringAttr::get(parser.getContext(), ident), value);67 return ParseResult::success();68 }69 70 OptionalParseResult parsedEntry = parser.parseAttribute(entry);71 if (parsedEntry.has_value()) {72 if (succeeded(parsedEntry.value()))73 return parsedEntry.value();74 return failure(); // Assume that an error has already been emitted.75 }76 return parser.emitError(parser.getCurrentLocation())77 << "failed to parse DLTI entry";78}79 80/// Construct a requested attribute by parsing list of entries occurring within81/// a pair of `<` and `>`, optionally allow types as keys and an empty list.82/// The grammar is as follows:83/// bracketed-entry-list ::=`<` entry-list `>`84/// entry-list ::= | entry | entry `,` entry-list85/// entry ::= ((type | quoted-string) `=` attr) | dl-entry-attr86template <class Attr>87static Attribute parseAngleBracketedEntries(AsmParser &parser, Type ty,88 bool tryType = false,89 bool allowEmpty = false) {90 SmallVector<DataLayoutEntryInterface> entries;91 if (failed(parser.parseCommaSeparatedList(92 AsmParser::Delimiter::LessGreater, [&]() {93 return parseKeyValuePair(parser, entries.emplace_back(), tryType);94 })))95 return {};96 97 if (entries.empty() && !allowEmpty) {98 parser.emitError(parser.getNameLoc()) << "no DLTI entries provided";99 return {};100 }101 102 return Attr::getChecked([&] { return parser.emitError(parser.getNameLoc()); },103 parser.getContext(), ArrayRef(entries));104}105 106//===----------------------------------------------------------------------===//107// Common printing utility functions.108//===----------------------------------------------------------------------===//109 110/// Convert pointer-union keys to strings.111static std::string keyToStr(DataLayoutEntryKey key) {112 std::string buf;113 TypeSwitch<DataLayoutEntryKey>(key)114 .Case<StringAttr, Type>( // The only two kinds of key we know of.115 [&](auto key) { llvm::raw_string_ostream(buf) << key; });116 return buf;117}118 119/// Pretty-print entries, each in `key = value` format, separated by commas.120template <class T>121static void printAngleBracketedEntries(AsmPrinter &os, T &&entries) {122 os << "<";123 llvm::interleaveComma(std::forward<T>(entries), os, [&](auto entry) {124 os << keyToStr(entry.getKey()) << " = " << entry.getValue();125 });126 os << ">";127}128 129//===----------------------------------------------------------------------===//130// Common verifying utility functions.131//===----------------------------------------------------------------------===//132 133/// Verify entries, with the option to disallow types as keys.134static LogicalResult verifyEntries(function_ref<InFlightDiagnostic()> emitError,135 ArrayRef<DataLayoutEntryInterface> entries,136 bool allowTypes = true) {137 DenseSet<DataLayoutEntryKey> keys;138 for (DataLayoutEntryInterface entry : entries) {139 if (!entry)140 return emitError() << "contained invalid DLTI entry";141 DataLayoutEntryKey key = entry.getKey();142 if (key.isNull())143 return emitError() << "contained invalid DLTI key";144 if (!allowTypes && dyn_cast<Type>(key))145 return emitError() << "type as DLTI key is not allowed";146 if (auto strKey = dyn_cast<StringAttr>(key))147 if (strKey.getValue().empty())148 return emitError() << "empty string as DLTI key is not allowed";149 if (!keys.insert(key).second)150 return emitError() << "repeated DLTI key: " << keyToStr(key);151 if (!entry.getValue())152 return emitError() << "value associated to DLTI key " << keyToStr(key)153 << " is invalid";154 }155 return success();156}157 158//===----------------------------------------------------------------------===//159// DataLayoutEntryAttr160//===----------------------------------------------------------------------===//161namespace mlir {162namespace detail {163class DataLayoutEntryAttrStorage : public AttributeStorage {164public:165 using KeyTy = std::pair<DataLayoutEntryKey, Attribute>;166 167 DataLayoutEntryAttrStorage(DataLayoutEntryKey entryKey, Attribute value)168 : entryKey(entryKey), value(value) {}169 170 static DataLayoutEntryAttrStorage *171 construct(AttributeStorageAllocator &allocator, const KeyTy &key) {172 return new (allocator.allocate<DataLayoutEntryAttrStorage>())173 DataLayoutEntryAttrStorage(key.first, key.second);174 }175 176 bool operator==(const KeyTy &other) const {177 return other.first == entryKey && other.second == value;178 }179 180 DataLayoutEntryKey entryKey;181 Attribute value;182};183} // namespace detail184} // namespace mlir185 186DataLayoutEntryAttr DataLayoutEntryAttr::get(StringAttr key, Attribute value) {187 return Base::get(key.getContext(), key, value);188}189 190DataLayoutEntryAttr DataLayoutEntryAttr::get(Type key, Attribute value) {191 return Base::get(key.getContext(), key, value);192}193 194DataLayoutEntryKey DataLayoutEntryAttr::getKey() const {195 return getImpl()->entryKey;196}197 198Attribute DataLayoutEntryAttr::getValue() const { return getImpl()->value; }199 200/// Parses an attribute with syntax:201/// dl-entry-attr ::= `#dlti.` `dl_entry` `<` (type | quoted-string) `,`202/// attr `>`203Attribute DataLayoutEntryAttr::parse(AsmParser &parser, Type type) {204 if (failed(parser.parseLess()))205 return {};206 207 Type typeKey = nullptr;208 std::string identifier;209 SMLoc idLoc = parser.getCurrentLocation();210 OptionalParseResult parsedType = parser.parseOptionalType(typeKey);211 if (parsedType.has_value() && failed(parsedType.value()))212 return {};213 if (!parsedType.has_value()) {214 OptionalParseResult parsedString = parser.parseOptionalString(&identifier);215 if (!parsedString.has_value() || failed(parsedString.value())) {216 parser.emitError(idLoc) << "expected a type or a quoted string";217 return {};218 }219 }220 221 Attribute value;222 if (failed(parser.parseComma()) || failed(parser.parseAttribute(value)) ||223 failed(parser.parseGreater()))224 return {};225 226 return typeKey ? get(typeKey, value)227 : get(parser.getBuilder().getStringAttr(identifier), value);228}229 230void DataLayoutEntryAttr::print(AsmPrinter &printer) const {231 printer << "<" << keyToStr(getKey()) << ", " << getValue() << ">";232}233 234//===----------------------------------------------------------------------===//235// DLTIMapAttr236//===----------------------------------------------------------------------===//237 238/// Parses an attribute with syntax:239/// map-attr ::= `#dlti.` `map` `<` entry-list `>`240/// entry-list ::= entry | entry `,` entry-list241/// entry ::= ((type | quoted-string) `=` attr) | dl-entry-attr242Attribute MapAttr::parse(AsmParser &parser, Type type) {243 return parseAngleBracketedEntries<MapAttr>(parser, type, /*tryType=*/true,244 /*allowEmpty=*/true);245}246 247void MapAttr::print(AsmPrinter &printer) const {248 printAngleBracketedEntries(printer, getEntries());249}250 251LogicalResult MapAttr::verify(function_ref<InFlightDiagnostic()> emitError,252 ArrayRef<DataLayoutEntryInterface> entries) {253 return verifyEntries(emitError, entries);254}255 256//===----------------------------------------------------------------------===//257// DataLayoutSpecAttr258//===----------------------------------------------------------------------===//259 260LogicalResult261DataLayoutSpecAttr::verify(function_ref<InFlightDiagnostic()> emitError,262 ArrayRef<DataLayoutEntryInterface> entries) {263 return verifyEntries(emitError, entries);264}265 266/// Given a list of old and a list of new entries, overwrites old entries with267/// new ones if they have matching keys, appends new entries to the old entry268/// list otherwise.269static void270overwriteDuplicateEntries(SmallVectorImpl<DataLayoutEntryInterface> &oldEntries,271 ArrayRef<DataLayoutEntryInterface> newEntries) {272 unsigned oldEntriesSize = oldEntries.size();273 for (DataLayoutEntryInterface entry : newEntries) {274 // We expect a small (dozens) number of entries, so it is practically275 // cheaper to iterate over the list linearly rather than to create an276 // auxiliary hashmap to avoid duplication. Also note that we never need to277 // check for duplicate keys the values that were added from `newEntries`.278 bool replaced = false;279 for (unsigned i = 0; i < oldEntriesSize; ++i) {280 if (oldEntries[i].getKey() == entry.getKey()) {281 oldEntries[i] = entry;282 replaced = true;283 break;284 }285 }286 if (!replaced)287 oldEntries.push_back(entry);288 }289}290 291/// Combines a data layout spec into the given lists of entries organized by292/// type class and identifier, overwriting them if necessary. Fails to combine293/// if the two entries with identical keys are not compatible.294static LogicalResult combineOneSpec(295 DataLayoutSpecInterface spec,296 llvm::MapVector<TypeID, DataLayoutEntryList> &entriesForType,297 llvm::MapVector<StringAttr, DataLayoutEntryInterface> &entriesForID) {298 // A missing spec should be fine.299 if (!spec)300 return success();301 302 llvm::MapVector<TypeID, DataLayoutEntryList> newEntriesForType;303 llvm::MapVector<StringAttr, DataLayoutEntryInterface> newEntriesForID;304 spec.bucketEntriesByType(newEntriesForType, newEntriesForID);305 306 // Combine non-Type DL entries first so they are visible to the307 // `type.areCompatible` method, allowing to query global properties.308 for (const auto &kvp : newEntriesForID) {309 StringAttr id = cast<StringAttr>(kvp.second.getKey());310 Dialect *dialect = id.getReferencedDialect();311 if (!entriesForID.count(id)) {312 entriesForID[id] = kvp.second;313 continue;314 }315 316 // Attempt to combine the entries using the dialect interface. If the317 // dialect is not loaded for some reason, use the default combinator318 // that conservatively accepts identical entries only.319 entriesForID[id] =320 dialect ? cast<DataLayoutDialectInterface>(dialect)->combine(321 entriesForID[id], kvp.second)322 : DataLayoutDialectInterface::defaultCombine(entriesForID[id],323 kvp.second);324 if (!entriesForID[id])325 return failure();326 }327 328 // Try overwriting the old entries with the new ones.329 for (auto &kvp : newEntriesForType) {330 if (!entriesForType.count(kvp.first)) {331 entriesForType[kvp.first] = std::move(kvp.second);332 continue;333 }334 335 Type typeSample = cast<Type>(kvp.second.front().getKey());336 assert(&typeSample.getDialect() !=337 typeSample.getContext()->getLoadedDialect<BuiltinDialect>() &&338 "unexpected data layout entry for built-in type");339 340 auto interface = cast<DataLayoutTypeInterface>(typeSample);341 // TODO: Revisit this method and call once342 // https://github.com/llvm/llvm-project/issues/130321 gets resolved.343 if (!interface.areCompatible(entriesForType.lookup(kvp.first), kvp.second,344 spec, entriesForID))345 return failure();346 347 overwriteDuplicateEntries(entriesForType[kvp.first], kvp.second);348 }349 350 return success();351}352 353DataLayoutSpecAttr354DataLayoutSpecAttr::combineWith(ArrayRef<DataLayoutSpecInterface> specs) const {355 // Only combine with attributes of the same kind.356 // TODO: reconsider this when the need arises.357 if (any_of(specs, [](DataLayoutSpecInterface spec) {358 return !llvm::isa<DataLayoutSpecAttr>(spec);359 }))360 return {};361 362 // Combine all specs in order, with `this` being the last one.363 llvm::MapVector<TypeID, DataLayoutEntryList> entriesForType;364 llvm::MapVector<StringAttr, DataLayoutEntryInterface> entriesForID;365 for (DataLayoutSpecInterface spec : specs)366 if (failed(combineOneSpec(spec, entriesForType, entriesForID)))367 return nullptr;368 if (failed(combineOneSpec(*this, entriesForType, entriesForID)))369 return nullptr;370 371 // Rebuild the linear list of entries.372 SmallVector<DataLayoutEntryInterface> entries;373 llvm::append_range(entries, llvm::make_second_range(entriesForID));374 for (const auto &kvp : entriesForType)375 llvm::append_range(entries, kvp.second);376 377 return DataLayoutSpecAttr::get(getContext(), entries);378}379 380StringAttr381DataLayoutSpecAttr::getEndiannessIdentifier(MLIRContext *context) const {382 return Builder(context).getStringAttr(DLTIDialect::kDataLayoutEndiannessKey);383}384 385StringAttr DataLayoutSpecAttr::getDefaultMemorySpaceIdentifier(386 MLIRContext *context) const {387 return Builder(context).getStringAttr(388 DLTIDialect::kDataLayoutDefaultMemorySpaceKey);389}390 391StringAttr392DataLayoutSpecAttr::getAllocaMemorySpaceIdentifier(MLIRContext *context) const {393 return Builder(context).getStringAttr(394 DLTIDialect::kDataLayoutAllocaMemorySpaceKey);395}396 397StringAttr DataLayoutSpecAttr::getProgramMemorySpaceIdentifier(398 MLIRContext *context) const {399 return Builder(context).getStringAttr(400 DLTIDialect::kDataLayoutProgramMemorySpaceKey);401}402 403StringAttr404DataLayoutSpecAttr::getGlobalMemorySpaceIdentifier(MLIRContext *context) const {405 return Builder(context).getStringAttr(406 DLTIDialect::kDataLayoutGlobalMemorySpaceKey);407}408 409StringAttr410DataLayoutSpecAttr::getManglingModeIdentifier(MLIRContext *context) const {411 return Builder(context).getStringAttr(412 DLTIDialect::kDataLayoutManglingModeKey);413}414 415StringAttr416DataLayoutSpecAttr::getStackAlignmentIdentifier(MLIRContext *context) const {417 return Builder(context).getStringAttr(418 DLTIDialect::kDataLayoutStackAlignmentKey);419}420 421StringAttr DataLayoutSpecAttr::getFunctionPointerAlignmentIdentifier(422 MLIRContext *context) const {423 return Builder(context).getStringAttr(424 DLTIDialect::kDataLayoutFunctionPointerAlignmentKey);425}426 427StringAttr428DataLayoutSpecAttr::getLegalIntWidthsIdentifier(MLIRContext *context) const {429 return Builder(context).getStringAttr(430 DLTIDialect::kDataLayoutLegalIntWidthsKey);431}432 433/// Parses an attribute with syntax:434/// dl-spec-attr ::= `#dlti.` `dl_spec` `<` entry-list `>`435/// entry-list ::= | entry | entry `,` entry-list436/// entry ::= ((type | quoted-string) = attr) | dl-entry-attr437Attribute DataLayoutSpecAttr::parse(AsmParser &parser, Type type) {438 return parseAngleBracketedEntries<DataLayoutSpecAttr>(parser, type,439 /*tryType=*/true,440 /*allowEmpty=*/true);441}442 443void DataLayoutSpecAttr::print(AsmPrinter &printer) const {444 printAngleBracketedEntries(printer, getEntries());445}446 447//===----------------------------------------------------------------------===//448// TargetDeviceSpecAttr449//===----------------------------------------------------------------------===//450 451LogicalResult452TargetDeviceSpecAttr::verify(function_ref<InFlightDiagnostic()> emitError,453 ArrayRef<DataLayoutEntryInterface> entries) {454 return verifyEntries(emitError, entries, /*allowTypes=*/false);455}456 457/// Parses an attribute with syntax:458/// dev-spec-attr ::= `#dlti.` `target_device_spec` `<` entry-list `>`459/// entry-list ::= entry | entry `,` entry-list460/// entry ::= (quoted-string `=` attr) | dl-entry-attr461Attribute TargetDeviceSpecAttr::parse(AsmParser &parser, Type type) {462 return parseAngleBracketedEntries<TargetDeviceSpecAttr>(parser, type);463}464 465void TargetDeviceSpecAttr::print(AsmPrinter &printer) const {466 printAngleBracketedEntries(printer, getEntries());467}468 469//===----------------------------------------------------------------------===//470// TargetSystemSpecAttr471//===----------------------------------------------------------------------===//472 473LogicalResult474TargetSystemSpecAttr::verify(function_ref<InFlightDiagnostic()> emitError,475 ArrayRef<DataLayoutEntryInterface> entries) {476 DenseSet<TargetSystemSpecInterface::DeviceID> deviceIds;477 478 for (const auto &entry : entries) {479 auto deviceId =480 llvm::dyn_cast<TargetSystemSpecInterface::DeviceID>(entry.getKey());481 if (!deviceId)482 return emitError() << "non-string key of DLTI system spec";483 484 if (auto targetDeviceSpec =485 llvm::dyn_cast<TargetDeviceSpecInterface>(entry.getValue())) {486 if (failed(TargetDeviceSpecAttr::verify(emitError,487 targetDeviceSpec.getEntries())))488 return failure(); // Assume sub-verifier outputted error message.489 } else {490 return emitError() << "value associated with key " << deviceId491 << " is not a DLTI device spec";492 }493 494 // Check that device IDs are unique across all entries.495 if (!deviceIds.insert(deviceId).second)496 return emitError() << "repeated device ID in dlti.target_system_spec: "497 << deviceId;498 }499 500 return success();501}502 503/// Parses an attribute with syntax:504/// sys-spec-attr ::= `#dlti.` `target_system_spec` `<` entry-list `>`505/// entry-list ::= entry | entry `,` entry-list506/// entry ::= (quoted-string `=` dev-spec-attr) | dl-entry-attr507Attribute TargetSystemSpecAttr::parse(AsmParser &parser, Type type) {508 return parseAngleBracketedEntries<TargetSystemSpecAttr>(parser, type);509}510 511void TargetSystemSpecAttr::print(AsmPrinter &printer) const {512 printAngleBracketedEntries(printer, getEntries());513}514 515//===----------------------------------------------------------------------===//516// DLTIDialect517//===----------------------------------------------------------------------===//518 519/// Retrieve the first `DLTIQueryInterface`-implementing attribute that is520/// attached to `op` or such an attr on as close as possible an ancestor. The521/// op the attribute is attached to is returned as well.522static std::pair<DLTIQueryInterface, Operation *>523getClosestQueryable(Operation *op) {524 DLTIQueryInterface queryable = {};525 526 // Search op and its ancestors for the first attached DLTIQueryInterface attr.527 do {528 for (NamedAttribute attr : op->getAttrs())529 if ((queryable = dyn_cast<DLTIQueryInterface>(attr.getValue())))530 break;531 } while (!queryable && (op = op->getParentOp()));532 533 return std::pair(queryable, op);534}535 536FailureOr<Attribute>537dlti::query(Operation *op, ArrayRef<DataLayoutEntryKey> keys, bool emitError) {538 if (!op)539 return failure();540 541 if (keys.empty()) {542 if (emitError) {543 auto diag = op->emitError() << "target op of failed DLTI query";544 diag.attachNote(op->getLoc()) << "no keys provided to attempt query with";545 }546 return failure();547 }548 549 auto [queryable, queryOp] = getClosestQueryable(op);550 Operation *reportOp = (queryOp ? queryOp : op);551 552 if (!queryable) {553 if (emitError) {554 auto diag = op->emitError() << "target op of failed DLTI query";555 diag.attachNote(reportOp->getLoc())556 << "no DLTI-queryable attrs on target op or any of its ancestors";557 }558 return failure();559 }560 561 Attribute currentAttr = queryable;562 for (auto &&[idx, key] : llvm::enumerate(keys)) {563 if (auto map = dyn_cast<DLTIQueryInterface>(currentAttr)) {564 auto maybeAttr = map.query(key);565 if (failed(maybeAttr)) {566 if (emitError) {567 auto diag = op->emitError() << "target op of failed DLTI query";568 diag.attachNote(reportOp->getLoc())569 << "key " << keyToStr(key)570 << " has no DLTI-mapping per attr: " << map;571 }572 return failure();573 }574 currentAttr = *maybeAttr;575 } else {576 if (emitError) {577 std::string commaSeparatedKeys;578 llvm::interleave(579 keys.take_front(idx), // All prior keys.580 [&](auto key) { commaSeparatedKeys += keyToStr(key); },581 [&]() { commaSeparatedKeys += ","; });582 583 auto diag = op->emitError() << "target op of failed DLTI query";584 diag.attachNote(reportOp->getLoc())585 << "got non-DLTI-queryable attribute upon looking up keys ["586 << commaSeparatedKeys << "] at op";587 }588 return failure();589 }590 }591 592 return currentAttr;593}594 595FailureOr<Attribute> dlti::query(Operation *op, ArrayRef<StringRef> keys,596 bool emitError) {597 if (!op)598 return failure();599 600 MLIRContext *ctx = op->getContext();601 SmallVector<DataLayoutEntryKey> entryKeys;602 entryKeys.reserve(keys.size());603 for (StringRef key : keys)604 entryKeys.push_back(StringAttr::get(ctx, key));605 606 return dlti::query(op, entryKeys, emitError);607}608 609namespace {610class TargetDataLayoutInterface : public DataLayoutDialectInterface {611public:612 using DataLayoutDialectInterface::DataLayoutDialectInterface;613 614 LogicalResult verifyEntry(DataLayoutEntryInterface entry,615 Location loc) const final {616 StringRef entryName = cast<StringAttr>(entry.getKey()).strref();617 if (entryName == DLTIDialect::kDataLayoutEndiannessKey) {618 auto value = dyn_cast<StringAttr>(entry.getValue());619 if (value &&620 (value.getValue() == DLTIDialect::kDataLayoutEndiannessBig ||621 value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle))622 return success();623 return emitError(loc) << "'" << entryName624 << "' data layout entry is expected to be either '"625 << DLTIDialect::kDataLayoutEndiannessBig << "' or '"626 << DLTIDialect::kDataLayoutEndiannessLittle << "'";627 }628 if (entryName == DLTIDialect::kDataLayoutDefaultMemorySpaceKey ||629 entryName == DLTIDialect::kDataLayoutAllocaMemorySpaceKey ||630 entryName == DLTIDialect::kDataLayoutProgramMemorySpaceKey ||631 entryName == DLTIDialect::kDataLayoutGlobalMemorySpaceKey ||632 entryName == DLTIDialect::kDataLayoutStackAlignmentKey ||633 entryName == DLTIDialect::kDataLayoutFunctionPointerAlignmentKey ||634 entryName == DLTIDialect::kDataLayoutLegalIntWidthsKey ||635 entryName == DLTIDialect::kDataLayoutManglingModeKey)636 return success();637 return emitError(loc) << "unknown data layout entry name: " << entryName;638 }639};640} // namespace641 642void DLTIDialect::initialize() {643 addAttributes<644#define GET_ATTRDEF_LIST645#include "mlir/Dialect/DLTI/DLTIAttrs.cpp.inc"646 >();647 addInterfaces<TargetDataLayoutInterface>();648}649 650LogicalResult DLTIDialect::verifyOperationAttribute(Operation *op,651 NamedAttribute attr) {652 if (attr.getName() == DLTIDialect::kDataLayoutAttrName) {653 if (!llvm::isa<DataLayoutSpecAttr>(attr.getValue())) {654 return op->emitError() << "'" << DLTIDialect::kDataLayoutAttrName655 << "' is expected to be a #dlti.dl_spec attribute";656 }657 if (isa<ModuleOp>(op))658 return detail::verifyDataLayoutOp(op);659 return success();660 }661 662 if (attr.getName() == DLTIDialect::kTargetSystemDescAttrName) {663 if (!llvm::isa<TargetSystemSpecAttr>(attr.getValue())) {664 return op->emitError()665 << "'" << DLTIDialect::kTargetSystemDescAttrName666 << "' is expected to be a #dlti.target_system_spec attribute";667 }668 return success();669 }670 671 if (attr.getName() == DLTIDialect::kMapAttrName) {672 if (!llvm::isa<MapAttr>(attr.getValue())) {673 return op->emitError() << "'" << DLTIDialect::kMapAttrName674 << "' is expected to be a #dlti.map attribute";675 }676 return success();677 }678 679 return op->emitError() << "attribute '" << attr.getName().getValue()680 << "' not supported by dialect";681}682