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 return readListWithKnownSize(result, size,
80 std::forward<CallbackFn>(callback));
81 }
82
83 /// Read out a list of elements with a known size, invoking the provided
84 /// callback for each element. Unlike readList, this does not read a length
85 /// prefix. The callback function may be in any of the following forms:
86 /// * LogicalResult(T &)
87 /// * FailureOr<T>()
88 template <typename T, typename CallbackFn>
89 LogicalResult readListWithKnownSize(SmallVectorImpl<T> &result, uint64_t size,
90 CallbackFn &&callback) {
91 result.reserve(size);
92
93 for (uint64_t i = 0; i < size; ++i) {
94 // Check if the callback uses FailureOr, or populates the result by
95 // reference.
96 if constexpr (llvm::function_traits<std::decay_t<CallbackFn>>::num_args) {
97 T element = {};
98 if (failed(callback(element)))
99 return failure();
100 result.emplace_back(std::move(element));
101 } else {
102 FailureOr<T> element = callback();
103 if (failed(element))
104 return failure();
105 result.emplace_back(std::move(*element));
106 }
107 }
108 return success();
109 }
110
111 //===--------------------------------------------------------------------===//
112 // IR
113 //===--------------------------------------------------------------------===//
114
115 /// Read a reference to the given attribute.
116 virtual LogicalResult readAttribute(Attribute &result) = 0;
117 /// Read an optional reference to the given attribute. Returns success even if
118 /// the Attribute isn't present.
119 virtual LogicalResult readOptionalAttribute(Attribute &attr) = 0;
120
121 template <typename T>
122 LogicalResult readAttributes(SmallVectorImpl<T> &attrs) {
123 return readList(attrs, [this](T &attr) { return readAttribute(attr); });
124 }
125 template <typename T>
126 LogicalResult readAttribute(T &result) {
127 Attribute baseResult;
128 if (failed(readAttribute(baseResult)))
129 return failure();
130 if ((result = dyn_cast<T>(baseResult)))
131 return success();
132 return emitError() << "expected " << llvm::getTypeName<T>()
133 << ", but got: " << baseResult;
134 }
135 template <typename T>
136 LogicalResult readOptionalAttribute(T &result) {
137 Attribute baseResult;
138 if (failed(readOptionalAttribute(baseResult)))
139 return failure();
140 if (!baseResult)
141 return success();
142 if ((result = dyn_cast<T>(baseResult)))
143 return success();
144 return emitError() << "expected " << llvm::getTypeName<T>()
145 << ", but got: " << baseResult;
146 }
147
148 /// Read a reference to the given type.
149 virtual LogicalResult readType(Type &result) = 0;
150 template <typename T>
151 LogicalResult readTypes(SmallVectorImpl<T> &types) {
152 return readList(types, [this](T &type) { return readType(type); });
153 }
154 template <typename T>
155 LogicalResult readType(T &result) {
156 Type baseResult;
157 if (failed(readType(baseResult)))
158 return failure();
159 if ((result = dyn_cast<T>(baseResult)))
160 return success();
161 return emitError() << "expected " << llvm::getTypeName<T>()
162 << ", but got: " << baseResult;
163 }
164
165 /// Read a handle to a dialect resource.
166 template <typename ResourceT>
167 FailureOr<ResourceT> readResourceHandle() {
168 FailureOr<AsmDialectResourceHandle> handle = readResourceHandle();
169 if (failed(handle))
170 return failure();
171 if (auto *result = dyn_cast<ResourceT>(&*handle))
172 return std::move(*result);
173 return emitError() << "provided resource handle differs from the "
174 "expected resource type";
175 }
176
177 //===--------------------------------------------------------------------===//
178 // Primitives
179 //===--------------------------------------------------------------------===//
180
181 /// Read a variable width integer.
182 virtual LogicalResult readVarInt(uint64_t &result) = 0;
183
184 /// Read a signed variable width integer.
185 virtual LogicalResult readSignedVarInt(int64_t &result) = 0;
187 return readList(result,
188 [this](int64_t &value) { return readSignedVarInt(value); });
189 }
190
191 /// Parse a variable length encoded integer whose low bit is used to encode an
192 /// unrelated flag, i.e: `(integerValue << 1) | (flag ? 1 : 0)`.
193 LogicalResult readVarIntWithFlag(uint64_t &result, bool &flag) {
194 if (failed(readVarInt(result)))
195 return failure();
196 flag = result & 1;
197 result >>= 1;
198 return success();
199 }
200
201 /// Read a "small" sparse array of integer <= 32 bits elements, where
202 /// index/value pairs can be compressed when the array is small.
203 /// Note that only some position of the array will be read and the ones
204 /// not stored in the bytecode are gonne be left untouched.
205 /// If the provided array is too small for the stored indices, an error
206 /// will be returned.
207 template <typename T>
208 LogicalResult readSparseArray(MutableArrayRef<T> array) {
209 static_assert(sizeof(T) < sizeof(uint64_t), "expect integer < 64 bits");
210 static_assert(std::is_integral<T>::value, "expects integer");
211 uint64_t nonZeroesCount;
212 bool useSparseEncoding;
213 if (failed(readVarIntWithFlag(nonZeroesCount, useSparseEncoding)))
214 return failure();
215 if (nonZeroesCount == 0)
216 return success();
217 if (!useSparseEncoding) {
218 // This is a simple dense array.
219 if (nonZeroesCount > array.size()) {
220 emitError("trying to read an array of ")
221 << nonZeroesCount << " but only " << array.size()
222 << " storage available.";
223 return failure();
224 }
225 for (int64_t index : llvm::seq<int64_t>(0, nonZeroesCount)) {
226 uint64_t value;
227 if (failed(readVarInt(value)))
228 return failure();
229 array[index] = value;
230 }
231 return success();
232 }
233 // Read sparse encoding
234 // This is the number of bits used for packing the index with the value.
235 uint64_t indexBitSize;
236 if (failed(readVarInt(indexBitSize)))
237 return failure();
238 constexpr uint64_t maxIndexBitSize = 8;
239 if (indexBitSize > maxIndexBitSize) {
240 emitError("reading sparse array with indexing above 8 bits: ")
241 << indexBitSize;
242 return failure();
243 }
244 for (uint32_t count : llvm::seq<uint32_t>(0, nonZeroesCount)) {
245 (void)count;
246 uint64_t indexValuePair;
247 if (failed(readVarInt(indexValuePair)))
248 return failure();
249 uint64_t index = indexValuePair & ~(uint64_t(-1) << (indexBitSize));
250 uint64_t value = indexValuePair >> indexBitSize;
251 if (index >= array.size()) {
252 emitError("reading a sparse array found index ")
253 << index << " but only " << array.size() << " storage available.";
254 return failure();
255 }
256 array[index] = value;
257 }
258 return success();
259 }
260
261 /// Read an APInt that is known to have been encoded with the given width.
262 virtual FailureOr<APInt> readAPIntWithKnownWidth(unsigned bitWidth) = 0;
263
264 /// Read an APFloat that is known to have been encoded with the given
265 /// semantics.
266 virtual FailureOr<APFloat>
267 readAPFloatWithKnownSemantics(const llvm::fltSemantics &semantics) = 0;
268
269 /// Read a string from the bytecode.
270 virtual LogicalResult readString(StringRef &result) = 0;
271
272 /// Read a blob from the bytecode.
273 virtual LogicalResult readBlob(ArrayRef<char> &result) = 0;
274
275 /// Read a bool from the bytecode.
276 virtual LogicalResult readBool(bool &result) = 0;
277
278private:
279 /// Read a handle to a dialect resource.
280 virtual FailureOr<AsmDialectResourceHandle> readResourceHandle() = 0;
281};
282
283//===----------------------------------------------------------------------===//
284// DialectBytecodeWriter
285//===----------------------------------------------------------------------===//
286
287/// This class defines a virtual interface for writing to a bytecode stream,
288/// providing hooks into the bytecode writer. As such, this class should only be
289/// derived and defined by the main bytecode writer, users (i.e. dialects)
290/// should generally only interact with this class via the
291/// BytecodeDialectInterface below.
293public:
294 virtual ~DialectBytecodeWriter() = default;
295
296 //===--------------------------------------------------------------------===//
297 // IR
298 //===--------------------------------------------------------------------===//
299
300 /// Write out a list of elements, invoking the provided callback for each
301 /// element.
302 template <typename RangeT, typename CallbackFn>
303 void writeList(RangeT &&range, CallbackFn &&callback) {
304 writeVarInt(llvm::size(range));
305 for (auto &element : range)
306 callback(element);
307 }
308
309 /// Write out a list of elements without a length prefix, for cases where the
310 /// size is known from another field.
311 template <typename RangeT, typename CallbackFn>
312 void writeListWithKnownSize(RangeT &&range, CallbackFn &&callback) {
313 for (auto &element : range)
314 callback(element);
315 }
316
317 /// Write a reference to the given attribute.
318 virtual void writeAttribute(Attribute attr) = 0;
319 virtual void writeOptionalAttribute(Attribute attr) = 0;
320 template <typename T>
322 writeList(attrs, [this](T attr) { writeAttribute(attr); });
323 }
324
325 /// Write a reference to the given type.
326 virtual void writeType(Type type) = 0;
327 template <typename T>
329 writeList(types, [this](T type) { writeType(type); });
330 }
331
332 /// Write the given handle to a dialect resource.
333 virtual void
335
336 //===--------------------------------------------------------------------===//
337 // Primitives
338 //===--------------------------------------------------------------------===//
339
340 /// Write a variable width integer to the output stream. This should be the
341 /// preferred method for emitting integers whenever possible.
342 virtual void writeVarInt(uint64_t value) = 0;
343
344 /// Write a signed variable width integer to the output stream. This should be
345 /// the preferred method for emitting signed integers whenever possible.
346 virtual void writeSignedVarInt(int64_t value) = 0;
348 writeList(value, [this](int64_t value) { writeSignedVarInt(value); });
349 }
350
351 /// Write a VarInt and a flag packed together.
352 void writeVarIntWithFlag(uint64_t value, bool flag) {
353 writeVarInt((value << 1) | (flag ? 1 : 0));
354 }
355
356 /// Write out a "small" sparse array of integer <= 32 bits elements, where
357 /// index/value pairs can be compressed when the array is small. This method
358 /// will scan the array multiple times and should not be used for large
359 /// arrays. The optional provided "zero" can be used to adjust for the
360 /// expected repeated value. We assume here that the array size fits in a 32
361 /// bits integer.
362 template <typename T>
364 static_assert(sizeof(T) < sizeof(uint64_t), "expect integer < 64 bits");
365 static_assert(std::is_integral<T>::value, "expects integer");
366 uint32_t size = array.size();
367 uint32_t nonZeroesCount = 0, lastIndex = 0;
368 for (uint32_t index : llvm::seq<uint32_t>(0, size)) {
369 if (!array[index])
370 continue;
371 nonZeroesCount++;
372 lastIndex = index;
373 }
374 // If the last position is too large, or the array isn't at least 50%
375 // sparse, emit it with a dense encoding.
376 if (lastIndex > 256 || nonZeroesCount > size / 2) {
377 // Emit the array size and a flag which indicates whether it is sparse.
378 writeVarIntWithFlag(size, false);
379 for (const T &elt : array)
380 writeVarInt(elt);
381 return;
382 }
383 // Emit sparse: first the number of elements we'll write and a flag
384 // indicating it is a sparse encoding.
385 writeVarIntWithFlag(nonZeroesCount, true);
386 if (nonZeroesCount == 0)
387 return;
388 // This is the number of bits used for packing the index with the value.
389 int indexBitSize = llvm::Log2_32_Ceil(lastIndex + 1);
390 writeVarInt(indexBitSize);
391 for (uint32_t index : llvm::seq<uint32_t>(0, lastIndex + 1)) {
392 T value = array[index];
393 if (!value)
394 continue;
395 uint64_t indexValuePair = (value << indexBitSize) | (index);
396 writeVarInt(indexValuePair);
397 }
398 }
399
400 /// Write an APInt to the bytecode stream whose bitwidth will be known
401 /// externally at read time. This method is useful for encoding APInt values
402 /// when the width is known via external means, such as via a type. This
403 /// method should generally only be invoked if you need an APInt, otherwise
404 /// use the varint methods above. APInt values are generally encoded using
405 /// zigzag encoding, to enable more efficient encodings for negative values.
406 virtual void writeAPIntWithKnownWidth(const APInt &value) = 0;
407
408 /// Write an APFloat to the bytecode stream whose semantics will be known
409 /// externally at read time. This method is useful for encoding APFloat values
410 /// when the semantics are known via external means, such as via a type.
411 virtual void writeAPFloatWithKnownSemantics(const APFloat &value) = 0;
412
413 /// Write a string to the bytecode, which is owned by the caller and is
414 /// guaranteed to not die before the end of the bytecode process. This should
415 /// only be called if such a guarantee can be made, such as when the string is
416 /// owned by an attribute or type.
417 virtual void writeOwnedString(StringRef str) = 0;
418
419 /// Write a blob to the bytecode, which is owned by the caller and is
420 /// guaranteed to not die before the end of the bytecode process. The blob is
421 /// written as-is, with no additional compression or compaction.
422 virtual void writeOwnedBlob(ArrayRef<char> blob) = 0;
423
424 /// Write a blob to the bytecode, which is not owned by the caller. The blob
425 /// is copied into the bytecode, and need not strictly outlive the call.
426 virtual void writeUnownedBlob(ArrayRef<char> blob) = 0;
427
428 /// Write a bool to the output stream.
429 virtual void writeOwnedBool(bool value) = 0;
430
431 /// Return the bytecode version being emitted for.
432 virtual int64_t getBytecodeVersion() const = 0;
433
434 /// Retrieve the dialect version by name if available.
435 virtual FailureOr<const DialectVersion *>
436 getDialectVersion(StringRef dialectName) const = 0;
437
438 template <class T>
439 FailureOr<const DialectVersion *> getDialectVersion() const {
440 return getDialectVersion(T::getDialectNamespace());
441 }
442};
443
444/// Helper for resource handle reading that returns LogicalResult.
445template <typename T, typename... Ts>
446static LogicalResult readResourceHandle(DialectBytecodeReader &reader,
447 FailureOr<T> &value, Ts &&...params) {
448 FailureOr<T> handle = reader.readResourceHandle<T>();
449 if (failed(handle))
450 return failure();
451 if (auto *result = dyn_cast<T>(&*handle)) {
452 value = std::move(*result);
453 return success();
454 }
455 return failure();
456}
457
458/// Helper method that injects context only if needed, this helps unify some of
459/// the attribute construction methods.
460template <typename T, typename... Ts>
461auto get(MLIRContext *context, Ts &&...params) {
462 // Prefer a direct `get` method if one exists.
463 if constexpr (llvm::is_detected<detail::has_get_method, T, Ts...>::value) {
464 (void)context;
465 return T::get(std::forward<Ts>(params)...);
466 } else if constexpr (llvm::is_detected<detail::has_get_method, T,
467 MLIRContext *, Ts...>::value) {
468 return T::get(context, std::forward<Ts>(params)...);
469 } else {
470 // Otherwise, pass to the base get.
471 return T::Base::get(context, std::forward<Ts>(params)...);
472 }
473}
474
475namespace detail {
476template <typename T, typename... Ts>
477using has_get_checked_method = decltype(T::getChecked(std::declval<Ts>()...));
478} // namespace detail
479
480/// Helper method analogous to `get`, but uses `getChecked` when available to
481/// allow graceful failure on invalid parameters instead of asserting.
482///
483/// Only the no-context form of `getChecked` is tried here. Types that expose
484/// `getChecked(emitError, params...)` without a leading `MLIRContext*` (e.g.
485/// MemRefType, VectorType, RankedTensorType) will use it for graceful failure.
486/// Everything else falls back to `get<T>()`. We intentionally do NOT try
487/// `T::getChecked(emitError, context, params...)`: for types that only inherit
488/// the base `StorageUserBase::getChecked` template (e.g. ArrayAttr), that
489/// template instantiation requires a complete storage type which may not be
490/// available in the bytecode reading TU.
491template <typename T, typename... Ts>
493 MLIRContext *context, Ts &&...params) {
494 if constexpr (llvm::is_detected<detail::has_get_checked_method, T,
496 Ts...>::value) {
497 (void)context;
498 return T::getChecked(emitError, std::forward<Ts>(params)...);
499 } else {
500 // Fall back to get() for types that don't define a no-context getChecked.
501 return get<T>(context, std::forward<Ts>(params)...);
502 }
503}
504
505} // namespace mlir
506
507#include "mlir/Bytecode/BytecodeDialectInterface.h.inc"
508
509#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
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.
LogicalResult readListWithKnownSize(SmallVectorImpl< T > &result, uint64_t size, CallbackFn &&callback)
Read out a list of elements with a known size, invoking the provided callback for each element.
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 writeListWithKnownSize(RangeT &&range, CallbackFn &&callback)
Write out a list of elements without a length prefix, for cases where the size is known from another ...
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 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
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
decltype(T::get(std::declval< Ts >()...)) has_get_method
decltype(T::getChecked(std::declval< Ts >()...)) has_get_checked_method
Include the generated interface declarations.
static LogicalResult readResourceHandle(DialectBytecodeReader &reader, FailureOr< T > &value, Ts &&...params)
Helper for resource handle reading that returns LogicalResult.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto getChecked(function_ref< InFlightDiagnostic()> emitError, MLIRContext *context, Ts &&...params)
Helper method analogous to get, but uses getChecked when available to allow graceful failure on inval...
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
llvm::function_ref< Fn > function_ref
Definition LLVM.h:147