MLIR  16.0.0git
AsmState.h
Go to the documentation of this file.
1 //===- AsmState.h - Assembly State Utilities --------------------*- 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 file defines various classes and utilites for interacting with the MLIR
10 // assembly formats.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_IR_ASMSTATE_H_
15 #define MLIR_IR_ASMSTATE_H_
16 
18 #include "mlir/Support/LLVM.h"
19 
20 #include <memory>
21 
22 namespace mlir {
23 class AsmResourcePrinter;
24 class Operation;
25 
26 namespace detail {
27 class AsmStateImpl;
28 } // namespace detail
29 
30 //===----------------------------------------------------------------------===//
31 // Resources
32 //===----------------------------------------------------------------------===//
33 
34 /// The following classes enable support for parsing and printing resources
35 /// within MLIR assembly formats. Resources are a mechanism by which dialects,
36 /// and external clients, may attach additional information when parsing or
37 /// printing IR without that information being encoded in the IR itself.
38 /// Resources are not uniqued within the MLIR context, are not attached directly
39 /// to any operation, and are solely intended to live and be processed outside
40 /// of the immediate IR.
41 ///
42 /// Resources are encoded using a key-value pair nested within dictionaries
43 /// anchored either on a dialect, or an externally registered entity.
44 /// Dictionaries anchored on dialects use the dialect namespace directly, and
45 /// dictionaries anchored on external entities use a provided unique identifier.
46 /// The resource key is an identifier used to disambiguate the data. The
47 /// resource value may be stored in various limited forms, but general encodings
48 /// use a string (human readable) or blob format (binary). Within the textual
49 /// format, an example may be of the form:
50 ///
51 /// {-#
52 /// // The `dialect_resources` section within the file-level metadata
53 /// // dictionary is used to contain any dialect resource entries.
54 /// dialect_resources: {
55 /// // Here is a dictionary anchored on "foo_dialect", which is a dialect
56 /// // namespace.
57 /// foo_dialect: {
58 /// // `some_dialect_resource` is a key to be interpreted by the dialect,
59 /// // and used to initialize/configure/etc.
60 /// some_dialect_resource: "Some important resource value"
61 /// }
62 /// },
63 /// // The `external_resources` section within the file-level metadata
64 /// // dictionary is used to contain any non-dialect resource entries.
65 /// external_resources: {
66 /// // Here is a dictionary anchored on "mlir_reproducer", which is an
67 /// // external entity representing MLIR's crash reproducer functionality.
68 /// mlir_reproducer: {
69 /// // `pipeline` is an entry that holds a crash reproducer pipeline
70 /// // resource.
71 /// pipeline: "func.func(canonicalize,cse)"
72 /// }
73 /// }
74 /// #-}
75 ///
76 
77 //===----------------------------------------------------------------------===//
78 // Resource Entry
79 
80 /// This class represents a processed binary blob of data. A resource blob is
81 /// essentially a collection of data, potentially mutable, with an associated
82 /// deleter function (used if the data needs to be destroyed).
84 public:
85  /// A deleter function that frees a blob given the data, allocation size, and
86  /// allocation aligment.
87  using DeleterFn =
88  llvm::unique_function<void(void *data, size_t size, size_t align)>;
89 
90  //===--------------------------------------------------------------------===//
91  // Construction
92  //===--------------------------------------------------------------------===//
93 
94  AsmResourceBlob() = default;
95  AsmResourceBlob(ArrayRef<char> data, size_t dataAlignment, DeleterFn deleter,
96  bool dataIsMutable)
97  : data(data), dataAlignment(dataAlignment), deleter(std::move(deleter)),
98  dataIsMutable(dataIsMutable) {}
99  /// Utility constructor that initializes a blob with a non-char type T.
100  template <typename T, typename DelT>
101  AsmResourceBlob(ArrayRef<T> data, DelT &&deleteFn, bool dataIsMutable)
102  : data((const char *)data.data(), data.size() * sizeof(T)),
103  dataAlignment(alignof(T)),
104  deleter([deleteFn = std::forward<DelT>(deleteFn)](
105  void *data, size_t size, size_t align) {
106  return deleteFn((T *)data, size, align);
107  }),
108  dataIsMutable(dataIsMutable) {}
109  AsmResourceBlob(AsmResourceBlob &&) = default;
111  // Delete the current blob if necessary.
112  if (deleter)
113  deleter(const_cast<char *>(data.data()), data.size(), dataAlignment);
114 
115  // Take the data entries from rhs.
116  data = rhs.data;
117  dataAlignment = rhs.dataAlignment;
118  deleter = std::move(rhs.deleter);
119  dataIsMutable = rhs.dataIsMutable;
120  return *this;
121  }
122  AsmResourceBlob(const AsmResourceBlob &) = delete;
123  AsmResourceBlob &operator=(const AsmResourceBlob &) = delete;
125  if (deleter)
126  deleter(const_cast<char *>(data.data()), data.size(), dataAlignment);
127  }
128 
129  //===--------------------------------------------------------------------===//
130  // Data Access
131  //===--------------------------------------------------------------------===//
132 
133  /// Return the alignment of the underlying data.
134  size_t getDataAlignment() const { return dataAlignment; }
135 
136  /// Return the raw underlying data of this blob.
137  ArrayRef<char> getData() const { return data; }
138 
139  /// Return the underlying data as an array of the given type. This is an
140  /// inherrently unsafe operation, and should only be used when the data is
141  /// known to be of the correct type.
142  template <typename T>
144  return llvm::makeArrayRef<T>((const T *)data.data(),
145  data.size() / sizeof(T));
146  }
147 
148  /// Return a mutable reference to the raw underlying data of this blob.
149  /// Asserts that the blob `isMutable`.
151  assert(isMutable() &&
152  "cannot access mutable reference to non-mutable data");
153  return MutableArrayRef<char>(const_cast<char *>(data.data()), data.size());
154  }
155 
156  /// Return if the data of this blob is mutable.
157  bool isMutable() const { return dataIsMutable; }
158 
159  /// Return the deleter function of this blob.
160  DeleterFn &getDeleter() { return deleter; }
161  const DeleterFn &getDeleter() const { return deleter; }
162 
163 private:
164  /// The raw, properly aligned, blob data.
165  ArrayRef<char> data;
166 
167  /// The alignment of the data.
168  size_t dataAlignment = 0;
169 
170  /// An optional deleter function used to deallocate the underlying data when
171  /// necessary.
172  DeleterFn deleter;
173 
174  /// Whether the data is mutable.
175  bool dataIsMutable;
176 };
177 
178 /// This class provides a simple utility wrapper for creating heap allocated
179 /// AsmResourceBlobs.
181 public:
182  /// Create a new heap allocated blob with the given size and alignment.
183  /// `dataIsMutable` indicates if the allocated data can be mutated. By
184  /// default, we treat heap allocated blobs as mutable.
185  static AsmResourceBlob allocate(size_t size, size_t align,
186  bool dataIsMutable = true) {
187  return AsmResourceBlob(
188  ArrayRef<char>((char *)llvm::allocate_buffer(size, align), size), align,
189  llvm::deallocate_buffer, dataIsMutable);
190  }
191  /// Create a new heap allocated blob and copy the provided data into it.
192  static AsmResourceBlob allocateAndCopy(ArrayRef<char> data, size_t align,
193  bool dataIsMutable = true) {
194  AsmResourceBlob blob = allocate(data.size(), align, dataIsMutable);
195  std::memcpy(blob.getMutableData().data(), data.data(), data.size());
196  return blob;
197  }
198  template <typename T>
200  allocateAndCopy(ArrayRef<T> data, bool dataIsMutable = true) {
201  return allocateAndCopy(
202  ArrayRef<char>((const char *)data.data(), data.size() * sizeof(T)),
203  alignof(T));
204  }
205 };
206 /// This class provides a simple utility wrapper for creating "unmanaged"
207 /// AsmResourceBlobs. The lifetime of the data provided to these blobs is
208 /// guaranteed to persist beyond the lifetime of this reference.
210 public:
211  /// Create a new unmanaged resource directly referencing the provided data.
212  /// `dataIsMutable` indicates if the allocated data can be mutated. By
213  /// default, we treat unmanaged blobs as immutable.
214  static AsmResourceBlob allocate(ArrayRef<char> data, size_t align,
215  bool dataIsMutable = false) {
216  return AsmResourceBlob(data, align, /*deleter=*/{},
217  /*dataIsMutable=*/false);
218  }
219  template <typename T>
221  allocate(ArrayRef<T> data, bool dataIsMutable = false) {
222  return allocate(
223  ArrayRef<char>((const char *)data.data(), data.size() * sizeof(T)),
224  alignof(T));
225  }
226 };
227 
228 /// This class is used to build resource entries for use by the printer. Each
229 /// resource entry is represented using a key/value pair. The provided key must
230 /// be unique within the current context, which allows for a client to provide
231 /// resource entries without worrying about overlap with other clients.
233 public:
234  virtual ~AsmResourceBuilder();
235 
236  /// Build a resource entry represented by the given bool.
237  virtual void buildBool(StringRef key, bool data) = 0;
238 
239  /// Build a resource entry represented by the given human-readable string
240  /// value.
241  virtual void buildString(StringRef key, StringRef data) = 0;
242 
243  /// Build an resource entry represented by the given binary blob data.
244  virtual void buildBlob(StringRef key, ArrayRef<char> data,
245  uint32_t dataAlignment) = 0;
246  /// Build an resource entry represented by the given binary blob data. This is
247  /// a useful overload if the data type is known. Note that this does not
248  /// support `char` element types to avoid accidentally not providing the
249  /// expected alignment of data in situations that treat blobs generically.
250  template <typename T>
252  ArrayRef<T> data) {
253  buildBlob(
254  key, ArrayRef<char>((const char *)data.data(), data.size() * sizeof(T)),
255  alignof(T));
256  }
257  /// Build an resource entry represented by the given resource blob. This is
258  /// a useful overload if a blob already exists in-memory.
259  void buildBlob(StringRef key, const AsmResourceBlob &blob) {
260  buildBlob(key, blob.getData(), blob.getDataAlignment());
261  }
262 };
263 
264 /// This class represents a single parsed resource entry.
266 public:
267  virtual ~AsmParsedResourceEntry();
268 
269  /// Return the key of the resource entry.
270  virtual StringRef getKey() const = 0;
271 
272  /// Emit an error at the location of this entry.
273  virtual InFlightDiagnostic emitError() const = 0;
274 
275  /// Parse the resource entry represented by a boolean. Returns failure if the
276  /// entry does not correspond to a bool.
277  virtual FailureOr<bool> parseAsBool() const = 0;
278 
279  /// Parse the resource entry represented by a human-readable string. Returns
280  /// failure if the entry does not correspond to a string.
281  virtual FailureOr<std::string> parseAsString() const = 0;
282 
283  /// An allocator function used to allocate memory for a blob when required.
284  /// The function is provided a size and alignment, and should return an
285  /// aligned allocation buffer.
286  using BlobAllocatorFn =
288 
289  /// Parse the resource entry represented by a binary blob. Returns failure if
290  /// the entry does not correspond to a blob. If the blob needed to be
291  /// allocated, the given allocator function is invoked.
293  parseAsBlob(BlobAllocatorFn allocator) const = 0;
294  /// Parse the resource entry represented by a binary blob using heap
295  /// allocation.
297  return parseAsBlob([](size_t size, size_t align) {
298  return HeapAsmResourceBlob::allocate(size, align);
299  });
300  }
301 };
302 
303 //===----------------------------------------------------------------------===//
304 // Resource Parser/Printer
305 
306 /// This class represents an instance of a resource parser. This class should be
307 /// implemented by non-dialect clients that want to inject additional resources
308 /// into MLIR assembly formats.
310 public:
311  /// Create a new parser with the given identifying name. This name uniquely
312  /// identifies the entries of this parser, and differentiates them from other
313  /// contexts.
314  AsmResourceParser(StringRef name) : name(name.str()) {}
315  virtual ~AsmResourceParser();
316 
317  /// Return the name of this parser.
318  StringRef getName() const { return name; }
319 
320  /// Parse the given resource entry. Returns failure if the key/data were not
321  /// valid, or could otherwise not be processed correctly. Any necessary errors
322  /// should be emitted with the provided entry.
323  virtual LogicalResult parseResource(AsmParsedResourceEntry &entry) = 0;
324 
325  /// Return a resource parser implemented via the given callable, whose form
326  /// should match that of `parseResource` above.
327  template <typename CallableT>
328  static std::unique_ptr<AsmResourceParser> fromCallable(StringRef name,
329  CallableT &&parseFn) {
330  struct Processor : public AsmResourceParser {
331  Processor(StringRef name, CallableT &&parseFn)
332  : AsmResourceParser(name), parseFn(std::move(parseFn)) {}
333  LogicalResult parseResource(AsmParsedResourceEntry &entry) override {
334  return parseFn(entry);
335  }
336 
337  std::decay_t<CallableT> parseFn;
338  };
339  return std::make_unique<Processor>(name, std::forward<CallableT>(parseFn));
340  }
341 
342 private:
343  std::string name;
344 };
345 
346 /// This class represents an instance of a resource printer. This class should
347 /// be implemented by non-dialect clients that want to inject additional
348 /// resources into MLIR assembly formats.
350 public:
351  /// Create a new printer with the given identifying name. This name uniquely
352  /// identifies the entries of this printer, and differentiates them from
353  /// other contexts.
354  AsmResourcePrinter(StringRef name) : name(name.str()) {}
355  virtual ~AsmResourcePrinter();
356 
357  /// Return the name of this printer.
358  StringRef getName() const { return name; }
359 
360  /// Build any resources to include during printing, utilizing the given
361  /// top-level root operation to help determine what information to include.
362  /// Provided data should be registered in the form of a key/data pair, to the
363  /// given builder.
364  virtual void buildResources(Operation *op,
365  AsmResourceBuilder &builder) const = 0;
366 
367  /// Return a resource printer implemented via the given callable, whose form
368  /// should match that of `buildResources` above.
369  template <typename CallableT>
370  static std::unique_ptr<AsmResourcePrinter> fromCallable(StringRef name,
371  CallableT &&printFn) {
372  struct Printer : public AsmResourcePrinter {
373  Printer(StringRef name, CallableT &&printFn)
374  : AsmResourcePrinter(name), printFn(std::move(printFn)) {}
375  void buildResources(Operation *op,
376  AsmResourceBuilder &builder) const override {
377  printFn(op, builder);
378  }
379 
380  std::decay_t<CallableT> printFn;
381  };
382  return std::make_unique<Printer>(name, std::forward<CallableT>(printFn));
383  }
384 
385 private:
386  std::string name;
387 };
388 
389 //===----------------------------------------------------------------------===//
390 // ParserConfig
391 //===----------------------------------------------------------------------===//
392 
393 /// This class represents a configuration for the MLIR assembly parser. It
394 /// contains all of the necessary state to parse a MLIR source file.
396 public:
397  ParserConfig(MLIRContext *context) : context(context) {
398  assert(context && "expected valid MLIR context");
399  }
400 
401  /// Return the MLIRContext to be used when parsing.
402  MLIRContext *getContext() const { return context; }
403 
404  /// Return the resource parser registered to the given name, or nullptr if no
405  /// parser with `name` is registered.
406  AsmResourceParser *getResourceParser(StringRef name) const {
407  auto it = resourceParsers.find(name);
408  return it == resourceParsers.end() ? nullptr : it->second.get();
409  }
410 
411  /// Attach the given resource parser.
412  void attachResourceParser(std::unique_ptr<AsmResourceParser> parser) {
413  StringRef name = parser->getName();
414  auto it = resourceParsers.try_emplace(name, std::move(parser));
415  (void)it;
416  assert(it.second &&
417  "resource parser already registered with the given name");
418  }
419 
420  /// Attach the given callable resource parser with the given name.
421  template <typename CallableT>
422  std::enable_if_t<std::is_convertible<
424  attachResourceParser(StringRef name, CallableT &&parserFn) {
425  attachResourceParser(AsmResourceParser::fromCallable(
426  name, std::forward<CallableT>(parserFn)));
427  }
428 
429 private:
430  MLIRContext *context;
432 };
433 
434 //===----------------------------------------------------------------------===//
435 // AsmState
436 //===----------------------------------------------------------------------===//
437 
438 /// This class provides management for the lifetime of the state used when
439 /// printing the IR. It allows for alleviating the cost of recomputing the
440 /// internal state of the asm printer.
441 ///
442 /// The IR should not be mutated in-between invocations using this state, and
443 /// the IR being printed must not be an parent of the IR originally used to
444 /// initialize this state. This means that if a child operation is provided, a
445 /// parent operation cannot reuse this state.
446 class AsmState {
447 public:
448  /// This map represents the raw locations of operations within the output
449  /// stream. This maps the original pointer to the operation, to a pair of line
450  /// and column in the output stream.
452 
453  /// Initialize the asm state at the level of the given operation. A location
454  /// map may optionally be provided to be populated when printing.
455  AsmState(Operation *op,
456  const OpPrintingFlags &printerFlags = OpPrintingFlags(),
457  LocationMap *locationMap = nullptr);
458  ~AsmState();
459 
460  /// Get the printer flags.
461  const OpPrintingFlags &getPrinterFlags() const;
462 
463  /// Return an instance of the internal implementation. Returns nullptr if the
464  /// state has not been initialized.
466 
467  //===--------------------------------------------------------------------===//
468  // Resources
469  //===--------------------------------------------------------------------===//
470 
471  /// Attach the given resource printer to the AsmState.
472  void attachResourcePrinter(std::unique_ptr<AsmResourcePrinter> printer);
473 
474  /// Attach an resource printer, in the form of a callable, to the AsmState.
475  template <typename CallableT>
476  std::enable_if_t<std::is_convertible<
478  attachResourcePrinter(StringRef name, CallableT &&printFn) {
479  attachResourcePrinter(AsmResourcePrinter::fromCallable(
480  name, std::forward<CallableT>(printFn)));
481  }
482 
483 private:
484  AsmState() = delete;
485 
486  /// A pointer to allocated storage for the impl state.
487  std::unique_ptr<detail::AsmStateImpl> impl;
488 };
489 
490 //===----------------------------------------------------------------------===//
491 // AsmPrinter CommandLine Options
492 //===----------------------------------------------------------------------===//
493 
494 /// Register a set of useful command-line options that can be used to configure
495 /// various flags within the AsmPrinter.
497 
498 } // namespace mlir
499 
500 #endif // MLIR_IR_ASMSTATE_H_
Include the generated interface declarations.
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
ParserConfig(MLIRContext *context)
Definition: AsmState.h:397
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:310
AsmResourceParser(StringRef name)
Create a new parser with the given identifying name.
Definition: AsmState.h:314
MLIRContext * getContext() const
Return the MLIRContext to be used when parsing.
Definition: AsmState.h:402
This class is used to build resource entries for use by the printer.
Definition: AsmState.h:232
MutableArrayRef< char > getMutableData()
Return a mutable reference to the raw underlying data of this blob.
Definition: AsmState.h:150
void buildBlob(StringRef key, const AsmResourceBlob &blob)
Build an resource entry represented by the given resource blob.
Definition: AsmState.h:259
size_t getDataAlignment() const
Return the alignment of the underlying data.
Definition: AsmState.h:134
static std::enable_if_t<!std::is_same< T, char >::value, AsmResourceBlob > allocateAndCopy(ArrayRef< T > data, bool dataIsMutable=true)
Definition: AsmState.h:200
This class represents a single parsed resource entry.
Definition: AsmState.h:265
static AsmResourceBlob allocateAndCopy(ArrayRef< char > data, size_t align, bool dataIsMutable=true)
Create a new heap allocated blob and copy the provided data into it.
Definition: AsmState.h:192
FailureOr< AsmResourceBlob > parseAsBlob() const
Parse the resource entry represented by a binary blob using heap allocation.
Definition: AsmState.h:296
bool isMutable() const
Return if the data of this blob is mutable.
Definition: AsmState.h:157
static constexpr const bool value
ArrayRef< T > getDataAs() const
Return the underlying data as an array of the given type.
Definition: AsmState.h:143
detail::AsmStateImpl & getImpl()
Return an instance of the internal implementation.
Definition: AsmState.h:465
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
This class provides a simple utility wrapper for creating heap allocated AsmResourceBlobs.
Definition: AsmState.h:180
This class provides a simple utility wrapper for creating "unmanaged" AsmResourceBlobs.
Definition: AsmState.h:209
This class provides support for representing a failure result, or a valid value of type T...
Definition: LogicalResult.h:78
void registerAsmPrinterCLOptions()
Register a set of useful command-line options that can be used to configure various flags within the ...
Definition: AsmPrinter.cpp:178
static std::unique_ptr< AsmResourcePrinter > fromCallable(StringRef name, CallableT &&printFn)
Return a resource printer implemented via the given callable, whose form should match that of buildRe...
Definition: AsmState.h:370
StringRef getName() const
Return the name of this printer.
Definition: AsmState.h:358
std::enable_if_t<!std::is_same< T, char >::value > buildBlob(StringRef key, ArrayRef< T > data)
Build an resource entry represented by the given binary blob data.
Definition: AsmState.h:251
static AsmResourceBlob allocate(ArrayRef< char > data, size_t align, bool dataIsMutable=false)
Create a new unmanaged resource directly referencing the provided data.
Definition: AsmState.h:214
std::enable_if_t< std::is_convertible< CallableT, function_ref< void(Operation *, AsmResourceBuilder &)> >::value > attachResourcePrinter(StringRef name, CallableT &&printFn)
Attach an resource printer, in the form of a callable, to the AsmState.
Definition: AsmState.h:478
DeleterFn & getDeleter()
Return the deleter function of this blob.
Definition: AsmState.h:160
AsmResourceBlob(ArrayRef< char > data, size_t dataAlignment, DeleterFn deleter, bool dataIsMutable)
Definition: AsmState.h:95
This class represents an instance of a resource printer.
Definition: AsmState.h:349
void attachResourceParser(std::unique_ptr< AsmResourceParser > parser)
Attach the given resource parser.
Definition: AsmState.h:412
static std::unique_ptr< AsmResourceParser > fromCallable(StringRef name, CallableT &&parseFn)
Return a resource parser implemented via the given callable, whose form should match that of parseRes...
Definition: AsmState.h:328
llvm::unique_function< void(void *data, size_t size, size_t align)> DeleterFn
A deleter function that frees a blob given the data, allocation size, and allocation aligment...
Definition: AsmState.h:88
ArrayRef< char > getData() const
Return the raw underlying data of this blob.
Definition: AsmState.h:137
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
Set of flags used to control the behavior of the various IR print methods (e.g.
AsmResourceBlob & operator=(AsmResourceBlob &&rhs)
Definition: AsmState.h:110
StringRef getName() const
Return the name of this parser.
Definition: AsmState.h:318
This class represents an instance of a resource parser.
Definition: AsmState.h:309
const DeleterFn & getDeleter() const
Definition: AsmState.h:161
static bool isMutable(Attribute attr)
Return if the given element is mutable.
static AsmResourceBlob allocate(size_t size, size_t align, bool dataIsMutable=true)
Create a new heap allocated blob with the given size and alignment.
Definition: AsmState.h:185
This class represents a configuration for the MLIR assembly parser.
Definition: AsmState.h:395
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:55
std::enable_if_t< std::is_convertible< CallableT, function_ref< LogicalResult(AsmParsedResourceEntry &)> >::value > attachResourceParser(StringRef name, CallableT &&parserFn)
Attach the given callable resource parser with the given name.
Definition: AsmState.h:424
AsmResourcePrinter(StringRef name)
Create a new printer with the given identifying name.
Definition: AsmState.h:354
AsmResourceParser * getResourceParser(StringRef name) const
Return the resource parser registered to the given name, or nullptr if no parser with name is registe...
Definition: AsmState.h:406
The following classes enable support for parsing and printing resources within MLIR assembly formats...
Definition: AsmState.h:83
AsmResourceBlob(ArrayRef< T > data, DelT &&deleteFn, bool dataIsMutable)
Utility constructor that initializes a blob with a non-char type T.
Definition: AsmState.h:101
This class provides management for the lifetime of the state used when printing the IR...
Definition: AsmState.h:446
static std::enable_if_t<!std::is_same< T, char >::value, AsmResourceBlob > allocate(ArrayRef< T > data, bool dataIsMutable=false)
Definition: AsmState.h:221