15 #include "llvm/ADT/TypeSwitch.h"
19 #include "mlir/Dialect/DLTI/DLTIDialect.cpp.inc"
31 using KeyTy = std::pair<DataLayoutEntryKey, Attribute>;
53 return Base::get(key.getContext(), key, value);
73 std::string identifier;
81 parser.
emitError(idLoc) <<
"expected a type or a quoted string";
91 return type ?
get(type, value)
97 if (
auto type = llvm::dyn_cast_if_present<Type>(
getKey()))
100 os <<
"\"" <<
getKey().get<StringAttr>().strref() <<
"\"";
109 constexpr
const StringLiteral
110 mlir::DLTIDialect::kDataLayoutAllocaMemorySpaceKey;
111 constexpr
const StringLiteral
112 mlir::DLTIDialect::kDataLayoutProgramMemorySpaceKey;
113 constexpr
const StringLiteral
114 mlir::DLTIDialect::kDataLayoutGlobalMemorySpaceKey;
116 constexpr
const StringLiteral mlir::DLTIDialect::kDataLayoutStackAlignmentKey;
150 return Base::getChecked(
emitError, context, entries);
158 for (DataLayoutEntryInterface entry : entries) {
159 if (
auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
160 if (!types.insert(type).second)
161 return emitError() <<
"repeated layout entry key: " << type;
163 auto id = entry.getKey().get<StringAttr>();
164 if (!ids.insert(
id).second)
165 return emitError() <<
"repeated layout entry key: " <<
id.getValue();
177 unsigned oldEntriesSize = oldEntries.size();
178 for (DataLayoutEntryInterface entry : newEntries) {
183 bool replaced =
false;
184 for (
unsigned i = 0; i < oldEntriesSize; ++i) {
185 if (oldEntries[i].getKey() == entry.getKey()) {
186 oldEntries[i] = entry;
192 oldEntries.push_back(entry);
209 spec.bucketEntriesByType(newEntriesForType, newEntriesForID);
212 for (
auto &kvp : newEntriesForType) {
213 if (!entriesForType.count(kvp.first)) {
214 entriesForType[kvp.first] = std::move(kvp.second);
218 Type typeSample = kvp.second.front().getKey().get<
Type>();
221 "unexpected data layout entry for built-in type");
223 auto interface = llvm::cast<DataLayoutTypeInterface>(typeSample);
224 if (!interface.areCompatible(entriesForType.lookup(kvp.first), kvp.second))
230 for (
const auto &kvp : newEntriesForID) {
231 StringAttr
id = kvp.second.getKey().get<StringAttr>();
232 Dialect *dialect =
id.getReferencedDialect();
233 if (!entriesForID.count(
id)) {
234 entriesForID[id] = kvp.second;
242 dialect ? cast<DataLayoutDialectInterface>(dialect)->combine(
243 entriesForID[
id], kvp.second)
246 if (!entriesForID[
id])
257 if (llvm::any_of(specs, [](DataLayoutSpecInterface spec) {
258 return !llvm::isa<DataLayoutSpecAttr>(spec);
265 for (DataLayoutSpecInterface spec : specs)
273 llvm::append_range(entries, llvm::make_second_range(entriesForID));
274 for (
const auto &kvp : entriesForType)
275 llvm::append_range(entries, kvp.getSecond());
292 DLTIDialect::kDataLayoutAllocaMemorySpaceKey);
298 DLTIDialect::kDataLayoutProgramMemorySpaceKey);
304 DLTIDialect::kDataLayoutGlobalMemorySpaceKey);
309 DLTIDialect::kDataLayoutStackAlignmentKey);
326 [&]() { return parser.parseAttribute(entries.emplace_back()); }) ||
344 constexpr
const StringLiteral mlir::DLTIDialect::kDataLayoutAttrName;
345 constexpr
const StringLiteral mlir::DLTIDialect::kDataLayoutEndiannessKey;
346 constexpr
const StringLiteral mlir::DLTIDialect::kDataLayoutEndiannessBig;
347 constexpr
const StringLiteral mlir::DLTIDialect::kDataLayoutEndiannessLittle;
356 StringRef entryName = entry.getKey().get<StringAttr>().strref();
357 if (entryName == DLTIDialect::kDataLayoutEndiannessKey) {
358 auto value = llvm::dyn_cast<StringAttr>(entry.getValue());
360 (value.getValue() == DLTIDialect::kDataLayoutEndiannessBig ||
361 value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle))
363 return emitError(loc) <<
"'" << entryName
364 <<
"' data layout entry is expected to be either '"
365 << DLTIDialect::kDataLayoutEndiannessBig <<
"' or '"
366 << DLTIDialect::kDataLayoutEndiannessLittle <<
"'";
368 if (entryName == DLTIDialect::kDataLayoutAllocaMemorySpaceKey ||
369 entryName == DLTIDialect::kDataLayoutProgramMemorySpaceKey ||
370 entryName == DLTIDialect::kDataLayoutGlobalMemorySpaceKey ||
371 entryName == DLTIDialect::kDataLayoutStackAlignmentKey)
373 return emitError(loc) <<
"unknown data layout entry name: " << entryName;
378 void DLTIDialect::initialize() {
379 addAttributes<DataLayoutEntryAttr, DataLayoutSpecAttr>();
380 addInterfaces<TargetDataLayoutInterface>();
402 [&](
auto a) { a.print(os); })
403 .Default([](
Attribute) { llvm_unreachable(
"unknown attribute kind"); });
408 if (attr.
getName() == DLTIDialect::kDataLayoutAttrName) {
409 if (!llvm::isa<DataLayoutSpecAttr>(attr.
getValue())) {
410 return op->
emitError() <<
"'" << DLTIDialect::kDataLayoutAttrName
411 <<
"' is expected to be a #dlti.dl_spec attribute";
413 if (isa<ModuleOp>(op))
419 <<
"' 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)
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.
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 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.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
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...
A data layout entry attribute is a key-value pair where the key is a type or an identifier and the va...
static DataLayoutEntryAttr parse(AsmParser &parser)
Parses an instance of this attribute.
void print(AsmPrinter &os) const
Prints this attribute.
constexpr static const llvm::StringLiteral kAttrKeyword
The keyword used for this attribute in custom syntax.
DataLayoutEntryKey getKey() const
Returns the key of this entry.
Attribute getValue() const
Returns the value of this entry.
static DataLayoutEntryAttr get(StringAttr key, Attribute value)
Returns the entry with the given key and value.
A data layout specification is a list of entries that specify (partial) data layout information.
static DataLayoutSpecAttr get(MLIRContext *ctx, ArrayRef< DataLayoutEntryInterface > entries)
Returns the specification containing the given list of keys.
StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const
Returns the program memory space identifier.
StringAttr getGlobalMemorySpaceIdentifier(MLIRContext *context) const
Returns the global memory space identifier.
void print(AsmPrinter &os) const
Prints this attribute.
StringAttr getStackAlignmentIdentifier(MLIRContext *context) const
Returns the stack alignment identifier.
StringAttr getEndiannessIdentifier(MLIRContext *context) const
Returns the endiannes identifier.
static LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, ArrayRef< DataLayoutEntryInterface > entries)
Checks that the given list of entries does not contain duplicate keys.
static DataLayoutSpecAttr parse(AsmParser &parser)
Parses an instance of this attribute.
static DataLayoutSpecAttr getChecked(function_ref< InFlightDiagnostic()> emitError, MLIRContext *context, ArrayRef< DataLayoutEntryInterface > entries)
Returns the specification containing the given list of keys.
StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const
Returns the alloca memory space identifier.
constexpr static const StringLiteral kAttrKeyword
The keyword used for this attribute in custom syntax.
DataLayoutEntryListRef getEntries() const
Returns the list of entries.
DataLayoutSpecAttr combineWith(ArrayRef< DataLayoutSpecInterface > specs) const
Combines this specification with specs, enclosing specifications listed from outermost to innermost.
The DialectAsmParser has methods for interacting with the asm parser when parsing attributes and type...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
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.
ArrayRef< T > copyInto(ArrayRef< T > elements)
Copy the specified array of elements into memory managed by our bump pointer allocator.
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.
ImplType * getImpl() const
Utility for easy access to the storage instance.
std::pair< DataLayoutEntryKey, Attribute > KeyTy
DataLayoutEntryKey entryKey
static DataLayoutEntryStorage * construct(AttributeStorageAllocator &allocator, const KeyTy &key)
DataLayoutEntryStorage(DataLayoutEntryKey entryKey, Attribute value)
bool operator==(const KeyTy &other) const
DataLayoutSpecStorage(ArrayRef< DataLayoutEntryInterface > entries)
ArrayRef< DataLayoutEntryInterface > entries
bool operator==(const KeyTy &key) const
static DataLayoutSpecStorage * construct(AttributeStorageAllocator &allocator, const KeyTy &key)
LogicalResult verifyDataLayoutOp(Operation *op)
Verifies that the operation implementing the data layout interface, or a module operation,...
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Attribute parseAttribute(llvm::StringRef attrStr, MLIRContext *context, Type type={}, size_t *numRead=nullptr, bool isKnownNullTerminated=false)
This parses a single MLIR attribute to an MLIR context if it was valid.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
This class represents an efficient way to signal success or failure.