14#ifndef MLIR_BYTECODE_BYTECODEIMPLEMENTATION_H
15#define MLIR_BYTECODE_BYTECODEIMPLEMENTATION_H
22#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/Twine.h"
57 virtual FailureOr<const DialectVersion *>
74 template <
typename T,
typename CallbackFn>
81 for (uint64_t i = 0; i < size; ++i) {
84 if constexpr (llvm::function_traits<std::decay_t<CallbackFn>>::num_args) {
86 if (failed(callback(element)))
88 result.emplace_back(std::move(element));
90 FailureOr<T> element = callback();
93 result.emplace_back(std::move(*element));
109 template <
typename T>
113 template <
typename T>
118 if ((
result = dyn_cast<T>(baseResult)))
120 return emitError() <<
"expected " << llvm::getTypeName<T>()
121 <<
", but got: " << baseResult;
123 template <
typename T>
130 if ((
result = dyn_cast<T>(baseResult)))
132 return emitError() <<
"expected " << llvm::getTypeName<T>()
133 <<
", but got: " << baseResult;
138 template <
typename T>
142 template <
typename T>
147 if ((
result = dyn_cast<T>(baseResult)))
149 return emitError() <<
"expected " << llvm::getTypeName<T>()
150 <<
", but got: " << baseResult;
154 template <
typename ResourceT>
159 if (
auto *
result = dyn_cast<ResourceT>(&*handle))
160 return std::move(*
result);
161 return emitError() <<
"provided resource handle differs from the "
162 "expected resource type";
195 template <
typename T>
197 static_assert(
sizeof(T) <
sizeof(uint64_t),
"expect integer < 64 bits");
198 static_assert(std::is_integral<T>::value,
"expects integer");
199 uint64_t nonZeroesCount;
200 bool useSparseEncoding;
203 if (nonZeroesCount == 0)
205 if (!useSparseEncoding) {
207 if (nonZeroesCount > array.size()) {
209 << nonZeroesCount <<
" but only " << array.size()
210 <<
" storage available.";
213 for (
int64_t index : llvm::seq<int64_t>(0, nonZeroesCount)) {
217 array[
index] = value;
223 uint64_t indexBitSize;
226 constexpr uint64_t maxIndexBitSize = 8;
227 if (indexBitSize > maxIndexBitSize) {
228 emitError(
"reading sparse array with indexing above 8 bits: ")
232 for (uint32_t count : llvm::seq<uint32_t>(0, nonZeroesCount)) {
234 uint64_t indexValuePair;
237 uint64_t
index = indexValuePair & ~(uint64_t(-1) << (indexBitSize));
238 uint64_t value = indexValuePair >> indexBitSize;
239 if (
index >= array.size()) {
240 emitError(
"reading a sparse array found index ")
241 <<
index <<
" but only " << array.size() <<
" storage available.";
244 array[
index] = value;
254 virtual FailureOr<APFloat>
290 template <
typename RangeT,
typename CallbackFn>
293 for (
auto &element : range)
300 template <
typename T>
307 template <
typename T>
342 template <
typename T>
344 static_assert(
sizeof(T) <
sizeof(uint64_t),
"expect integer < 64 bits");
345 static_assert(std::is_integral<T>::value,
"expects integer");
346 uint32_t size = array.size();
347 uint32_t nonZeroesCount = 0, lastIndex = 0;
348 for (uint32_t
index : llvm::seq<uint32_t>(0, size)) {
356 if (lastIndex > 256 || nonZeroesCount > size / 2) {
359 for (
const T &elt : array)
366 if (nonZeroesCount == 0)
369 int indexBitSize = llvm::Log2_32_Ceil(lastIndex + 1);
371 for (uint32_t
index : llvm::seq<uint32_t>(0, lastIndex + 1)) {
372 T value = array[
index];
375 uint64_t indexValuePair = (value << indexBitSize) | (
index);
415 virtual FailureOr<const DialectVersion *>
442 <<
" does not support reading attributes from bytecode";
451 <<
" does not support reading types from bytecode";
482 virtual std::unique_ptr<DialectVersion>
484 reader.
emitError(
"Dialect does not support versioning");
492 virtual LogicalResult
500template <
typename T,
typename... Ts>
502 FailureOr<T> &value, Ts &&...params) {
506 if (
auto *
result = dyn_cast<T>(&*handle)) {
507 value = std::move(*
result);
515template <
typename T,
typename... Ts>
520 return T::get(std::forward<Ts>(params)...);
523 return T::get(context, std::forward<Ts>(params)...);
526 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 std::unique_ptr< DialectVersion > readVersion(DialectBytecodeReader &reader) const
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 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)
virtual MLIRContext * getContext() const =0
Retrieve the context associated to the reader.
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 FailureOr< const DialectVersion * > getDialectVersion(StringRef dialectName) const =0
Retrieve the dialect version by name if available.
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,...
virtual FailureOr< APInt > readAPIntWithKnownWidth(unsigned bitWidth)=0
Read an APInt that is known to have been encoded with the given width.
LogicalResult readSignedVarInts(SmallVectorImpl< int64_t > &result)
LogicalResult readOptionalAttribute(T &result)
virtual InFlightDiagnostic emitWarning(const Twine &msg={}) const =0
Emit a warning to the reader.
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...
FailureOr< ResourceT > readResourceHandle()
Read a handle to a dialect resource.
virtual LogicalResult readString(StringRef &result)=0
Read a string from the bytecode.
FailureOr< const DialectVersion * > getDialectVersion() const
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.
virtual FailureOr< APFloat > readAPFloatWithKnownSemantics(const llvm::fltSemantics &semantics)=0
Read an APFloat that is known to have been encoded with the given semantics.
This class defines a virtual interface for writing to a bytecode stream, providing hooks into the byt...
virtual FailureOr< const DialectVersion * > getDialectVersion(StringRef dialectName) const =0
Retrieve the dialect version by name if available.
virtual void writeOptionalAttribute(Attribute attr)=0
FailureOr< const DialectVersion * > getDialectVersion() const
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 writeUnownedBlob(ArrayRef< char > blob)=0
Write a blob to the bytecode, which is not owned by the caller.
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)
Dialect * getDialect() const
Return the dialect that this interface represents.
detail::DialectInterfaceBase< ConcreteType, DialectInterface > Base
The base class used for all derived interface types.
This class is used to represent the version of a dialect, for the purpose of polymorphic destruction.
virtual ~DialectVersion()=default
StringRef getNamespace() const
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...
DialectInterfaceBase< ConcreteType, DialectInterface > Base
decltype(T::get(std::declval< Ts >()...)) has_get_method
Include the generated interface declarations.
static LogicalResult readResourceHandle(DialectBytecodeReader &reader, FailureOr< T > &value, Ts &&...params)
Helper for resource handle reading that returns LogicalResult.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...