MLIR  20.0.0git
DLTI.cpp
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "mlir/IR/Builders.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"
17 #include "llvm/ADT/TypeSwitch.h"
18 
19 #include "llvm/ADT/TypeSwitch.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/MathExtras.h"
22 
23 using namespace mlir;
24 
25 #include "mlir/Dialect/DLTI/DLTIDialect.cpp.inc"
26 
27 #define GET_ATTRDEF_CLASSES
28 #include "mlir/Dialect/DLTI/DLTIAttrs.cpp.inc"
29 
30 #define DEBUG_TYPE "dlti"
31 
32 //===----------------------------------------------------------------------===//
33 // Common parsing utility functions.
34 //===----------------------------------------------------------------------===//
35 
36 /// Parse an entry which can either be of the form `key = value` or a
37 /// #dlti.dl_entry attribute. When `tryType=true` the key can be a type,
38 /// otherwise only quoted strings are allowed. The grammar is as follows:
39 /// entry ::= ((type | quoted-string) `=` attr) | dl-entry-attr
40 static ParseResult parseKeyValuePair(AsmParser &parser,
41  DataLayoutEntryInterface &entry,
42  bool tryType = false) {
43  Attribute value;
44 
45  if (tryType) {
46  Type type;
47  OptionalParseResult parsedType = parser.parseOptionalType(type);
48  if (parsedType.has_value()) {
49  if (failed(parsedType.value()))
50  return parser.emitError(parser.getCurrentLocation())
51  << "error while parsing type DLTI key";
52 
53  if (failed(parser.parseEqual()) || failed(parser.parseAttribute(value)))
54  return failure();
55 
56  entry = DataLayoutEntryAttr::get(type, value);
57  return ParseResult::success();
58  }
59  }
60 
61  std::string ident;
62  OptionalParseResult parsedStr = parser.parseOptionalString(&ident);
63  if (parsedStr.has_value() && succeeded(parsedStr.value())) {
64  if (failed(parser.parseEqual()) || failed(parser.parseAttribute(value)))
65  return failure(); // Assume that an error has already been emitted.
66 
68  StringAttr::get(parser.getContext(), ident), value);
69  return ParseResult::success();
70  }
71 
72  OptionalParseResult parsedEntry = parser.parseAttribute(entry);
73  if (parsedEntry.has_value()) {
74  if (succeeded(parsedEntry.value()))
75  return parsedEntry.value();
76  return failure(); // Assume that an error has already been emitted.
77  }
78  return parser.emitError(parser.getCurrentLocation())
79  << "failed to parse DLTI entry";
80 }
81 
82 /// Construct a requested attribute by parsing list of entries occurring within
83 /// a pair of `<` and `>`, optionally allow types as keys and an empty list.
84 /// The grammar is as follows:
85 /// bracketed-entry-list ::=`<` entry-list `>`
86 /// entry-list ::= | entry | entry `,` entry-list
87 /// entry ::= ((type | quoted-string) `=` attr) | dl-entry-attr
88 template <class Attr>
90  bool tryType = false,
91  bool allowEmpty = false) {
93  if (failed(parser.parseCommaSeparatedList(
95  return parseKeyValuePair(parser, entries.emplace_back(), tryType);
96  })))
97  return {};
98 
99  if (entries.empty() && !allowEmpty) {
100  parser.emitError(parser.getNameLoc()) << "no DLTI entries provided";
101  return {};
102  }
103 
104  return Attr::getChecked([&] { return parser.emitError(parser.getNameLoc()); },
105  parser.getContext(), ArrayRef(entries));
106 }
107 
108 //===----------------------------------------------------------------------===//
109 // Common printing utility functions.
110 //===----------------------------------------------------------------------===//
111 
112 /// Convert pointer-union keys to strings.
113 static std::string keyToStr(DataLayoutEntryKey key) {
114  std::string buf;
116  .Case<StringAttr, Type>( // The only two kinds of key we know of.
117  [&](auto key) { llvm::raw_string_ostream(buf) << key; });
118  return buf;
119 }
120 
121 /// Pretty-print entries, each in `key = value` format, separated by commas.
122 template <class T>
123 static void printAngleBracketedEntries(AsmPrinter &os, T &&entries) {
124  os << "<";
125  llvm::interleaveComma(std::forward<T>(entries), os, [&](auto entry) {
126  os << keyToStr(entry.getKey()) << " = " << entry.getValue();
127  });
128  os << ">";
129 }
130 
131 //===----------------------------------------------------------------------===//
132 // Common verifying utility functions.
133 //===----------------------------------------------------------------------===//
134 
135 /// Verify entries, with the option to disallow types as keys.
138  bool allowTypes = true) {
140  for (DataLayoutEntryInterface entry : entries) {
141  if (!entry)
142  return emitError() << "contained invalid DLTI entry";
143  DataLayoutEntryKey key = entry.getKey();
144  if (key.isNull())
145  return emitError() << "contained invalid DLTI key";
146  if (!allowTypes && dyn_cast<Type>(key))
147  return emitError() << "type as DLTI key is not allowed";
148  if (auto strKey = dyn_cast<StringAttr>(key))
149  if (strKey.getValue().empty())
150  return emitError() << "empty string as DLTI key is not allowed";
151  if (!keys.insert(key).second)
152  return emitError() << "repeated DLTI key: " << keyToStr(key);
153  if (!entry.getValue())
154  return emitError() << "value associated to DLTI key " << keyToStr(key)
155  << " is invalid";
156  }
157  return success();
158 }
159 
160 //===----------------------------------------------------------------------===//
161 // DataLayoutEntryAttr
162 //===----------------------------------------------------------------------===//
163 namespace mlir {
164 namespace detail {
166 public:
167  using KeyTy = std::pair<DataLayoutEntryKey, Attribute>;
168 
170  : entryKey(entryKey), value(value) {}
171 
173  construct(AttributeStorageAllocator &allocator, const KeyTy &key) {
174  return new (allocator.allocate<DataLayoutEntryAttrStorage>())
175  DataLayoutEntryAttrStorage(key.first, key.second);
176  }
177 
178  bool operator==(const KeyTy &other) const {
179  return other.first == entryKey && other.second == value;
180  }
181 
184 };
185 } // namespace detail
186 } // namespace mlir
187 
188 DataLayoutEntryAttr DataLayoutEntryAttr::get(StringAttr key, Attribute value) {
189  return Base::get(key.getContext(), key, value);
190 }
191 
192 DataLayoutEntryAttr DataLayoutEntryAttr::get(Type key, Attribute value) {
193  return Base::get(key.getContext(), key, value);
194 }
195 
196 DataLayoutEntryKey DataLayoutEntryAttr::getKey() const {
197  return getImpl()->entryKey;
198 }
199 
200 Attribute DataLayoutEntryAttr::getValue() const { return getImpl()->value; }
201 
202 /// Parses an attribute with syntax:
203 /// dl-entry-attr ::= `#dlti.` `dl_entry` `<` (type | quoted-string) `,`
204 /// attr `>`
206  if (failed(parser.parseLess()))
207  return {};
208 
209  Type typeKey = nullptr;
210  std::string identifier;
211  SMLoc idLoc = parser.getCurrentLocation();
212  OptionalParseResult parsedType = parser.parseOptionalType(typeKey);
213  if (parsedType.has_value() && failed(parsedType.value()))
214  return {};
215  if (!parsedType.has_value()) {
216  OptionalParseResult parsedString = parser.parseOptionalString(&identifier);
217  if (!parsedString.has_value() || failed(parsedString.value())) {
218  parser.emitError(idLoc) << "expected a type or a quoted string";
219  return {};
220  }
221  }
222 
223  Attribute value;
224  if (failed(parser.parseComma()) || failed(parser.parseAttribute(value)) ||
225  failed(parser.parseGreater()))
226  return {};
227 
228  return typeKey ? get(typeKey, value)
229  : get(parser.getBuilder().getStringAttr(identifier), value);
230 }
231 
232 void DataLayoutEntryAttr::print(AsmPrinter &printer) const {
233  printer << "<" << keyToStr(getKey()) << ", " << getValue() << ">";
234 }
235 
236 //===----------------------------------------------------------------------===//
237 // DLTIMapAttr
238 //===----------------------------------------------------------------------===//
239 
240 /// Parses an attribute with syntax:
241 /// map-attr ::= `#dlti.` `map` `<` entry-list `>`
242 /// entry-list ::= entry | entry `,` entry-list
243 /// entry ::= ((type | quoted-string) `=` attr) | dl-entry-attr
244 Attribute MapAttr::parse(AsmParser &parser, Type type) {
245  return parseAngleBracketedEntries<MapAttr>(parser, type, /*tryType=*/true,
246  /*allowEmpty=*/true);
247 }
248 
249 void MapAttr::print(AsmPrinter &printer) const {
250  printAngleBracketedEntries(printer, getEntries());
251 }
252 
255  return verifyEntries(emitError, entries);
256 }
257 
258 //===----------------------------------------------------------------------===//
259 // DataLayoutSpecAttr
260 //===----------------------------------------------------------------------===//
261 
262 LogicalResult
265  return verifyEntries(emitError, entries);
266 }
267 
268 /// Given a list of old and a list of new entries, overwrites old entries with
269 /// new ones if they have matching keys, appends new entries to the old entry
270 /// list otherwise.
271 static void
274  unsigned oldEntriesSize = oldEntries.size();
275  for (DataLayoutEntryInterface entry : newEntries) {
276  // We expect a small (dozens) number of entries, so it is practically
277  // cheaper to iterate over the list linearly rather than to create an
278  // auxiliary hashmap to avoid duplication. Also note that we never need to
279  // check for duplicate keys the values that were added from `newEntries`.
280  bool replaced = false;
281  for (unsigned i = 0; i < oldEntriesSize; ++i) {
282  if (oldEntries[i].getKey() == entry.getKey()) {
283  oldEntries[i] = entry;
284  replaced = true;
285  break;
286  }
287  }
288  if (!replaced)
289  oldEntries.push_back(entry);
290  }
291 }
292 
293 /// Combines a data layout spec into the given lists of entries organized by
294 /// type class and identifier, overwriting them if necessary. Fails to combine
295 /// if the two entries with identical keys are not compatible.
296 static LogicalResult
297 combineOneSpec(DataLayoutSpecInterface spec,
300  // A missing spec should be fine.
301  if (!spec)
302  return success();
303 
304  DenseMap<TypeID, DataLayoutEntryList> newEntriesForType;
306  spec.bucketEntriesByType(newEntriesForType, newEntriesForID);
307 
308  // Try overwriting the old entries with the new ones.
309  for (auto &kvp : newEntriesForType) {
310  if (!entriesForType.count(kvp.first)) {
311  entriesForType[kvp.first] = std::move(kvp.second);
312  continue;
313  }
314 
315  Type typeSample = kvp.second.front().getKey().get<Type>();
316  assert(&typeSample.getDialect() !=
317  typeSample.getContext()->getLoadedDialect<BuiltinDialect>() &&
318  "unexpected data layout entry for built-in type");
319 
320  auto interface = cast<DataLayoutTypeInterface>(typeSample);
321  if (!interface.areCompatible(entriesForType.lookup(kvp.first), kvp.second))
322  return failure();
323 
324  overwriteDuplicateEntries(entriesForType[kvp.first], kvp.second);
325  }
326 
327  for (const auto &kvp : newEntriesForID) {
328  StringAttr id = kvp.second.getKey().get<StringAttr>();
329  Dialect *dialect = id.getReferencedDialect();
330  if (!entriesForID.count(id)) {
331  entriesForID[id] = kvp.second;
332  continue;
333  }
334 
335  // Attempt to combine the enties using the dialect interface. If the
336  // dialect is not loaded for some reason, use the default combinator
337  // that conservatively accepts identical entries only.
338  entriesForID[id] =
339  dialect ? cast<DataLayoutDialectInterface>(dialect)->combine(
340  entriesForID[id], kvp.second)
342  kvp.second);
343  if (!entriesForID[id])
344  return failure();
345  }
346 
347  return success();
348 }
349 
350 DataLayoutSpecAttr
351 DataLayoutSpecAttr::combineWith(ArrayRef<DataLayoutSpecInterface> specs) const {
352  // Only combine with attributes of the same kind.
353  // TODO: reconsider this when the need arises.
354  if (any_of(specs, [](DataLayoutSpecInterface spec) {
355  return !llvm::isa<DataLayoutSpecAttr>(spec);
356  }))
357  return {};
358 
359  // Combine all specs in order, with `this` being the last one.
362  for (DataLayoutSpecInterface spec : specs)
363  if (failed(combineOneSpec(spec, entriesForType, entriesForID)))
364  return nullptr;
365  if (failed(combineOneSpec(*this, entriesForType, entriesForID)))
366  return nullptr;
367 
368  // Rebuild the linear list of entries.
370  llvm::append_range(entries, llvm::make_second_range(entriesForID));
371  for (const auto &kvp : entriesForType)
372  llvm::append_range(entries, kvp.getSecond());
373 
374  return DataLayoutSpecAttr::get(getContext(), entries);
375 }
376 
377 StringAttr
378 DataLayoutSpecAttr::getEndiannessIdentifier(MLIRContext *context) const {
379  return Builder(context).getStringAttr(DLTIDialect::kDataLayoutEndiannessKey);
380 }
381 
382 StringAttr
383 DataLayoutSpecAttr::getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
384  return Builder(context).getStringAttr(
385  DLTIDialect::kDataLayoutAllocaMemorySpaceKey);
386 }
387 
388 StringAttr DataLayoutSpecAttr::getProgramMemorySpaceIdentifier(
389  MLIRContext *context) const {
390  return Builder(context).getStringAttr(
391  DLTIDialect::kDataLayoutProgramMemorySpaceKey);
392 }
393 
394 StringAttr
395 DataLayoutSpecAttr::getGlobalMemorySpaceIdentifier(MLIRContext *context) const {
396  return Builder(context).getStringAttr(
397  DLTIDialect::kDataLayoutGlobalMemorySpaceKey);
398 }
399 
400 StringAttr
401 DataLayoutSpecAttr::getStackAlignmentIdentifier(MLIRContext *context) const {
402  return Builder(context).getStringAttr(
403  DLTIDialect::kDataLayoutStackAlignmentKey);
404 }
405 
406 /// Parses an attribute with syntax:
407 /// dl-spec-attr ::= `#dlti.` `dl_spec` `<` entry-list `>`
408 /// entry-list ::= | entry | entry `,` entry-list
409 /// entry ::= ((type | quoted-string) = attr) | dl-entry-attr
411  return parseAngleBracketedEntries<DataLayoutSpecAttr>(parser, type,
412  /*tryType=*/true,
413  /*allowEmpty=*/true);
414 }
415 
416 void DataLayoutSpecAttr::print(AsmPrinter &printer) const {
417  printAngleBracketedEntries(printer, getEntries());
418 }
419 
420 //===----------------------------------------------------------------------===//
421 // TargetDeviceSpecAttr
422 //===----------------------------------------------------------------------===//
423 
424 LogicalResult
427  return verifyEntries(emitError, entries, /*allowTypes=*/false);
428 }
429 
430 /// Parses an attribute with syntax:
431 /// dev-spec-attr ::= `#dlti.` `target_device_spec` `<` entry-list `>`
432 /// entry-list ::= entry | entry `,` entry-list
433 /// entry ::= (quoted-string `=` attr) | dl-entry-attr
435  return parseAngleBracketedEntries<TargetDeviceSpecAttr>(parser, type);
436 }
437 
438 void TargetDeviceSpecAttr::print(AsmPrinter &printer) const {
439  printAngleBracketedEntries(printer, getEntries());
440 }
441 
442 //===----------------------------------------------------------------------===//
443 // TargetSystemSpecAttr
444 //===----------------------------------------------------------------------===//
445 
446 LogicalResult
450 
451  for (const auto &entry : entries) {
452  auto deviceId =
453  llvm::dyn_cast<TargetSystemSpecInterface::DeviceID>(entry.getKey());
454  if (!deviceId)
455  return emitError() << "non-string key of DLTI system spec";
456 
457  if (auto targetDeviceSpec =
458  llvm::dyn_cast<TargetDeviceSpecInterface>(entry.getValue())) {
460  targetDeviceSpec.getEntries())))
461  return failure(); // Assume sub-verifier outputted error message.
462  } else {
463  return emitError() << "value associated with key " << deviceId
464  << " is not a DLTI device spec";
465  }
466 
467  // Check that device IDs are unique across all entries.
468  if (!deviceIds.insert(deviceId).second)
469  return emitError() << "repeated device ID in dlti.target_system_spec: "
470  << deviceId;
471  }
472 
473  return success();
474 }
475 
476 /// Parses an attribute with syntax:
477 /// sys-spec-attr ::= `#dlti.` `target_system_spec` `<` entry-list `>`
478 /// entry-list ::= entry | entry `,` entry-list
479 /// entry ::= (quoted-string `=` dev-spec-attr) | dl-entry-attr
481  return parseAngleBracketedEntries<TargetSystemSpecAttr>(parser, type);
482 }
483 
484 void TargetSystemSpecAttr::print(AsmPrinter &printer) const {
485  printAngleBracketedEntries(printer, getEntries());
486 }
487 
488 //===----------------------------------------------------------------------===//
489 // DLTIDialect
490 //===----------------------------------------------------------------------===//
491 
492 /// Retrieve the first `DLTIQueryInterface`-implementing attribute that is
493 /// attached to `op` or such an attr on as close as possible an ancestor. The
494 /// op the attribute is attached to is returned as well.
495 static std::pair<DLTIQueryInterface, Operation *>
497  DLTIQueryInterface queryable = {};
498 
499  // Search op and its ancestors for the first attached DLTIQueryInterface attr.
500  do {
501  for (NamedAttribute attr : op->getAttrs())
502  if ((queryable = dyn_cast<DLTIQueryInterface>(attr.getValue())))
503  break;
504  } while (!queryable && (op = op->getParentOp()));
505 
506  return std::pair(queryable, op);
507 }
508 
509 FailureOr<Attribute>
511  if (keys.empty()) {
512  if (emitError) {
513  auto diag = op->emitError() << "target op of failed DLTI query";
514  diag.attachNote(op->getLoc()) << "no keys provided to attempt query with";
515  }
516  return failure();
517  }
518 
519  auto [queryable, queryOp] = getClosestQueryable(op);
520  Operation *reportOp = (queryOp ? queryOp : op);
521 
522  if (!queryable) {
523  if (emitError) {
524  auto diag = op->emitError() << "target op of failed DLTI query";
525  diag.attachNote(reportOp->getLoc())
526  << "no DLTI-queryable attrs on target op or any of its ancestors";
527  }
528  return failure();
529  }
530 
531  Attribute currentAttr = queryable;
532  for (auto &&[idx, key] : llvm::enumerate(keys)) {
533  if (auto map = dyn_cast<DLTIQueryInterface>(currentAttr)) {
534  auto maybeAttr = map.query(key);
535  if (failed(maybeAttr)) {
536  if (emitError) {
537  auto diag = op->emitError() << "target op of failed DLTI query";
538  diag.attachNote(reportOp->getLoc())
539  << "key " << keyToStr(key)
540  << " has no DLTI-mapping per attr: " << map;
541  }
542  return failure();
543  }
544  currentAttr = *maybeAttr;
545  } else {
546  if (emitError) {
547  std::string commaSeparatedKeys;
548  llvm::interleave(
549  keys.take_front(idx), // All prior keys.
550  [&](auto key) { commaSeparatedKeys += keyToStr(key); },
551  [&]() { commaSeparatedKeys += ","; });
552 
553  auto diag = op->emitError() << "target op of failed DLTI query";
554  diag.attachNote(reportOp->getLoc())
555  << "got non-DLTI-queryable attribute upon looking up keys ["
556  << commaSeparatedKeys << "] at op";
557  }
558  return failure();
559  }
560  }
561 
562  return currentAttr;
563 }
564 
565 constexpr const StringLiteral mlir::DLTIDialect::kDataLayoutAttrName;
566 constexpr const StringLiteral mlir::DLTIDialect::kDataLayoutEndiannessKey;
567 constexpr const StringLiteral mlir::DLTIDialect::kDataLayoutEndiannessBig;
568 constexpr const StringLiteral mlir::DLTIDialect::kDataLayoutEndiannessLittle;
569 
570 namespace {
571 class TargetDataLayoutInterface : public DataLayoutDialectInterface {
572 public:
574 
575  LogicalResult verifyEntry(DataLayoutEntryInterface entry,
576  Location loc) const final {
577  StringRef entryName = entry.getKey().get<StringAttr>().strref();
578  if (entryName == DLTIDialect::kDataLayoutEndiannessKey) {
579  auto value = dyn_cast<StringAttr>(entry.getValue());
580  if (value &&
581  (value.getValue() == DLTIDialect::kDataLayoutEndiannessBig ||
582  value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle))
583  return success();
584  return emitError(loc) << "'" << entryName
585  << "' data layout entry is expected to be either '"
586  << DLTIDialect::kDataLayoutEndiannessBig << "' or '"
587  << DLTIDialect::kDataLayoutEndiannessLittle << "'";
588  }
589  if (entryName == DLTIDialect::kDataLayoutAllocaMemorySpaceKey ||
590  entryName == DLTIDialect::kDataLayoutProgramMemorySpaceKey ||
591  entryName == DLTIDialect::kDataLayoutGlobalMemorySpaceKey ||
592  entryName == DLTIDialect::kDataLayoutStackAlignmentKey)
593  return success();
594  return emitError(loc) << "unknown data layout entry name: " << entryName;
595  }
596 };
597 } // namespace
598 
599 void DLTIDialect::initialize() {
600  addAttributes<
601 #define GET_ATTRDEF_LIST
602 #include "mlir/Dialect/DLTI/DLTIAttrs.cpp.inc"
603  >();
604  addInterfaces<TargetDataLayoutInterface>();
605 }
606 
607 LogicalResult DLTIDialect::verifyOperationAttribute(Operation *op,
608  NamedAttribute attr) {
609  if (attr.getName() == DLTIDialect::kDataLayoutAttrName) {
610  if (!llvm::isa<DataLayoutSpecAttr>(attr.getValue())) {
611  return op->emitError() << "'" << DLTIDialect::kDataLayoutAttrName
612  << "' is expected to be a #dlti.dl_spec attribute";
613  }
614  if (isa<ModuleOp>(op))
615  return detail::verifyDataLayoutOp(op);
616  return success();
617  }
618 
619  if (attr.getName() == DLTIDialect::kTargetSystemDescAttrName) {
620  if (!llvm::isa<TargetSystemSpecAttr>(attr.getValue())) {
621  return op->emitError()
622  << "'" << DLTIDialect::kTargetSystemDescAttrName
623  << "' is expected to be a #dlti.target_system_spec attribute";
624  }
625  return success();
626  }
627 
628  if (attr.getName() == DLTIDialect::kMapAttrName) {
629  if (!llvm::isa<MapAttr>(attr.getValue())) {
630  return op->emitError() << "'" << DLTIDialect::kMapAttrName
631  << "' is expected to be a #dlti.map attribute";
632  }
633  return success();
634  }
635 
636  return op->emitError() << "attribute '" << attr.getName().getValue()
637  << "' not supported by dialect";
638 }
static LogicalResult verifyEntries(function_ref< InFlightDiagnostic()> emitError, ArrayRef< DataLayoutEntryInterface > entries, bool allowTypes=true)
Verify entries, with the option to disallow types as keys.
Definition: DLTI.cpp:136
static void printAngleBracketedEntries(AsmPrinter &os, T &&entries)
Pretty-print entries, each in key = value format, separated by commas.
Definition: DLTI.cpp:123
static std::pair< DLTIQueryInterface, Operation * > getClosestQueryable(Operation *op)
Retrieve the first DLTIQueryInterface-implementing attribute that is attached to op or such an attr o...
Definition: DLTI.cpp:496
static std::string keyToStr(DataLayoutEntryKey key)
Convert pointer-union keys to strings.
Definition: DLTI.cpp:113
static LogicalResult combineOneSpec(DataLayoutSpecInterface spec, DenseMap< TypeID, DataLayoutEntryList > &entriesForType, DenseMap< StringAttr, DataLayoutEntryInterface > &entriesForID)
Combines a data layout spec into the given lists of entries organized by type class and identifier,...
Definition: DLTI.cpp:297
static void overwriteDuplicateEntries(SmallVectorImpl< DataLayoutEntryInterface > &oldEntries, ArrayRef< DataLayoutEntryInterface > newEntries)
Given a list of old and a list of new entries, overwrites old entries with new ones if they have matc...
Definition: DLTI.cpp:272
static Attribute parseAngleBracketedEntries(AsmParser &parser, Type ty, bool tryType=false, bool allowEmpty=false)
Construct a requested attribute by parsing list of entries occurring within a pair of < and >,...
Definition: DLTI.cpp:89
static ParseResult parseKeyValuePair(AsmParser &parser, DataLayoutEntryInterface &entry, bool tryType=false)
Parse an entry which can either be of the form key = value or a #dlti.dl_entry attribute.
Definition: DLTI.cpp:40
static MLIRContext * getContext(OpFoldResult val)
static std::string diag(const llvm::Value &value)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
This base class exposes generic asm parser hooks, usable across the various derived parsers.
@ LessGreater
<> brackets surrounding zero or more operands.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual OptionalParseResult parseOptionalType(Type &result)=0
Parse an optional type.
MLIRContext * getContext() const
Definition: AsmPrinter.cpp:73
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseLess()=0
Parse a '<' token.
virtual ParseResult parseEqual()=0
Parse a = token.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalString(std::string *string)=0
Parse a quoted string token if present.
virtual ParseResult parseGreater()=0
Parse a '>' token.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
This base class exposes generic asm printer hooks, usable across the various derived printers.
Base storage class appearing in an attribute.
Attributes are known-constant values of operations.
Definition: Attributes.h:25
This class is a general helper class for creating context-global objects like types,...
Definition: Builders.h:50
StringAttr getStringAttr(const Twine &bytes)
Definition: Builders.cpp:302
An interface to be implemented by dialects that can have identifiers in the data layout specification...
static DataLayoutEntryInterface defaultCombine(DataLayoutEntryInterface outer, DataLayoutEntryInterface inner)
Default implementation of entry combination that combines identical entries and returns null otherwis...
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:38
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:314
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:66
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:207
StringAttr getName() const
Return the name of the attribute.
Definition: Attributes.cpp:49
Attribute getValue() const
Return the value of the attribute.
Definition: Attributes.h:221
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition: Operation.h:234
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this operation.
Definition: Operation.h:507
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:268
This class implements Optional functionality for ParseResult.
Definition: OpDefinition.h:39
ParseResult value() const
Access the internal ParseResult value.
Definition: OpDefinition.h:52
bool has_value() const
Returns true if we contain a valid ParseResult value.
Definition: OpDefinition.h:49
This is a utility allocator used to allocate memory for instances of derived types.
T * allocate()
Allocate an instance of the provided type.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
Dialect & getDialect() const
Get the dialect this type is registered to.
Definition: Types.h:123
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition: Types.cpp:35
DataLayoutEntryAttrStorage(DataLayoutEntryKey entryKey, Attribute value)
Definition: DLTI.cpp:169
bool operator==(const KeyTy &other) const
Definition: DLTI.cpp:178
std::pair< DataLayoutEntryKey, Attribute > KeyTy
Definition: DLTI.cpp:167
static DataLayoutEntryAttrStorage * construct(AttributeStorageAllocator &allocator, const KeyTy &key)
Definition: DLTI.cpp:173
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:344
LogicalResult verifyDataLayoutOp(Operation *op)
Verifies that the operation implementing the data layout interface, or a module operation,...
FailureOr< Attribute > query(Operation *op, ArrayRef< DataLayoutEntryKey > keys, bool emitError=false)
Perform a DLTI-query at op, recursively querying each key of keys on query interface-implementing att...
Definition: DLTI.cpp:510
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Definition: Query.cpp:20
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:426