14 #ifndef MLIR_BYTECODE_BYTECODEIMPLEMENTATION_H
15 #define MLIR_BYTECODE_BYTECODEIMPLEMENTATION_H
23 #include "llvm/ADT/STLExtras.h"
24 #include "llvm/ADT/Twine.h"
68 template <
typename T,
typename CallbackFn>
75 for (uint64_t i = 0; i < size; ++i) {
78 if constexpr (llvm::function_traits<std::decay_t<CallbackFn>>::num_args) {
80 if (
failed(callback(element)))
82 result.emplace_back(std::move(element));
87 result.emplace_back(std::move(*element));
103 template <
typename T>
107 template <
typename T>
112 if ((result = dyn_cast<T>(baseResult)))
114 return emitError() <<
"expected " << llvm::getTypeName<T>()
115 <<
", but got: " << baseResult;
117 template <
typename T>
124 if ((result = dyn_cast<T>(baseResult)))
126 return emitError() <<
"expected " << llvm::getTypeName<T>()
127 <<
", but got: " << baseResult;
132 template <
typename T>
136 template <
typename T>
141 if ((result = dyn_cast<T>(baseResult)))
143 return emitError() <<
"expected " << llvm::getTypeName<T>()
144 <<
", but got: " << baseResult;
148 template <
typename ResourceT>
153 if (
auto *result = dyn_cast<ResourceT>(&*handle))
154 return std::move(*result);
155 return emitError() <<
"provided resource handle differs from the "
156 "expected resource type";
189 template <
typename T>
191 static_assert(
sizeof(T) <
sizeof(uint64_t),
"expect integer < 64 bits");
192 static_assert(std::is_integral<T>::value,
"expects integer");
193 uint64_t nonZeroesCount;
194 bool useSparseEncoding;
197 if (nonZeroesCount == 0)
199 if (!useSparseEncoding) {
201 if (nonZeroesCount > array.size()) {
203 << nonZeroesCount <<
" but only " << array.size()
204 <<
" storage available.";
207 for (int64_t index : llvm::seq<int64_t>(0, nonZeroesCount)) {
211 array[index] = value;
217 uint64_t indexBitSize;
220 constexpr uint64_t maxIndexBitSize = 8;
221 if (indexBitSize > maxIndexBitSize) {
222 emitError(
"reading sparse array with indexing above 8 bits: ")
226 for (uint32_t count : llvm::seq<uint32_t>(0, nonZeroesCount)) {
228 uint64_t indexValuePair;
231 uint64_t index = indexValuePair & ~(uint64_t(-1) << (indexBitSize));
232 uint64_t value = indexValuePair >> indexBitSize;
233 if (index >= array.size()) {
234 emitError(
"reading a sparse array found index ")
235 << index <<
" but only " << array.size() <<
" storage available.";
238 array[index] = value;
284 template <
typename RangeT,
typename CallbackFn>
287 for (
auto &element : range)
294 template <
typename T>
301 template <
typename T>
336 template <
typename T>
338 static_assert(
sizeof(T) <
sizeof(uint64_t),
"expect integer < 64 bits");
339 static_assert(std::is_integral<T>::value,
"expects integer");
340 uint32_t size = array.size();
341 uint32_t nonZeroesCount = 0, lastIndex = 0;
342 for (uint32_t index : llvm::seq<uint32_t>(0, size)) {
350 if (lastIndex > 256 || nonZeroesCount > size / 2) {
353 for (
const T &elt : array)
360 if (nonZeroesCount == 0)
363 int indexBitSize = llvm::Log2_32_Ceil(lastIndex + 1);
365 for (uint32_t index : llvm::seq<uint32_t>(0, lastIndex + 1)) {
366 T value = array[index];
369 uint64_t indexValuePair = (value << indexBitSize) | (index);
422 reader.
emitError() <<
"dialect " << getDialect()->getNamespace()
423 <<
" does not support reading attributes from bytecode";
431 reader.
emitError() <<
"dialect " << getDialect()->getNamespace()
432 <<
" does not support reading types from bytecode";
463 virtual std::unique_ptr<DialectVersion>
465 reader.
emitError(
"Dialect does not support versioning");
481 template <
typename T,
typename... Ts>
487 if (
auto *result = dyn_cast<T>(&*handle)) {
488 value = std::move(*result);
496 template <
typename T,
typename... Ts>
499 if constexpr (llvm::is_detected<detail::has_get_method, T, Ts...>::value) {
501 return T::get(std::forward<Ts>(params)...);
504 return T::get(context, std::forward<Ts>(params)...);
507 return T::Base::get(context, std::forward<Ts>(params)...);
This class represents an opaque handle to a dialect resource entry.
Attributes are known-constant values of operations.
virtual Type readType(DialectBytecodeReader &reader) const
Read a type belonging to this dialect from the given reader.
virtual LogicalResult upgradeFromVersion(Operation *topLevelOp, const DialectVersion &version) const
Hook invoked after parsing completed, if a version directive was present and included an entry for th...
virtual Attribute readAttribute(DialectBytecodeReader &reader) const
Read an attribute belonging to this dialect from the given reader.
virtual std::unique_ptr< DialectVersion > readVersion(DialectBytecodeReader &reader) const
virtual LogicalResult writeAttribute(Attribute attr, DialectBytecodeWriter &writer) const
Write the given attribute, which belongs to this dialect, to the given writer.
virtual LogicalResult writeType(Type type, DialectBytecodeWriter &writer) const
Write the given type, which belongs to this dialect, to the given writer.
virtual void writeVersion(DialectBytecodeWriter &writer) const
Write the version of this dialect to the given writer.
This class defines a virtual interface for reading a bytecode stream, providing hooks into the byteco...
virtual ~DialectBytecodeReader()=default
virtual LogicalResult readBlob(ArrayRef< char > &result)=0
Read a blob from the bytecode.
LogicalResult readAttributes(SmallVectorImpl< T > &attrs)
FailureOr< ResourceT > readResourceHandle()
Read a handle to a dialect resource.
virtual MLIRContext * getContext() const =0
Retrieve the context associated to the reader.
virtual FailureOr< APInt > readAPIntWithKnownWidth(unsigned bitWidth)=0
Read an APInt that is known to have been encoded with the given width.
LogicalResult readTypes(SmallVectorImpl< T > &types)
virtual LogicalResult readBool(bool &result)=0
Read a bool from the bytecode.
virtual LogicalResult readVarInt(uint64_t &result)=0
Read a variable width integer.
virtual LogicalResult readType(Type &result)=0
Read a reference to the given type.
virtual uint64_t getBytecodeVersion() const =0
Return the bytecode version being read.
LogicalResult readType(T &result)
LogicalResult readVarIntWithFlag(uint64_t &result, bool &flag)
Parse a variable length encoded integer whose low bit is used to encode an unrelated flag,...
LogicalResult readSignedVarInts(SmallVectorImpl< int64_t > &result)
LogicalResult readOptionalAttribute(T &result)
virtual LogicalResult readOptionalAttribute(Attribute &attr)=0
Read an optional reference to the given attribute.
LogicalResult readAttribute(T &result)
virtual InFlightDiagnostic emitError(const Twine &msg={}) const =0
Emit an error to the reader.
LogicalResult readSparseArray(MutableArrayRef< T > array)
Read a "small" sparse array of integer <= 32 bits elements, where index/value pairs can be compressed...
virtual FailureOr< APFloat > readAPFloatWithKnownSemantics(const llvm::fltSemantics &semantics)=0
Read an APFloat that is known to have been encoded with the given semantics.
virtual FailureOr< const DialectVersion * > getDialectVersion(StringRef dialectName) const =0
Retrieve the dialect version by name if available.
virtual LogicalResult readString(StringRef &result)=0
Read a string from the bytecode.
virtual LogicalResult readSignedVarInt(int64_t &result)=0
Read a signed variable width integer.
LogicalResult readList(SmallVectorImpl< T > &result, CallbackFn &&callback)
Read out a list of elements, invoking the provided callback for each element.
virtual LogicalResult readAttribute(Attribute &result)=0
Read a reference to the given attribute.
This class defines a virtual interface for writing to a bytecode stream, providing hooks into the byt...
virtual void writeOptionalAttribute(Attribute attr)=0
virtual void writeVarInt(uint64_t value)=0
Write a variable width integer to the output stream.
void writeVarIntWithFlag(uint64_t value, bool flag)
Write a VarInt and a flag packed together.
void writeList(RangeT &&range, CallbackFn &&callback)
Write out a list of elements, invoking the provided callback for each element.
void writeSparseArray(ArrayRef< T > array)
Write out a "small" sparse array of integer <= 32 bits elements, where index/value pairs can be compr...
virtual void writeType(Type type)=0
Write a reference to the given type.
virtual void writeAPIntWithKnownWidth(const APInt &value)=0
Write an APInt to the bytecode stream whose bitwidth will be known externally at read time.
virtual void writeOwnedBlob(ArrayRef< char > blob)=0
Write a blob to the bytecode, which is owned by the caller and is guaranteed to not die before the en...
virtual void writeAttribute(Attribute attr)=0
Write a reference to the given attribute.
virtual ~DialectBytecodeWriter()=default
void writeAttributes(ArrayRef< T > attrs)
virtual void writeSignedVarInt(int64_t value)=0
Write a signed variable width integer to the output stream.
virtual void writeResourceHandle(const AsmDialectResourceHandle &resource)=0
Write the given handle to a dialect resource.
virtual void writeAPFloatWithKnownSemantics(const APFloat &value)=0
Write an APFloat to the bytecode stream whose semantics will be known externally at read time.
void writeSignedVarInts(ArrayRef< int64_t > value)
virtual void writeOwnedBool(bool value)=0
Write a bool to the output stream.
virtual int64_t getBytecodeVersion() const =0
Return the bytecode version being emitted for.
virtual void writeOwnedString(StringRef str)=0
Write a string to the bytecode, which is owned by the caller and is guaranteed to not die before the ...
void writeTypes(ArrayRef< T > types)
This class is used to represent the version of a dialect, for the purpose of polymorphic destruction.
virtual ~DialectVersion()=default
This class provides support for representing a failure result, or a valid value of type T.
This class represents a diagnostic that is inflight and set to be reported.
MLIRContext is the top-level object for a collection of MLIR operations.
Operation is the basic unit of execution within MLIR.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
The base class used for all derived interface types.
decltype(T::get(std::declval< Ts >()...)) has_get_method
This header declares functions that assist transformations in the MemRef dialect.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
static LogicalResult readResourceHandle(DialectBytecodeReader &reader, FailureOr< T > &value, Ts &&...params)
Helper for resource handle reading that returns LogicalResult.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
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.