MLIR  19.0.0git
Deserializer.h
Go to the documentation of this file.
1 //===- Deserializer.h - MLIR SPIR-V Deserializer ----------------*- 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 declares the SPIR-V binary to MLIR SPIR-V module deserializer.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_TARGET_SPIRV_DESERIALIZER_H
14 #define MLIR_TARGET_SPIRV_DESERIALIZER_H
15 
18 #include "mlir/IR/Builders.h"
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/SetVector.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/ScopedPrinter.h"
23 #include <cstdint>
24 #include <optional>
25 
26 namespace mlir {
27 namespace spirv {
28 
29 //===----------------------------------------------------------------------===//
30 // Utility Definitions
31 //===----------------------------------------------------------------------===//
32 
33 /// A struct for containing a header block's merge and continue targets.
34 ///
35 /// This struct is used to track original structured control flow info from
36 /// SPIR-V blob. This info will be used to create
37 /// spirv.mlir.selection/spirv.mlir.loop later.
40  Block *continueBlock; // nullptr for spirv.mlir.selection
42  uint32_t control; // Selection/loop control
43 
44  BlockMergeInfo(Location location, uint32_t control)
45  : mergeBlock(nullptr), continueBlock(nullptr), loc(location),
46  control(control) {}
47  BlockMergeInfo(Location location, uint32_t control, Block *m,
48  Block *c = nullptr)
49  : mergeBlock(m), continueBlock(c), loc(location), control(control) {}
50 };
51 
52 /// A struct for containing OpLine instruction information.
53 struct DebugLine {
54  uint32_t fileID;
55  uint32_t line;
56  uint32_t column;
57 };
58 
59 /// Map from a selection/loop's header block to its merge (and continue) target.
61 
62 /// A "deferred struct type" is a struct type with one or more member types not
63 /// known when the Deserializer first encounters the struct. This happens, for
64 /// example, with recursive structs where a pointer to the struct type is
65 /// forward declared through OpTypeForwardPointer in the SPIR-V module before
66 /// the struct declaration; the actual pointer to struct type should be defined
67 /// later through an OpTypePointer. For example, the following C struct:
68 ///
69 /// struct A {
70 /// A* next;
71 /// };
72 ///
73 /// would be represented in the SPIR-V module as:
74 ///
75 /// OpName %A "A"
76 /// OpTypeForwardPointer %APtr Generic
77 /// %A = OpTypeStruct %APtr
78 /// %APtr = OpTypePointer Generic %A
79 ///
80 /// This means that the spirv::StructType cannot be fully constructed directly
81 /// when the Deserializer encounters it. Instead we create a
82 /// DeferredStructTypeInfo that contains all the information we know about the
83 /// spirv::StructType. Once all forward references for the struct are resolved,
84 /// the struct's body is set with all member info.
87 
88  // A list of all unresolved member types for the struct. First element of each
89  // item is operand ID, second element is member index in the struct.
91 
92  // The list of member types. For unresolved members, this list contains
93  // place-holder empty types that will be updated later.
97 };
98 
99 /// A struct that collects the info needed to materialize/emit a
100 /// SpecConstantOperation op.
102  spirv::Opcode enclodesOpcode;
103  uint32_t resultTypeID;
105 };
106 
107 //===----------------------------------------------------------------------===//
108 // Deserializer Declaration
109 //===----------------------------------------------------------------------===//
110 
111 /// A SPIR-V module serializer.
112 ///
113 /// A SPIR-V binary module is a single linear stream of instructions; each
114 /// instruction is composed of 32-bit words. The first word of an instruction
115 /// records the total number of words of that instruction using the 16
116 /// higher-order bits. So this deserializer uses that to get instruction
117 /// boundary and parse instructions and build a SPIR-V ModuleOp gradually.
118 ///
119 // TODO: clean up created ops on errors
121 public:
122  /// Creates a deserializer for the given SPIR-V `binary` module.
123  /// The SPIR-V ModuleOp will be created into `context.
124  explicit Deserializer(ArrayRef<uint32_t> binary, MLIRContext *context);
125 
126  /// Deserializes the remembered SPIR-V binary module.
128 
129  /// Collects the final SPIR-V ModuleOp.
131 
132 private:
133  //===--------------------------------------------------------------------===//
134  // Module structure
135  //===--------------------------------------------------------------------===//
136 
137  /// Initializes the `module` ModuleOp in this deserializer instance.
138  OwningOpRef<spirv::ModuleOp> createModuleOp();
139 
140  /// Processes SPIR-V module header in `binary`.
141  LogicalResult processHeader();
142 
143  /// Processes the SPIR-V OpCapability with `operands` and updates bookkeeping
144  /// in the deserializer.
145  LogicalResult processCapability(ArrayRef<uint32_t> operands);
146 
147  /// Processes the SPIR-V OpExtension with `operands` and updates bookkeeping
148  /// in the deserializer.
149  LogicalResult processExtension(ArrayRef<uint32_t> words);
150 
151  /// Processes the SPIR-V OpExtInstImport with `operands` and updates
152  /// bookkeeping in the deserializer.
153  LogicalResult processExtInstImport(ArrayRef<uint32_t> words);
154 
155  /// Attaches (version, capabilities, extensions) triple to `module` as an
156  /// attribute.
157  void attachVCETriple();
158 
159  /// Processes the SPIR-V OpMemoryModel with `operands` and updates `module`.
160  LogicalResult processMemoryModel(ArrayRef<uint32_t> operands);
161 
162  /// Process SPIR-V OpName with `operands`.
163  LogicalResult processName(ArrayRef<uint32_t> operands);
164 
165  /// Processes an OpDecorate instruction.
166  LogicalResult processDecoration(ArrayRef<uint32_t> words);
167 
168  // Processes an OpMemberDecorate instruction.
169  LogicalResult processMemberDecoration(ArrayRef<uint32_t> words);
170 
171  /// Processes an OpMemberName instruction.
172  LogicalResult processMemberName(ArrayRef<uint32_t> words);
173 
174  /// Gets the function op associated with a result <id> of OpFunction.
175  spirv::FuncOp getFunction(uint32_t id) { return funcMap.lookup(id); }
176 
177  /// Processes the SPIR-V function at the current `offset` into `binary`.
178  /// The operands to the OpFunction instruction is passed in as ``operands`.
179  /// This method processes each instruction inside the function and dispatches
180  /// them to their handler method accordingly.
181  LogicalResult processFunction(ArrayRef<uint32_t> operands);
182 
183  /// Processes OpFunctionEnd and finalizes function. This wires up block
184  /// argument created from OpPhi instructions and also structurizes control
185  /// flow.
186  LogicalResult processFunctionEnd(ArrayRef<uint32_t> operands);
187 
188  /// Gets the constant's attribute and type associated with the given <id>.
189  std::optional<std::pair<Attribute, Type>> getConstant(uint32_t id);
190 
191  /// Gets the info needed to materialize the spec constant operation op
192  /// associated with the given <id>.
193  std::optional<SpecConstOperationMaterializationInfo>
194  getSpecConstantOperation(uint32_t id);
195 
196  /// Gets the constant's integer attribute with the given <id>. Returns a
197  /// null IntegerAttr if the given is not registered or does not correspond
198  /// to an integer constant.
199  IntegerAttr getConstantInt(uint32_t id);
200 
201  /// Returns a symbol to be used for the function name with the given
202  /// result <id>. This tries to use the function's OpName if
203  /// exists; otherwise creates one based on the <id>.
204  std::string getFunctionSymbol(uint32_t id);
205 
206  /// Returns a symbol to be used for the specialization constant with the given
207  /// result <id>. This tries to use the specialization constant's OpName if
208  /// exists; otherwise creates one based on the <id>.
209  std::string getSpecConstantSymbol(uint32_t id);
210 
211  /// Gets the specialization constant with the given result <id>.
212  spirv::SpecConstantOp getSpecConstant(uint32_t id) {
213  return specConstMap.lookup(id);
214  }
215 
216  /// Gets the composite specialization constant with the given result <id>.
217  spirv::SpecConstantCompositeOp getSpecConstantComposite(uint32_t id) {
218  return specConstCompositeMap.lookup(id);
219  }
220 
221  /// Creates a spirv::SpecConstantOp.
222  spirv::SpecConstantOp createSpecConstant(Location loc, uint32_t resultID,
223  TypedAttr defaultValue);
224 
225  /// Processes the OpVariable instructions at current `offset` into `binary`.
226  /// It is expected that this method is used for variables that are to be
227  /// defined at module scope and will be deserialized into a
228  /// spirv.GlobalVariable instruction.
229  LogicalResult processGlobalVariable(ArrayRef<uint32_t> operands);
230 
231  /// Gets the global variable associated with a result <id> of OpVariable.
232  spirv::GlobalVariableOp getGlobalVariable(uint32_t id) {
233  return globalVariableMap.lookup(id);
234  }
235 
236  /// Sets the function argument's attributes. |argID| is the function
237  /// argument's result <id>, and |argIndex| is its index in the function's
238  /// argument list.
239  LogicalResult setFunctionArgAttrs(uint32_t argID,
240  SmallVectorImpl<Attribute> &argAttrs,
241  size_t argIndex);
242 
243  /// Gets the symbol name from the name of decoration.
244  StringAttr getSymbolDecoration(StringRef decorationName) {
245  auto attrName = llvm::convertToSnakeFromCamelCase(decorationName);
246  return opBuilder.getStringAttr(attrName);
247  }
248 
249  //===--------------------------------------------------------------------===//
250  // Type
251  //===--------------------------------------------------------------------===//
252 
253  /// Gets type for a given result <id>.
254  Type getType(uint32_t id) { return typeMap.lookup(id); }
255 
256  /// Get the type associated with the result <id> of an OpUndef.
257  Type getUndefType(uint32_t id) { return undefMap.lookup(id); }
258 
259  /// Returns true if the given `type` is for SPIR-V void type.
260  bool isVoidType(Type type) const { return isa<NoneType>(type); }
261 
262  /// Processes a SPIR-V type instruction with given `opcode` and `operands` and
263  /// registers the type into `module`.
264  LogicalResult processType(spirv::Opcode opcode, ArrayRef<uint32_t> operands);
265 
266  LogicalResult processOpTypePointer(ArrayRef<uint32_t> operands);
267 
268  LogicalResult processArrayType(ArrayRef<uint32_t> operands);
269 
270  LogicalResult processCooperativeMatrixTypeKHR(ArrayRef<uint32_t> operands);
271 
272  LogicalResult processCooperativeMatrixTypeNV(ArrayRef<uint32_t> operands);
273 
274  LogicalResult processFunctionType(ArrayRef<uint32_t> operands);
275 
276  LogicalResult processJointMatrixType(ArrayRef<uint32_t> operands);
277 
278  LogicalResult processImageType(ArrayRef<uint32_t> operands);
279 
280  LogicalResult processSampledImageType(ArrayRef<uint32_t> operands);
281 
282  LogicalResult processRuntimeArrayType(ArrayRef<uint32_t> operands);
283 
284  LogicalResult processStructType(ArrayRef<uint32_t> operands);
285 
286  LogicalResult processMatrixType(ArrayRef<uint32_t> operands);
287 
288  LogicalResult processTypeForwardPointer(ArrayRef<uint32_t> operands);
289 
290  //===--------------------------------------------------------------------===//
291  // Constant
292  //===--------------------------------------------------------------------===//
293 
294  /// Processes a SPIR-V Op{|Spec}Constant instruction with the given
295  /// `operands`. `isSpec` indicates whether this is a specialization constant.
296  LogicalResult processConstant(ArrayRef<uint32_t> operands, bool isSpec);
297 
298  /// Processes a SPIR-V Op{|Spec}Constant{True|False} instruction with the
299  /// given `operands`. `isSpec` indicates whether this is a specialization
300  /// constant.
301  LogicalResult processConstantBool(bool isTrue, ArrayRef<uint32_t> operands,
302  bool isSpec);
303 
304  /// Processes a SPIR-V OpConstantComposite instruction with the given
305  /// `operands`.
306  LogicalResult processConstantComposite(ArrayRef<uint32_t> operands);
307 
308  /// Processes a SPIR-V OpSpecConstantComposite instruction with the given
309  /// `operands`.
310  LogicalResult processSpecConstantComposite(ArrayRef<uint32_t> operands);
311 
312  /// Processes a SPIR-V OpSpecConstantOp instruction with the given
313  /// `operands`.
314  LogicalResult processSpecConstantOperation(ArrayRef<uint32_t> operands);
315 
316  /// Materializes/emits an OpSpecConstantOp instruction.
317  Value materializeSpecConstantOperation(uint32_t resultID,
318  spirv::Opcode enclosedOpcode,
319  uint32_t resultTypeID,
320  ArrayRef<uint32_t> enclosedOpOperands);
321 
322  /// Processes a SPIR-V OpConstantNull instruction with the given `operands`.
323  LogicalResult processConstantNull(ArrayRef<uint32_t> operands);
324 
325  //===--------------------------------------------------------------------===//
326  // Debug
327  //===--------------------------------------------------------------------===//
328 
329  /// Discontinues any source-level location information that might be active
330  /// from a previous OpLine instruction.
331  void clearDebugLine();
332 
333  /// Creates a FileLineColLoc with the OpLine location information.
334  Location createFileLineColLoc(OpBuilder opBuilder);
335 
336  /// Processes a SPIR-V OpLine instruction with the given `operands`.
337  LogicalResult processDebugLine(ArrayRef<uint32_t> operands);
338 
339  /// Processes a SPIR-V OpString instruction with the given `operands`.
340  LogicalResult processDebugString(ArrayRef<uint32_t> operands);
341 
342  //===--------------------------------------------------------------------===//
343  // Control flow
344  //===--------------------------------------------------------------------===//
345 
346  /// Returns the block for the given label <id>.
347  Block *getBlock(uint32_t id) const { return blockMap.lookup(id); }
348 
349  // In SPIR-V, structured control flow is explicitly declared using merge
350  // instructions (OpSelectionMerge and OpLoopMerge). In the SPIR-V dialect,
351  // we use spirv.mlir.selection and spirv.mlir.loop to group structured control
352  // flow. The deserializer need to turn structured control flow marked with
353  // merge instructions into using spirv.mlir.selection/spirv.mlir.loop ops.
354  //
355  // Because structured control flow can nest and the basic block order have
356  // flexibility, we cannot isolate a structured selection/loop without
357  // deserializing all the blocks. So we use the following approach:
358  //
359  // 1. Deserialize all basic blocks in a function and create MLIR blocks for
360  // them into the function's region. In the meanwhile, keep a map between
361  // selection/loop header blocks to their corresponding merge (and continue)
362  // target blocks.
363  // 2. For each selection/loop header block, recursively get all basic blocks
364  // reachable (except the merge block) and put them in a newly created
365  // spirv.mlir.selection/spirv.mlir.loop's region. Structured control flow
366  // guarantees that we enter and exit in structured ways and the construct
367  // is nestable.
368  // 3. Put the new spirv.mlir.selection/spirv.mlir.loop op at the beginning of
369  // the
370  // old merge block and redirect all branches to the old header block to the
371  // old merge block (which contains the spirv.mlir.selection/spirv.mlir.loop
372  // op now).
373 
374  /// For OpPhi instructions, we use block arguments to represent them. OpPhi
375  /// encodes a list of (value, predecessor) pairs. At the time of handling the
376  /// block containing an OpPhi instruction, the predecessor block might not be
377  /// processed yet, also the value sent by it. So we need to defer handling
378  /// the block argument from the predecessors. We use the following approach:
379  ///
380  /// 1. For each OpPhi instruction, add a block argument to the current block
381  /// in construction. Record the block argument in `valueMap` so its uses
382  /// can be resolved. For the list of (value, predecessor) pairs, update
383  /// `blockPhiInfo` for bookkeeping.
384  /// 2. After processing all blocks, loop over `blockPhiInfo` to fix up each
385  /// block recorded there to create the proper block arguments on their
386  /// terminators.
387 
388  /// A data structure for containing a SPIR-V block's phi info. It will be
389  /// represented as block argument in SPIR-V dialect.
390  using BlockPhiInfo =
391  SmallVector<uint32_t, 2>; // The result <id> of the values sent
392 
393  /// Gets or creates the block corresponding to the given label <id>. The newly
394  /// created block will always be placed at the end of the current function.
395  Block *getOrCreateBlock(uint32_t id);
396 
397  LogicalResult processBranch(ArrayRef<uint32_t> operands);
398 
399  LogicalResult processBranchConditional(ArrayRef<uint32_t> operands);
400 
401  /// Processes a SPIR-V OpLabel instruction with the given `operands`.
402  LogicalResult processLabel(ArrayRef<uint32_t> operands);
403 
404  /// Processes a SPIR-V OpSelectionMerge instruction with the given `operands`.
405  LogicalResult processSelectionMerge(ArrayRef<uint32_t> operands);
406 
407  /// Processes a SPIR-V OpLoopMerge instruction with the given `operands`.
408  LogicalResult processLoopMerge(ArrayRef<uint32_t> operands);
409 
410  /// Processes a SPIR-V OpPhi instruction with the given `operands`.
411  LogicalResult processPhi(ArrayRef<uint32_t> operands);
412 
413  /// Creates block arguments on predecessors previously recorded when handling
414  /// OpPhi instructions.
415  LogicalResult wireUpBlockArgument();
416 
417  /// Extracts blocks belonging to a structured selection/loop into a
418  /// spirv.mlir.selection/spirv.mlir.loop op. This method iterates until all
419  /// blocks declared as selection/loop headers are handled.
420  LogicalResult structurizeControlFlow();
421 
422  //===--------------------------------------------------------------------===//
423  // Instruction
424  //===--------------------------------------------------------------------===//
425 
426  /// Get the Value associated with a result <id>.
427  ///
428  /// This method materializes normal constants and inserts "casting" ops
429  /// (`spirv.mlir.addressof` and `spirv.mlir.referenceof`) to turn an symbol
430  /// into a SSA value for handling uses of module scope constants/variables in
431  /// functions.
432  Value getValue(uint32_t id);
433 
434  /// Slices the first instruction out of `binary` and returns its opcode and
435  /// operands via `opcode` and `operands` respectively. Returns failure if
436  /// there is no more remaining instructions (`expectedOpcode` will be used to
437  /// compose the error message) or the next instruction is malformed.
439  sliceInstruction(spirv::Opcode &opcode, ArrayRef<uint32_t> &operands,
440  std::optional<spirv::Opcode> expectedOpcode = std::nullopt);
441 
442  /// Processes a SPIR-V instruction with the given `opcode` and `operands`.
443  /// This method is the main entrance for handling SPIR-V instruction; it
444  /// checks the instruction opcode and dispatches to the corresponding handler.
445  /// Processing of Some instructions (like OpEntryPoint and OpExecutionMode)
446  /// might need to be deferred, since they contain forward references to <id>s
447  /// in the deserialized binary, but module in SPIR-V dialect expects these to
448  /// be ssa-uses.
449  LogicalResult processInstruction(spirv::Opcode opcode,
450  ArrayRef<uint32_t> operands,
451  bool deferInstructions = true);
452 
453  /// Processes a SPIR-V instruction from the given `operands`. It should
454  /// deserialize into an op with the given `opName` and `numOperands`.
455  /// This method is a generic one for dispatching any SPIR-V ops without
456  /// variadic operands and attributes in TableGen definitions.
457  LogicalResult processOpWithoutGrammarAttr(ArrayRef<uint32_t> words,
458  StringRef opName, bool hasResult,
459  unsigned numOperands);
460 
461  /// Processes a OpUndef instruction. Adds a spirv.Undef operation at the
462  /// current insertion point.
463  LogicalResult processUndef(ArrayRef<uint32_t> operands);
464 
465  /// Method to dispatch to the specialized deserialization function for an
466  /// operation in SPIR-V dialect that is a mirror of an instruction in the
467  /// SPIR-V spec. This is auto-generated from ODS. Dispatch is handled for
468  /// all operations in SPIR-V dialect that have hasOpcode == 1.
469  LogicalResult dispatchToAutogenDeserialization(spirv::Opcode opcode,
470  ArrayRef<uint32_t> words);
471 
472  /// Processes a SPIR-V OpExtInst with given `operands`. This slices the
473  /// entries of `operands` that specify the extended instruction set <id> and
474  /// the instruction opcode. The op deserializer is then invoked using the
475  /// other entries.
476  LogicalResult processExtInst(ArrayRef<uint32_t> operands);
477 
478  /// Dispatches the deserialization of extended instruction set operation based
479  /// on the extended instruction set name, and instruction opcode. This is
480  /// autogenerated from ODS.
482  dispatchToExtensionSetAutogenDeserialization(StringRef extensionSetName,
483  uint32_t instructionID,
484  ArrayRef<uint32_t> words);
485 
486  /// Method to deserialize an operation in the SPIR-V dialect that is a mirror
487  /// of an instruction in the SPIR-V spec. This is auto generated if hasOpcode
488  /// == 1 and autogenSerialization == 1 in ODS.
489  template <typename OpTy>
490  LogicalResult processOp(ArrayRef<uint32_t> words) {
491  return emitError(unknownLoc, "unsupported deserialization for ")
492  << OpTy::getOperationName() << " op";
493  }
494 
495 private:
496  /// The SPIR-V binary module.
497  ArrayRef<uint32_t> binary;
498 
499  /// Contains the data of the OpLine instruction which precedes the current
500  /// processing instruction.
501  std::optional<DebugLine> debugLine;
502 
503  /// The current word offset into the binary module.
504  unsigned curOffset = 0;
505 
506  /// MLIRContext to create SPIR-V ModuleOp into.
507  MLIRContext *context;
508 
509  // TODO: create Location subclass for binary blob
510  Location unknownLoc;
511 
512  /// The SPIR-V ModuleOp.
514 
515  /// The current function under construction.
516  std::optional<spirv::FuncOp> curFunction;
517 
518  /// The current block under construction.
519  Block *curBlock = nullptr;
520 
521  OpBuilder opBuilder;
522 
523  spirv::Version version = spirv::Version::V_1_0;
524 
525  /// The list of capabilities used by the module.
526  llvm::SmallSetVector<spirv::Capability, 4> capabilities;
527 
528  /// The list of extensions used by the module.
529  llvm::SmallSetVector<spirv::Extension, 2> extensions;
530 
531  // Result <id> to type mapping.
532  DenseMap<uint32_t, Type> typeMap;
533 
534  // Result <id> to constant attribute and type mapping.
535  ///
536  /// In the SPIR-V binary format, all constants are placed in the module and
537  /// shared by instructions at module level and in subsequent functions. But in
538  /// the SPIR-V dialect, we materialize the constant to where it's used in the
539  /// function. So when seeing a constant instruction in the binary format, we
540  /// don't immediately emit a constant op into the module, we keep its value
541  /// (and type) here. Later when it's used, we materialize the constant.
543 
544  // Result <id> to spec constant mapping.
546 
547  // Result <id> to composite spec constant mapping.
549 
550  /// Result <id> to info needed to materialize an OpSpecConstantOp
551  /// mapping.
553  specConstOperationMap;
554 
555  // Result <id> to variable mapping.
557 
558  // Result <id> to function mapping.
560 
561  // Result <id> to block mapping.
563 
564  // Header block to its merge (and continue) target mapping.
565  BlockMergeInfoMap blockMergeInfo;
566 
567  // For each pair of {predecessor, target} blocks, maps the pair of blocks to
568  // the list of phi arguments passed from predecessor to target.
569  DenseMap<std::pair<Block * /*predecessor*/, Block * /*target*/>, BlockPhiInfo>
570  blockPhiInfo;
571 
572  // Result <id> to value mapping.
573  DenseMap<uint32_t, Value> valueMap;
574 
575  // Mapping from result <id> to undef value of a type.
576  DenseMap<uint32_t, Type> undefMap;
577 
578  // Result <id> to name mapping.
580 
581  // Result <id> to debug info mapping.
582  DenseMap<uint32_t, StringRef> debugInfoMap;
583 
584  // Result <id> to decorations mapping.
586 
587  // Result <id> to type decorations.
588  DenseMap<uint32_t, uint32_t> typeDecorations;
589 
590  // Result <id> to member decorations.
591  // decorated-struct-type-<id> ->
592  // (struct-member-index -> (decoration -> decoration-operands))
593  DenseMap<uint32_t,
595  memberDecorationMap;
596 
597  // Result <id> to member name.
598  // struct-type-<id> -> (struct-member-index -> name)
600 
601  // Result <id> to extended instruction set name.
602  DenseMap<uint32_t, StringRef> extendedInstSets;
603 
604  // List of instructions that are processed in a deferred fashion (after an
605  // initial processing of the entire binary). Some operations like
606  // OpEntryPoint, and OpExecutionMode use forward references to function
607  // <id>s. In SPIR-V dialect the corresponding operations (spirv.EntryPoint and
608  // spirv.ExecutionMode) need these references resolved. So these instructions
609  // are deserialized and stored for processing once the entire binary is
610  // processed.
612  deferredInstructions;
613 
614  /// A list of IDs for all types forward-declared through OpTypeForwardPointer
615  /// instructions.
616  SetVector<uint32_t> typeForwardPointerIDs;
617 
618  /// A list of all structs which have unresolved member types.
619  SmallVector<DeferredStructTypeInfo, 0> deferredStructTypesInfos;
620 
621 #ifndef NDEBUG
622  /// A logger used to emit information during the deserialzation process.
623  llvm::ScopedPrinter logger;
624 #endif
625 };
626 
627 } // namespace spirv
628 } // namespace mlir
629 
630 #endif // MLIR_TARGET_SPIRV_DESERIALIZER_H
Block represents an ordered list of Operations.
Definition: Block.h:30
StringAttr getStringAttr(const Twine &bytes)
Definition: Builders.cpp:269
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
This class helps build Operations.
Definition: Builders.h:209
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
A SPIR-V module serializer.
Definition: Deserializer.h:120
LogicalResult deserialize()
Deserializes the remembered SPIR-V binary module.
Deserializer(ArrayRef< uint32_t > binary, MLIRContext *context)
Creates a deserializer for the given SPIR-V binary module.
OwningOpRef< spirv::ModuleOp > collect()
Collects the final SPIR-V ModuleOp.
SPIR-V struct type.
Definition: SPIRVTypes.h:293
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
A struct for containing a header block's merge and continue targets.
Definition: Deserializer.h:38
BlockMergeInfo(Location location, uint32_t control, Block *m, Block *c=nullptr)
Definition: Deserializer.h:47
BlockMergeInfo(Location location, uint32_t control)
Definition: Deserializer.h:44
A struct for containing OpLine instruction information.
Definition: Deserializer.h:53
A "deferred struct type" is a struct type with one or more member types not known when the Deserializ...
Definition: Deserializer.h:85
spirv::StructType deferredStructType
Definition: Deserializer.h:86
SmallVector< spirv::StructType::MemberDecorationInfo, 0 > memberDecorationsInfo
Definition: Deserializer.h:96
SmallVector< spirv::StructType::OffsetInfo, 0 > offsetInfo
Definition: Deserializer.h:95
SmallVector< Type, 4 > memberTypes
Definition: Deserializer.h:94
SmallVector< std::pair< uint32_t, unsigned >, 0 > unresolvedMemberTypes
Definition: Deserializer.h:90
A struct that collects the info needed to materialize/emit a SpecConstantOperation op.
Definition: Deserializer.h:101