MLIR 22.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"
13#include "mlir/IR/BuiltinOps.h"
15#include "mlir/IR/Dialect.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_CLASSES
26#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 a
35/// #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-attr
38static 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 within
81/// 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-list
85/// entry ::= ((type | quoted-string) `=` attr) | dl-entry-attr
86template <class Attr>
88 bool tryType = false,
89 bool allowEmpty = false) {
91 if (failed(parser.parseCommaSeparatedList(
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;
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.
136 bool allowTypes = true) {
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// DataLayoutEntryAttr
160//===----------------------------------------------------------------------===//
161namespace mlir {
162namespace detail {
164public:
165 using KeyTy = std::pair<DataLayoutEntryKey, Attribute>;
166
169
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
182};
183} // namespace detail
184} // namespace mlir
185
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// DLTIMapAttr
236//===----------------------------------------------------------------------===//
237
238/// Parses an attribute with syntax:
239/// map-attr ::= `#dlti.` `map` `<` entry-list `>`
240/// entry-list ::= entry | entry `,` entry-list
241/// entry ::= ((type | quoted-string) `=` attr) | dl-entry-attr
242Attribute 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,
253 return verifyEntries(emitError, entries);
254}
255
256//===----------------------------------------------------------------------===//
257// DataLayoutSpecAttr
258//===----------------------------------------------------------------------===//
259
260LogicalResult
261DataLayoutSpecAttr::verify(function_ref<InFlightDiagnostic()> emitError,
263 return verifyEntries(emitError, entries);
264}
265
266/// Given a list of old and a list of new entries, overwrites old entries with
267/// new ones if they have matching keys, appends new entries to the old entry
268/// list otherwise.
269static void
272 unsigned oldEntriesSize = oldEntries.size();
273 for (DataLayoutEntryInterface entry : newEntries) {
274 // We expect a small (dozens) number of entries, so it is practically
275 // cheaper to iterate over the list linearly rather than to create an
276 // auxiliary hashmap to avoid duplication. Also note that we never need to
277 // 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 by
292/// type class and identifier, overwriting them if necessary. Fails to combine
293/// 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 the
307 // `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 the
317 // dialect is not loaded for some reason, use the default combinator
318 // that conservatively accepts identical entries only.
319 entriesForID[id] =
320 dialect ? cast<DataLayoutDialectInterface>(dialect)->combine(
321 entriesForID[id], kvp.second)
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 once
342 // 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
353DataLayoutSpecAttr
354DataLayoutSpecAttr::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.
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
380StringAttr
381DataLayoutSpecAttr::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
391StringAttr
392DataLayoutSpecAttr::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
403StringAttr
404DataLayoutSpecAttr::getGlobalMemorySpaceIdentifier(MLIRContext *context) const {
405 return Builder(context).getStringAttr(
406 DLTIDialect::kDataLayoutGlobalMemorySpaceKey);
407}
408
409StringAttr
410DataLayoutSpecAttr::getManglingModeIdentifier(MLIRContext *context) const {
411 return Builder(context).getStringAttr(
412 DLTIDialect::kDataLayoutManglingModeKey);
413}
414
415StringAttr
416DataLayoutSpecAttr::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
427StringAttr
428DataLayoutSpecAttr::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-list
436/// entry ::= ((type | quoted-string) = attr) | dl-entry-attr
437Attribute DataLayoutSpecAttr::parse(AsmParser &parser, Type type) {
439 /*tryType=*/true,
440 /*allowEmpty=*/true);
441}
442
443void DataLayoutSpecAttr::print(AsmPrinter &printer) const {
444 printAngleBracketedEntries(printer, getEntries());
445}
446
447//===----------------------------------------------------------------------===//
448// TargetDeviceSpecAttr
449//===----------------------------------------------------------------------===//
450
451LogicalResult
452TargetDeviceSpecAttr::verify(function_ref<InFlightDiagnostic()> emitError,
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-list
460/// entry ::= (quoted-string `=` attr) | dl-entry-attr
461Attribute TargetDeviceSpecAttr::parse(AsmParser &parser, Type type) {
463}
464
465void TargetDeviceSpecAttr::print(AsmPrinter &printer) const {
466 printAngleBracketedEntries(printer, getEntries());
467}
468
469//===----------------------------------------------------------------------===//
470// TargetSystemSpecAttr
471//===----------------------------------------------------------------------===//
472
473LogicalResult
474TargetSystemSpecAttr::verify(function_ref<InFlightDiagnostic()> emitError,
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 " << deviceId
491 << " 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-list
506/// entry ::= (quoted-string `=` dev-spec-attr) | dl-entry-attr
507Attribute TargetSystemSpecAttr::parse(AsmParser &parser, Type type) {
509}
510
511void TargetSystemSpecAttr::print(AsmPrinter &printer) const {
512 printAngleBracketedEntries(printer, getEntries());
513}
514
515//===----------------------------------------------------------------------===//
516// DLTIDialect
517//===----------------------------------------------------------------------===//
518
519/// Retrieve the first `DLTIQueryInterface`-implementing attribute that is
520/// attached to `op` or such an attr on as close as possible an ancestor. The
521/// op the attribute is attached to is returned as well.
522static std::pair<DLTIQueryInterface, Operation *>
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>
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();
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:
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) << "'" << entryName
624 << "' 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} // namespace
641
642void DLTIDialect::initialize() {
643 addAttributes<
644#define GET_ATTRDEF_LIST
645#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::kDataLayoutAttrName
655 << "' is expected to be a #dlti.dl_spec attribute";
656 }
657 if (isa<ModuleOp>(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::kTargetSystemDescAttrName
666 << "' 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::kMapAttrName
674 << "' 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}
return success()
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:134
static void printAngleBracketedEntries(AsmPrinter &os, T &&entries)
Pretty-print entries, each in key = value format, separated by commas.
Definition DLTI.cpp:121
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:523
static std::string keyToStr(DataLayoutEntryKey key)
Convert pointer-union keys to strings.
Definition DLTI.cpp:111
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:270
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:87
static LogicalResult combineOneSpec(DataLayoutSpecInterface spec, llvm::MapVector< TypeID, DataLayoutEntryList > &entriesForType, llvm::MapVector< StringAttr, DataLayoutEntryInterface > &entriesForID)
Combines a data layout spec into the given lists of entries organized by type class and identifier,...
Definition DLTI.cpp:294
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:38
b getContext())
static std::string diag(const llvm::Value &value)
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
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:51
StringAttr getStringAttr(const Twine &bytes)
Definition Builders.cpp:262
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.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
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:164
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
Definition Attributes.h:179
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this operation.
Definition Operation.h:512
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
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
MLIRContext * getContext()
Return the context this operation is associated with.
Definition Operation.h:216
This class implements Optional functionality for ParseResult.
ParseResult value() const
Access the internal ParseResult value.
bool has_value() const
Returns true if we contain a valid ParseResult value.
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:107
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition Types.cpp:35
static DataLayoutEntryAttrStorage * construct(AttributeStorageAllocator &allocator, const KeyTy &key)
Definition DLTI.cpp:171
DataLayoutEntryAttrStorage(DataLayoutEntryKey entryKey, Attribute value)
Definition DLTI.cpp:167
bool operator==(const KeyTy &other) const
Definition DLTI.cpp:176
std::pair< DataLayoutEntryKey, Attribute > KeyTy
Definition DLTI.cpp:165
AttrTypeReplacer.
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:537
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition Remarks.h:561
Include the generated interface declarations.
llvm::PointerUnion< Type, StringAttr > DataLayoutEntryKey
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
Definition LLVM.h:128
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
StorageUniquer::StorageAllocator AttributeStorageAllocator
llvm::TypeSwitch< T, ResultT > TypeSwitch
Definition LLVM.h:144
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
llvm::function_ref< Fn > function_ref
Definition LLVM.h:152