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