16 #include "llvm/ADT/TypeSwitch.h"
18 #include "llvm/ADT/TypeSwitch.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/MathExtras.h"
24 #include "mlir/Dialect/DLTI/DLTIDialect.cpp.inc"
26 #define GET_ATTRDEF_CLASSES
27 #include "mlir/Dialect/DLTI/DLTIAttrs.cpp.inc"
29 #define DEBUG_TYPE "dlti"
38 using KeyTy = std::pair<DataLayoutEntryKey, Attribute>;
60 return Base::get(key.getContext(), key, value);
68 return getImpl()->entryKey;
71 Attribute DataLayoutEntryAttr::getValue()
const {
return getImpl()->value; }
80 std::string identifier;
88 parser.
emitError(idLoc) <<
"expected a type or a quoted string";
98 return type ?
get(type, value)
99 :
get(parser.getBuilder().getStringAttr(identifier), value);
104 if (
auto type = llvm::dyn_cast_if_present<Type>(getKey()))
107 os <<
"\"" << getKey().get<StringAttr>().strref() <<
"\"";
108 os <<
", " << getValue() <<
">";
120 for (DataLayoutEntryInterface entry : entries) {
121 if (
auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
122 if (!types.insert(type).second)
123 return emitError() <<
"repeated layout entry key: " << type;
125 auto id = entry.getKey().get<StringAttr>();
126 if (!ids.insert(
id).second)
127 return emitError() <<
"repeated layout entry key: " <<
id.getValue();
139 unsigned oldEntriesSize = oldEntries.size();
140 for (DataLayoutEntryInterface entry : newEntries) {
145 bool replaced =
false;
146 for (
unsigned i = 0; i < oldEntriesSize; ++i) {
147 if (oldEntries[i].getKey() == entry.getKey()) {
148 oldEntries[i] = entry;
154 oldEntries.push_back(entry);
171 spec.bucketEntriesByType(newEntriesForType, newEntriesForID);
174 for (
auto &kvp : newEntriesForType) {
175 if (!entriesForType.count(kvp.first)) {
176 entriesForType[kvp.first] = std::move(kvp.second);
180 Type typeSample = kvp.second.front().getKey().get<
Type>();
183 "unexpected data layout entry for built-in type");
185 auto interface = llvm::cast<DataLayoutTypeInterface>(typeSample);
186 if (!interface.areCompatible(entriesForType.lookup(kvp.first), kvp.second))
192 for (
const auto &kvp : newEntriesForID) {
193 StringAttr
id = kvp.second.getKey().get<StringAttr>();
194 Dialect *dialect =
id.getReferencedDialect();
195 if (!entriesForID.count(
id)) {
196 entriesForID[id] = kvp.second;
204 dialect ? cast<DataLayoutDialectInterface>(dialect)->combine(
205 entriesForID[
id], kvp.second)
208 if (!entriesForID[
id])
219 if (llvm::any_of(specs, [](DataLayoutSpecInterface spec) {
220 return !llvm::isa<DataLayoutSpecAttr>(spec);
227 for (DataLayoutSpecInterface spec : specs)
235 llvm::append_range(entries, llvm::make_second_range(entriesForID));
236 for (
const auto &kvp : entriesForType)
237 llvm::append_range(entries, kvp.getSecond());
243 DataLayoutSpecAttr::getEndiannessIdentifier(
MLIRContext *context)
const {
248 DataLayoutSpecAttr::getAllocaMemorySpaceIdentifier(
MLIRContext *context)
const {
250 DLTIDialect::kDataLayoutAllocaMemorySpaceKey);
253 StringAttr DataLayoutSpecAttr::getProgramMemorySpaceIdentifier(
256 DLTIDialect::kDataLayoutProgramMemorySpaceKey);
260 DataLayoutSpecAttr::getGlobalMemorySpaceIdentifier(
MLIRContext *context)
const {
262 DLTIDialect::kDataLayoutGlobalMemorySpaceKey);
266 DataLayoutSpecAttr::getStackAlignmentIdentifier(
MLIRContext *context)
const {
268 DLTIDialect::kDataLayoutStackAlignmentKey);
285 [&]() { return parser.parseAttribute(entries.emplace_back()); }) ||
295 llvm::interleaveComma(getEntries(), os);
309 std::string deviceID;
313 <<
"DeviceID is missing, or is not of string type";
322 auto target_device_spec =
324 if (failed(target_device_spec)) {
326 <<
"Error in parsing target device spec";
331 *target_device_spec);
337 return printer << param.first <<
" : " << param.second;
349 for (DataLayoutEntryInterface entry : entries) {
350 if (
auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
352 <<
"dlti.target_device_spec does not allow type as a key: "
356 auto id = entry.getKey().get<StringAttr>();
357 if (!ids.insert(
id).second)
358 return emitError() <<
"repeated layout entry key: " <<
id.getValue();
374 for (
const auto &entry : entries) {
375 TargetDeviceSpecInterface target_device_spec = entry.second;
379 target_device_spec.getEntries())))
383 TargetSystemSpecInterface::DeviceID device_id = entry.first;
384 if (!device_ids.insert(device_id).second) {
385 return emitError() <<
"repeated Device ID in dlti.target_system_spec: "
396 constexpr
const StringLiteral mlir::DLTIDialect::kDataLayoutAttrName;
397 constexpr
const StringLiteral mlir::DLTIDialect::kDataLayoutEndiannessKey;
398 constexpr
const StringLiteral mlir::DLTIDialect::kDataLayoutEndiannessBig;
399 constexpr
const StringLiteral mlir::DLTIDialect::kDataLayoutEndiannessLittle;
406 LogicalResult verifyEntry(DataLayoutEntryInterface entry,
408 StringRef entryName = entry.getKey().get<StringAttr>().strref();
409 if (entryName == DLTIDialect::kDataLayoutEndiannessKey) {
410 auto value = llvm::dyn_cast<StringAttr>(entry.getValue());
412 (value.getValue() == DLTIDialect::kDataLayoutEndiannessBig ||
413 value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle))
415 return emitError(loc) <<
"'" << entryName
416 <<
"' data layout entry is expected to be either '"
417 << DLTIDialect::kDataLayoutEndiannessBig <<
"' or '"
418 << DLTIDialect::kDataLayoutEndiannessLittle <<
"'";
420 if (entryName == DLTIDialect::kDataLayoutAllocaMemorySpaceKey ||
421 entryName == DLTIDialect::kDataLayoutProgramMemorySpaceKey ||
422 entryName == DLTIDialect::kDataLayoutGlobalMemorySpaceKey ||
423 entryName == DLTIDialect::kDataLayoutStackAlignmentKey)
425 return emitError(loc) <<
"unknown data layout entry name: " << entryName;
430 void DLTIDialect::initialize() {
432 #define GET_ATTRDEF_LIST
433 #include "mlir/Dialect/DLTI/DLTIAttrs.cpp.inc"
435 addInterfaces<TargetDataLayoutInterface>();
438 LogicalResult DLTIDialect::verifyOperationAttribute(
Operation *op,
440 if (attr.
getName() == DLTIDialect::kDataLayoutAttrName) {
441 if (!llvm::isa<DataLayoutSpecAttr>(attr.
getValue())) {
442 return op->
emitError() <<
"'" << DLTIDialect::kDataLayoutAttrName
443 <<
"' is expected to be a #dlti.dl_spec attribute";
445 if (isa<ModuleOp>(op))
448 }
else if (attr.
getName() == DLTIDialect::kTargetSystemDescAttrName) {
449 if (!llvm::isa<TargetSystemSpecAttr>(attr.
getValue())) {
451 <<
"'" << DLTIDialect::kTargetSystemDescAttrName
452 <<
"' is expected to be a #dlti.target_system_spec attribute";
458 <<
"' not supported by dialect";
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,...
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...
static MLIRContext * getContext(OpFoldResult val)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
This base class exposes generic asm parser hooks, usable across the various derived parsers.
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 Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
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.
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseOptionalGreater()=0
Parse a '>' token if present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseColon()=0
Parse a : token.
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.
This class is a general helper class for creating context-global objects like types,...
StringAttr getStringAttr(const Twine &bytes)
An interface to be implemented by dialects that can have identifiers in the data layout specification...
DataLayoutDialectInterface(Dialect *dialect)
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...
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...
MLIRContext is the top-level object for a collection of MLIR operations.
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
NamedAttribute represents a combination of a name and an Attribute value.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
Operation is the basic unit of execution within MLIR.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
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.
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...
Dialect & getDialect() const
Get the dialect this type is registered to.
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
DataLayoutEntryKey entryKey
DataLayoutEntryAttrStorage(DataLayoutEntryKey entryKey, Attribute value)
bool operator==(const KeyTy &other) const
std::pair< DataLayoutEntryKey, Attribute > KeyTy
static DataLayoutEntryAttrStorage * construct(AttributeStorageAllocator &allocator, const KeyTy &key)
LogicalResult verifyDataLayoutOp(Operation *op)
Verifies that the operation implementing the data layout interface, or a module operation,...
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
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...
std::pair< StringAttr, TargetDeviceSpecInterface > DeviceIDTargetDeviceSpecPair
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
static FailureOr< DeviceIDTargetDeviceSpecPair > parse(AsmParser &parser)
Provide a template class that can be specialized by users to dispatch to parsers.