MLIR 23.0.0git
BytecodeImplementation.h
Go to the documentation of this file.
1//===- BytecodeImplementation.h - MLIR Bytecode Implementation --*- C++ -*-===//
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//
9// This header defines various interfaces and utilities necessary for dialects
10// to hook into bytecode serialization.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef MLIR_BYTECODE_BYTECODEIMPLEMENTATION_H
15#define MLIR_BYTECODE_BYTECODEIMPLEMENTATION_H
16
17#include "mlir/IR/Attributes.h"
18#include "mlir/IR/Diagnostics.h"
19#include "mlir/IR/Dialect.h"
22#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/Twine.h"
24
25namespace mlir {
26//===--------------------------------------------------------------------===//
27// Dialect Version Interface.
28//===--------------------------------------------------------------------===//
29
30/// This class is used to represent the version of a dialect, for the purpose
31/// of polymorphic destruction.
33public:
34 virtual ~DialectVersion() = default;
35};
36
37//===----------------------------------------------------------------------===//
38// DialectBytecodeReader
39//===----------------------------------------------------------------------===//
40
41/// This class defines a virtual interface for reading a bytecode stream,
42/// providing hooks into the bytecode reader. As such, this class should only be
43/// derived and defined by the main bytecode reader, users (i.e. dialects)
44/// should generally only interact with this class via the
45/// BytecodeDialectInterface below.
47public:
48 virtual ~DialectBytecodeReader() = default;
49
50 /// Emit an error to the reader.
51 virtual InFlightDiagnostic emitError(const Twine &msg = {}) const = 0;
52
53 /// Emit a warning to the reader.
54 virtual InFlightDiagnostic emitWarning(const Twine &msg = {}) const = 0;
55
56 /// Retrieve the dialect version by name if available.
57 virtual FailureOr<const DialectVersion *>
58 getDialectVersion(StringRef dialectName) const = 0;
59 template <class T>
60 FailureOr<const DialectVersion *> getDialectVersion() const {
61 return getDialectVersion(T::getDialectNamespace());
62 }
63
64 /// Retrieve the context associated to the reader.
65 virtual MLIRContext *getContext() const = 0;
66
67 /// Return the bytecode version being read.
68 virtual uint64_t getBytecodeVersion() const = 0;
69
70 /// Read out a list of elements, invoking the provided callback for each
71 /// element. The callback function may be in any of the following forms:
72 /// * LogicalResult(T &)
73 /// * FailureOr<T>()
74 template <typename T, typename CallbackFn>
75 LogicalResult readList(SmallVectorImpl<T> &result, CallbackFn &&callback) {
76 uint64_t size;
77 if (failed(readVarInt(size)))
78 return failure();
79 result.reserve(size);
80
81 for (uint64_t i = 0; i < size; ++i) {
82 // Check if the callback uses FailureOr, or populates the result by
83 // reference.
84 if constexpr (llvm::function_traits<std::decay_t<CallbackFn>>::num_args) {
85 T element = {};
86 if (failed(callback(element)))
87 return failure();
88 result.emplace_back(std::move(element));
89 } else {
90 FailureOr<T> element = callback();
91 if (failed(element))
92 return failure();
93 result.emplace_back(std::move(*element));
94 }
95 }
96 return success();
97 }
98
99 //===--------------------------------------------------------------------===//
100 // IR
101 //===--------------------------------------------------------------------===//
102
103 /// Read a reference to the given attribute.
104 virtual LogicalResult readAttribute(Attribute &result) = 0;
105 /// Read an optional reference to the given attribute. Returns success even if
106 /// the Attribute isn't present.
107 virtual LogicalResult readOptionalAttribute(Attribute &attr) = 0;
108
109 template <typename T>
110 LogicalResult readAttributes(SmallVectorImpl<T> &attrs) {
111 return readList(attrs, [this](T &attr) { return readAttribute(attr); });
112 }
113 template <typename T>
114 LogicalResult readAttribute(T &result) {
115 Attribute baseResult;
116 if (failed(readAttribute(baseResult)))
117 return failure();
118 if ((result = dyn_cast<T>(baseResult)))
119 return success();
120 return emitError() << "expected " << llvm::getTypeName<T>()
121 << ", but got: " << baseResult;
122 }
123 template <typename T>
124 LogicalResult readOptionalAttribute(T &result) {
125 Attribute baseResult;
126 if (failed(readOptionalAttribute(baseResult)))
127 return failure();
128 if (!baseResult)
129 return success();
130 if ((result = dyn_cast<T>(baseResult)))
131 return success();
132 return emitError() << "expected " << llvm::getTypeName<T>()
133 << ", but got: " << baseResult;
134 }
135
136 /// Read a reference to the given type.
137 virtual LogicalResult readType(Type &result) = 0;
138 template <typename T>
139 LogicalResult readTypes(SmallVectorImpl<T> &types) {
140 return readList(types, [this](T &type) { return readType(type); });
141 }
142 template <typename T>
143 LogicalResult readType(T &result) {
144 Type baseResult;
145 if (failed(readType(baseResult)))
146 return failure();
147 if ((result = dyn_cast<T>(baseResult)))
148 return success();
149 return emitError() << "expected " << llvm::getTypeName<T>()
150 << ", but got: " << baseResult;
151 }
152
153 /// Read a handle to a dialect resource.
154 template <typename ResourceT>
155 FailureOr<ResourceT> readResourceHandle() {
156 FailureOr<AsmDialectResourceHandle> handle = readResourceHandle();
157 if (failed(handle))
158 return failure();
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";
163 }
164
165 //===--------------------------------------------------------------------===//
166 // Primitives
167 //===--------------------------------------------------------------------===//
168
169 /// Read a variable width integer.
170 virtual LogicalResult readVarInt(uint64_t &result) = 0;
171
172 /// Read a signed variable width integer.
173 virtual LogicalResult readSignedVarInt(int64_t &result) = 0;
175 return readList(result,
176 [this](int64_t &value) { return readSignedVarInt(value); });
177 }
178
179 /// Parse a variable length encoded integer whose low bit is used to encode an
180 /// unrelated flag, i.e: `(integerValue << 1) | (flag ? 1 : 0)`.
181 LogicalResult readVarIntWithFlag(uint64_t &result, bool &flag) {
182 if (failed(readVarInt(result)))
183 return failure();
184 flag = result & 1;
185 result >>= 1;
186 return success();
187 }
188
189 /// Read a "small" sparse array of integer <= 32 bits elements, where
190 /// index/value pairs can be compressed when the array is small.
191 /// Note that only some position of the array will be read and the ones
192 /// not stored in the bytecode are gonne be left untouched.
193 /// If the provided array is too small for the stored indices, an error
194 /// will be returned.
195 template <typename T>
196 LogicalResult readSparseArray(MutableArrayRef<T> array) {
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;
201 if (failed(readVarIntWithFlag(nonZeroesCount, useSparseEncoding)))
202 return failure();
203 if (nonZeroesCount == 0)
204 return success();
205 if (!useSparseEncoding) {
206 // This is a simple dense array.
207 if (nonZeroesCount > array.size()) {
208 emitError("trying to read an array of ")
209 << nonZeroesCount << " but only " << array.size()
210 << " storage available.";
211 return failure();
212 }
213 for (int64_t index : llvm::seq<int64_t>(0, nonZeroesCount)) {
214 uint64_t value;
215 if (failed(readVarInt(value)))
216 return failure();
217 array[index] = value;
218 }
219 return success();
220 }
221 // Read sparse encoding
222 // This is the number of bits used for packing the index with the value.
223 uint64_t indexBitSize;
224 if (failed(readVarInt(indexBitSize)))
225 return failure();
226 constexpr uint64_t maxIndexBitSize = 8;
227 if (indexBitSize > maxIndexBitSize) {
228 emitError("reading sparse array with indexing above 8 bits: ")
229 << indexBitSize;
230 return failure();
231 }
232 for (uint32_t count : llvm::seq<uint32_t>(0, nonZeroesCount)) {
233 (void)count;
234 uint64_t indexValuePair;
235 if (failed(readVarInt(indexValuePair)))
236 return failure();
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.";
242 return failure();
243 }
244 array[index] = value;
245 }
246 return success();
247 }
248
249 /// Read an APInt that is known to have been encoded with the given width.
250 virtual FailureOr<APInt> readAPIntWithKnownWidth(unsigned bitWidth) = 0;
251
252 /// Read an APFloat that is known to have been encoded with the given
253 /// semantics.
254 virtual FailureOr<APFloat>
255 readAPFloatWithKnownSemantics(const llvm::fltSemantics &semantics) = 0;
256
257 /// Read a string from the bytecode.
258 virtual LogicalResult readString(StringRef &result) = 0;
259
260 /// Read a blob from the bytecode.
261 virtual LogicalResult readBlob(ArrayRef<char> &result) = 0;
262
263 /// Read a bool from the bytecode.
264 virtual LogicalResult readBool(bool &result) = 0;
265
266private:
267 /// Read a handle to a dialect resource.
268 virtual FailureOr<AsmDialectResourceHandle> readResourceHandle() = 0;
269};
270
271//===----------------------------------------------------------------------===//
272// DialectBytecodeWriter
273//===----------------------------------------------------------------------===//
274
275/// This class defines a virtual interface for writing to a bytecode stream,
276/// providing hooks into the bytecode writer. As such, this class should only be
277/// derived and defined by the main bytecode writer, users (i.e. dialects)
278/// should generally only interact with this class via the
279/// BytecodeDialectInterface below.
281public:
282 virtual ~DialectBytecodeWriter() = default;
283
284 //===--------------------------------------------------------------------===//
285 // IR
286 //===--------------------------------------------------------------------===//
287
288 /// Write out a list of elements, invoking the provided callback for each
289 /// element.
290 template <typename RangeT, typename CallbackFn>
291 void writeList(RangeT &&range, CallbackFn &&callback) {
292 writeVarInt(llvm::size(range));
293 for (auto &element : range)
294 callback(element);
295 }
296
297 /// Write a reference to the given attribute.
298 virtual void writeAttribute(Attribute attr) = 0;
299 virtual void writeOptionalAttribute(Attribute attr) = 0;
300 template <typename T>
302 writeList(attrs, [this](T attr) { writeAttribute(attr); });
303 }
304
305 /// Write a reference to the given type.
306 virtual void writeType(Type type) = 0;
307 template <typename T>
309 writeList(types, [this](T type) { writeType(type); });
310 }
311
312 /// Write the given handle to a dialect resource.
313 virtual void
315
316 //===--------------------------------------------------------------------===//
317 // Primitives
318 //===--------------------------------------------------------------------===//
319
320 /// Write a variable width integer to the output stream. This should be the
321 /// preferred method for emitting integers whenever possible.
322 virtual void writeVarInt(uint64_t value) = 0;
323
324 /// Write a signed variable width integer to the output stream. This should be
325 /// the preferred method for emitting signed integers whenever possible.
326 virtual void writeSignedVarInt(int64_t value) = 0;
328 writeList(value, [this](int64_t value) { writeSignedVarInt(value); });
329 }
330
331 /// Write a VarInt and a flag packed together.
332 void writeVarIntWithFlag(uint64_t value, bool flag) {
333 writeVarInt((value << 1) | (flag ? 1 : 0));
334 }
335
336 /// Write out a "small" sparse array of integer <= 32 bits elements, where
337 /// index/value pairs can be compressed when the array is small. This method
338 /// will scan the array multiple times and should not be used for large
339 /// arrays. The optional provided "zero" can be used to adjust for the
340 /// expected repeated value. We assume here that the array size fits in a 32
341 /// bits integer.
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)) {
349 if (!array[index])
350 continue;
351 nonZeroesCount++;
352 lastIndex = index;
353 }
354 // If the last position is too large, or the array isn't at least 50%
355 // sparse, emit it with a dense encoding.
356 if (lastIndex > 256 || nonZeroesCount > size / 2) {
357 // Emit the array size and a flag which indicates whether it is sparse.
358 writeVarIntWithFlag(size, false);
359 for (const T &elt : array)
360 writeVarInt(elt);
361 return;
362 }
363 // Emit sparse: first the number of elements we'll write and a flag
364 // indicating it is a sparse encoding.
365 writeVarIntWithFlag(nonZeroesCount, true);
366 if (nonZeroesCount == 0)
367 return;
368 // This is the number of bits used for packing the index with the value.
369 int indexBitSize = llvm::Log2_32_Ceil(lastIndex + 1);
370 writeVarInt(indexBitSize);
371 for (uint32_t index : llvm::seq<uint32_t>(0, lastIndex + 1)) {
372 T value = array[index];
373 if (!value)
374 continue;
375 uint64_t indexValuePair = (value << indexBitSize) | (index);
376 writeVarInt(indexValuePair);
377 }
378 }
379
380 /// Write an APInt to the bytecode stream whose bitwidth will be known
381 /// externally at read time. This method is useful for encoding APInt values
382 /// when the width is known via external means, such as via a type. This
383 /// method should generally only be invoked if you need an APInt, otherwise
384 /// use the varint methods above. APInt values are generally encoded using
385 /// zigzag encoding, to enable more efficient encodings for negative values.
386 virtual void writeAPIntWithKnownWidth(const APInt &value) = 0;
387
388 /// Write an APFloat to the bytecode stream whose semantics will be known
389 /// externally at read time. This method is useful for encoding APFloat values
390 /// when the semantics are known via external means, such as via a type.
391 virtual void writeAPFloatWithKnownSemantics(const APFloat &value) = 0;
392
393 /// Write a string to the bytecode, which is owned by the caller and is
394 /// guaranteed to not die before the end of the bytecode process. This should
395 /// only be called if such a guarantee can be made, such as when the string is
396 /// owned by an attribute or type.
397 virtual void writeOwnedString(StringRef str) = 0;
398
399 /// Write a blob to the bytecode, which is owned by the caller and is
400 /// guaranteed to not die before the end of the bytecode process. The blob is
401 /// written as-is, with no additional compression or compaction.
402 virtual void writeOwnedBlob(ArrayRef<char> blob) = 0;
403
404 /// Write a blob to the bytecode, which is not owned by the caller. The blob
405 /// is copied into the bytecode, and need not strictly outlive the call.
406 virtual void writeUnownedBlob(ArrayRef<char> blob) = 0;
407
408 /// Write a bool to the output stream.
409 virtual void writeOwnedBool(bool value) = 0;
410
411 /// Return the bytecode version being emitted for.
412 virtual int64_t getBytecodeVersion() const = 0;
413
414 /// Retrieve the dialect version by name if available.
415 virtual FailureOr<const DialectVersion *>
416 getDialectVersion(StringRef dialectName) const = 0;
417
418 template <class T>
419 FailureOr<const DialectVersion *> getDialectVersion() const {
420 return getDialectVersion(T::getDialectNamespace());
421 }
422};
423
424//===----------------------------------------------------------------------===//
425// BytecodeDialectInterface
426//===----------------------------------------------------------------------===//
427
429 : public DialectInterface::Base<BytecodeDialectInterface> {
430public:
431 using Base::Base;
432
433 //===--------------------------------------------------------------------===//
434 // Reading
435 //===--------------------------------------------------------------------===//
436
437 /// Read an attribute belonging to this dialect from the given reader. This
438 /// method should return null in the case of failure. Optionally, the dialect
439 /// version can be accessed through the reader.
441 reader.emitError() << "dialect " << getDialect()->getNamespace()
442 << " does not support reading attributes from bytecode";
443 return Attribute();
444 }
445
446 /// Read a type belonging to this dialect from the given reader. This method
447 /// should return null in the case of failure. Optionally, the dialect version
448 /// can be accessed thorugh the reader.
449 virtual Type readType(DialectBytecodeReader &reader) const {
450 reader.emitError() << "dialect " << getDialect()->getNamespace()
451 << " does not support reading types from bytecode";
452 return Type();
453 }
454
455 //===--------------------------------------------------------------------===//
456 // Writing
457 //===--------------------------------------------------------------------===//
458
459 /// Write the given attribute, which belongs to this dialect, to the given
460 /// writer. This method may return failure to indicate that the given
461 /// attribute could not be encoded, in which case the textual format will be
462 /// used to encode this attribute instead.
463 virtual LogicalResult writeAttribute(Attribute attr,
464 DialectBytecodeWriter &writer) const {
465 return failure();
466 }
467
468 /// Write the given type, which belongs to this dialect, to the given writer.
469 /// This method may return failure to indicate that the given type could not
470 /// be encoded, in which case the textual format will be used to encode this
471 /// type instead.
472 virtual LogicalResult writeType(Type type,
473 DialectBytecodeWriter &writer) const {
474 return failure();
475 }
476
477 /// Write the version of this dialect to the given writer.
478 virtual void writeVersion(DialectBytecodeWriter &writer) const {}
479
480 // Read the version of this dialect from the provided reader and return it as
481 // a `unique_ptr` to a dialect version object.
482 virtual std::unique_ptr<DialectVersion>
484 reader.emitError("Dialect does not support versioning");
485 return nullptr;
486 }
487
488 /// Hook invoked after parsing completed, if a version directive was present
489 /// and included an entry for the current dialect. This hook offers the
490 /// opportunity to the dialect to visit the IR and upgrades constructs emitted
491 /// by the version of the dialect corresponding to the provided version.
492 virtual LogicalResult
494 const DialectVersion &version) const {
495 return success();
496 }
497};
498
499/// Helper for resource handle reading that returns LogicalResult.
500template <typename T, typename... Ts>
501static LogicalResult readResourceHandle(DialectBytecodeReader &reader,
502 FailureOr<T> &value, Ts &&...params) {
503 FailureOr<T> handle = reader.readResourceHandle<T>();
504 if (failed(handle))
505 return failure();
506 if (auto *result = dyn_cast<T>(&*handle)) {
507 value = std::move(*result);
508 return success();
509 }
510 return failure();
511}
512
513/// Helper method that injects context only if needed, this helps unify some of
514/// the attribute construction methods.
515template <typename T, typename... Ts>
516auto get(MLIRContext *context, Ts &&...params) {
517 // Prefer a direct `get` method if one exists.
518 if constexpr (llvm::is_detected<detail::has_get_method, T, Ts...>::value) {
519 (void)context;
520 return T::get(std::forward<Ts>(params)...);
521 } else if constexpr (llvm::is_detected<detail::has_get_method, T,
522 MLIRContext *, Ts...>::value) {
523 return T::get(context, std::forward<Ts>(params)...);
524 } else {
525 // Otherwise, pass to the base get.
526 return T::Base::get(context, std::forward<Ts>(params)...);
527 }
528}
529
530} // namespace mlir
531
532#endif // MLIR_BYTECODE_BYTECODEIMPLEMENTATION_H
return success()
This class represents an opaque handle to a dialect resource entry.
Attributes are known-constant values of operations.
Definition Attributes.h:25
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
Definition Dialect.h:54
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.
Definition MLIRContext.h:63
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
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...