brintos

brintos / llvm-project-archived public Read only

0
0
Text · 25.2 KiB · da572f1 Raw
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