MLIR 23.0.0git
DeserializeOps.cpp
Go to the documentation of this file.
1//===- DeserializeOps.cpp - MLIR SPIR-V Deserialization (Ops) -------------===//
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 the Deserializer methods for SPIR-V binary instructions.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Deserializer.h"
14
17#include "mlir/IR/Builders.h"
18#include "mlir/IR/Location.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/Support/Debug.h"
23#include <optional>
24
25using namespace mlir;
26
27#define DEBUG_TYPE "spirv-deserialization"
28
29//===----------------------------------------------------------------------===//
30// Utility Functions
31//===----------------------------------------------------------------------===//
32
33/// Extracts the opcode from the given first word of a SPIR-V instruction.
34static inline spirv::Opcode extractOpcode(uint32_t word) {
35 return static_cast<spirv::Opcode>(word & 0xffff);
36}
37
38//===----------------------------------------------------------------------===//
39// Instruction
40//===----------------------------------------------------------------------===//
41
43 if (auto constInfo = getConstant(id)) {
44 // Materialize a `spirv.Constant` op at every use site.
45 return spirv::ConstantOp::create(opBuilder, unknownLoc, constInfo->second,
46 constInfo->first);
47 }
48 if (std::optional<std::pair<Attribute, Type>> constCompositeReplicateInfo =
50 return spirv::EXTConstantCompositeReplicateOp::create(
51 opBuilder, unknownLoc, constCompositeReplicateInfo->second,
52 constCompositeReplicateInfo->first);
53 }
54 if (auto varOp = getGlobalVariable(id)) {
55 auto addressOfOp =
56 spirv::AddressOfOp::create(opBuilder, unknownLoc, varOp.getType(),
57 SymbolRefAttr::get(varOp.getOperation()));
58 return addressOfOp.getPointer();
59 }
60 if (auto constOp = getSpecConstant(id)) {
61 auto referenceOfOp = spirv::ReferenceOfOp::create(
62 opBuilder, unknownLoc, constOp.getDefaultValue().getType(),
63 SymbolRefAttr::get(constOp.getOperation()));
64 return referenceOfOp.getReference();
65 }
66 if (SpecConstantCompositeOp specConstCompositeOp =
68 auto referenceOfOp = spirv::ReferenceOfOp::create(
69 opBuilder, unknownLoc, specConstCompositeOp.getType(),
70 SymbolRefAttr::get(specConstCompositeOp.getOperation()));
71 return referenceOfOp.getReference();
72 }
73 if (auto specConstCompositeReplicateOp =
75 auto referenceOfOp = spirv::ReferenceOfOp::create(
76 opBuilder, unknownLoc, specConstCompositeReplicateOp.getType(),
77 SymbolRefAttr::get(specConstCompositeReplicateOp.getOperation()));
78 return referenceOfOp.getReference();
79 }
80 if (auto specConstOperationInfo = getSpecConstantOperation(id)) {
82 id, specConstOperationInfo->enclodesOpcode,
83 specConstOperationInfo->resultTypeID,
84 specConstOperationInfo->enclosedOpOperands);
85 }
86 if (auto undef = getUndefType(id)) {
87 return spirv::UndefOp::create(opBuilder, unknownLoc, undef);
88 }
89 if (std::optional<spirv::GraphConstantARMOpMaterializationInfo>
90 graphConstantARMInfo = getGraphConstantARM(id)) {
91 IntegerAttr graphConstantID = graphConstantARMInfo->graphConstantID;
92 Type resultType = graphConstantARMInfo->resultType;
93 return spirv::GraphConstantARMOp::create(opBuilder, unknownLoc, resultType,
94 graphConstantID);
95 }
96 return valueMap.lookup(id);
97}
98
100 spirv::Opcode &opcode, ArrayRef<uint32_t> &operands,
101 std::optional<spirv::Opcode> expectedOpcode) {
102 auto binarySize = binary.size();
103 if (curOffset >= binarySize) {
104 return emitError(unknownLoc, "expected ")
105 << (expectedOpcode ? spirv::stringifyOpcode(*expectedOpcode)
106 : "more")
107 << " instruction";
108 }
109
110 // For each instruction, get its word count from the first word to slice it
111 // from the stream properly, and then dispatch to the instruction handler.
112
113 uint32_t wordCount = binary[curOffset] >> 16;
114
115 if (wordCount == 0)
116 return emitError(unknownLoc, "word count cannot be zero");
117
118 uint32_t nextOffset = curOffset + wordCount;
119 if (nextOffset > binarySize)
120 return emitError(unknownLoc, "insufficient words for the last instruction");
121
122 opcode = extractOpcode(binary[curOffset]);
123 operands = binary.slice(curOffset + 1, wordCount - 1);
124 curOffset = nextOffset;
125 return success();
126}
127
129 spirv::Opcode opcode, ArrayRef<uint32_t> operands, bool deferInstructions) {
130 LLVM_DEBUG(logger.startLine() << "[inst] processing instruction "
131 << spirv::stringifyOpcode(opcode) << "\n");
132
133 // First dispatch all the instructions whose opcode does not correspond to
134 // those that have a direct mirror in the SPIR-V dialect
135 switch (opcode) {
136 case spirv::Opcode::OpCapability:
137 return processCapability(operands);
138 case spirv::Opcode::OpExtension:
139 return processExtension(operands);
140 case spirv::Opcode::OpExtInst:
141 return processExtInst(operands);
142 case spirv::Opcode::OpExtInstImport:
143 return processExtInstImport(operands);
144 case spirv::Opcode::OpMemberName:
145 return processMemberName(operands);
146 case spirv::Opcode::OpMemoryModel:
147 return processMemoryModel(operands);
148 case spirv::Opcode::OpEntryPoint:
149 case spirv::Opcode::OpExecutionMode:
150 case spirv::Opcode::OpExecutionModeId:
151 if (deferInstructions) {
152 deferredInstructions.emplace_back(opcode, operands);
153 return success();
154 }
155 break;
156 case spirv::Opcode::OpVariable:
157 if (isa<spirv::ModuleOp>(opBuilder.getBlock()->getParentOp())) {
158 return processGlobalVariable(operands);
159 }
160 break;
161 case spirv::Opcode::OpLine:
162 return processDebugLine(operands);
163 case spirv::Opcode::OpNoLine:
165 return success();
166 case spirv::Opcode::OpName:
167 return processName(operands);
168 case spirv::Opcode::OpString:
169 return processDebugString(operands);
170 case spirv::Opcode::OpModuleProcessed:
171 case spirv::Opcode::OpSource:
172 case spirv::Opcode::OpSourceContinued:
173 case spirv::Opcode::OpSourceExtension:
174 // TODO: This is debug information embedded in the binary which should be
175 // translated into the spirv.module.
176 return success();
177 case spirv::Opcode::OpTypeVoid:
178 case spirv::Opcode::OpTypeBool:
179 case spirv::Opcode::OpTypeInt:
180 case spirv::Opcode::OpTypeFloat:
181 case spirv::Opcode::OpTypeVector:
182 case spirv::Opcode::OpTypeMatrix:
183 case spirv::Opcode::OpTypeArray:
184 case spirv::Opcode::OpTypeFunction:
185 case spirv::Opcode::OpTypeImage:
186 case spirv::Opcode::OpTypeSampler:
187 case spirv::Opcode::OpTypeSampledImage:
188 case spirv::Opcode::OpTypeRuntimeArray:
189 case spirv::Opcode::OpTypeStruct:
190 case spirv::Opcode::OpTypePointer:
191 case spirv::Opcode::OpTypeTensorARM:
192 case spirv::Opcode::OpTypeGraphARM:
193 case spirv::Opcode::OpTypeCooperativeMatrixKHR:
194 return processType(opcode, operands);
195 case spirv::Opcode::OpTypeForwardPointer:
196 return processTypeForwardPointer(operands);
197 case spirv::Opcode::OpConstant:
198 return processConstant(operands, /*isSpec=*/false);
199 case spirv::Opcode::OpSpecConstant:
200 return processConstant(operands, /*isSpec=*/true);
201 case spirv::Opcode::OpConstantComposite:
202 return processConstantComposite(operands);
203 case spirv::Opcode::OpConstantCompositeReplicateEXT:
205 case spirv::Opcode::OpSpecConstantComposite:
206 return processSpecConstantComposite(operands);
207 case spirv::Opcode::OpSpecConstantCompositeReplicateEXT:
209 case spirv::Opcode::OpSpecConstantOp:
210 return processSpecConstantOperation(operands);
211 case spirv::Opcode::OpConstantTrue:
212 return processConstantBool(/*isTrue=*/true, operands, /*isSpec=*/false);
213 case spirv::Opcode::OpSpecConstantTrue:
214 return processConstantBool(/*isTrue=*/true, operands, /*isSpec=*/true);
215 case spirv::Opcode::OpConstantFalse:
216 return processConstantBool(/*isTrue=*/false, operands, /*isSpec=*/false);
217 case spirv::Opcode::OpSpecConstantFalse:
218 return processConstantBool(/*isTrue=*/false, operands, /*isSpec=*/true);
219 case spirv::Opcode::OpConstantNull:
220 return processConstantNull(operands);
221 case spirv::Opcode::OpGraphConstantARM:
222 return processGraphConstantARM(operands);
223 case spirv::Opcode::OpDecorate:
224 return processDecoration(operands);
225 case spirv::Opcode::OpMemberDecorate:
226 return processMemberDecoration(operands);
227 case spirv::Opcode::OpFunction:
228 return processFunction(operands);
229 case spirv::Opcode::OpGraphEntryPointARM:
230 if (deferInstructions) {
231 deferredInstructions.emplace_back(opcode, operands);
232 return success();
233 }
234 return processGraphEntryPointARM(operands);
235 case spirv::Opcode::OpGraphARM:
236 return processGraphARM(operands);
237 case spirv::Opcode::OpGraphSetOutputARM:
238 return processOpGraphSetOutputARM(operands);
239 case spirv::Opcode::OpGraphEndARM:
240 return processGraphEndARM(operands);
241 case spirv::Opcode::OpLabel:
242 return processLabel(operands);
243 case spirv::Opcode::OpBranch:
244 return processBranch(operands);
245 case spirv::Opcode::OpBranchConditional:
246 return processBranchConditional(operands);
247 case spirv::Opcode::OpSelectionMerge:
248 return processSelectionMerge(operands);
249 case spirv::Opcode::OpLoopMerge:
250 return processLoopMerge(operands);
251 case spirv::Opcode::OpPhi:
252 return processPhi(operands);
253 case spirv::Opcode::OpSwitch:
254 return processSwitch(operands);
255 case spirv::Opcode::OpUndef:
256 return processUndef(operands);
257 default:
258 break;
259 }
260 return dispatchToAutogenDeserialization(opcode, operands);
261}
262
264 ArrayRef<uint32_t> words, StringRef opName, bool hasResult,
265 unsigned numOperands) {
266 SmallVector<Type, 1> resultTypes;
267 uint32_t valueID = 0;
268
269 size_t wordIndex = 0;
270 if (hasResult) {
271 if (wordIndex >= words.size())
272 return emitError(unknownLoc,
273 "expected result type <id> while deserializing for ")
274 << opName;
275
276 // Decode the type <id>
277 auto type = getType(words[wordIndex]);
278 if (!type)
279 return emitError(unknownLoc, "unknown type result <id>: ")
280 << words[wordIndex];
281 resultTypes.push_back(type);
282 ++wordIndex;
283
284 // Decode the result <id>
285 if (wordIndex >= words.size())
286 return emitError(unknownLoc,
287 "expected result <id> while deserializing for ")
288 << opName;
289 valueID = words[wordIndex];
290 ++wordIndex;
291 }
292
293 SmallVector<Value, 4> operands;
295
296 // Decode operands
297 size_t operandIndex = 0;
298 for (; operandIndex < numOperands && wordIndex < words.size();
299 ++operandIndex, ++wordIndex) {
300 auto arg = getValue(words[wordIndex]);
301 if (!arg)
302 return emitError(unknownLoc, "unknown result <id>: ") << words[wordIndex];
303 operands.push_back(arg);
304 }
305 if (operandIndex != numOperands) {
306 return emitError(
307 unknownLoc,
308 "found less operands than expected when deserializing for ")
309 << opName << "; only " << operandIndex << " of " << numOperands
310 << " processed";
311 }
312 if (wordIndex != words.size()) {
313 return emitError(
314 unknownLoc,
315 "found more operands than expected when deserializing for ")
316 << opName << "; only " << wordIndex << " of " << words.size()
317 << " processed";
318 }
319
320 // Attach attributes from decorations
321 if (decorations.count(valueID)) {
322 auto attrs = decorations[valueID].getAttrs();
323 attributes.append(attrs.begin(), attrs.end());
324 }
325
326 // Create the op and update bookkeeping maps
327 Location loc = createFileLineColLoc(opBuilder);
328 OperationState opState(loc, opName);
329 opState.addOperands(operands);
330 if (hasResult)
331 opState.addTypes(resultTypes);
332 opState.addAttributes(attributes);
333 Operation *op = opBuilder.create(opState);
334 if (hasResult)
335 valueMap[valueID] = op->getResult(0);
336
339
340 return success();
341}
342
344 if (operands.size() != 2) {
345 return emitError(unknownLoc, "OpUndef instruction must have two operands");
346 }
347 auto type = getType(operands[0]);
348 if (!type) {
349 return emitError(unknownLoc, "unknown type <id> with OpUndef instruction");
350 }
351 undefMap[operands[1]] = type;
352 return success();
353}
354
356 if (operands.size() < 4) {
357 return emitError(unknownLoc,
358 "OpExtInst must have at least 4 operands, result type "
359 "<id>, result <id>, set <id> and instruction opcode");
360 }
361 if (!extendedInstSets.count(operands[2])) {
362 return emitError(unknownLoc, "undefined set <id> in OpExtInst");
363 }
364 SmallVector<uint32_t, 4> slicedOperands;
365 slicedOperands.append(operands.begin(), std::next(operands.begin(), 2));
366 slicedOperands.append(std::next(operands.begin(), 4), operands.end());
368 extendedInstSets[operands[2]], operands[3], slicedOperands);
369}
370
371namespace mlir {
372namespace spirv {
373
374template <>
375LogicalResult
377 unsigned wordIndex = 0;
378 if (wordIndex >= words.size()) {
379 return emitError(unknownLoc,
380 "missing Execution Model specification in OpEntryPoint");
381 }
382 auto execModel = spirv::ExecutionModelAttr::get(
383 context, static_cast<spirv::ExecutionModel>(words[wordIndex++]));
384 if (wordIndex >= words.size()) {
385 return emitError(unknownLoc, "missing <id> in OpEntryPoint");
386 }
387 // Get the function <id>
388 auto fnID = words[wordIndex++];
389 // Get the function name
390 auto fnName = decodeStringLiteral(words, wordIndex);
391 // Verify that the function <id> matches the fnName
392 auto parsedFunc = getFunction(fnID);
393 if (!parsedFunc) {
394 return emitError(unknownLoc, "no function matching <id> ") << fnID;
395 }
396 if (parsedFunc.getName() != fnName) {
397 // The deserializer uses "spirv_fn_<id>" as the function name if the input
398 // SPIR-V blob does not contain a name for it. We should use a more clear
399 // indication for such case rather than relying on naming details.
400 if (!parsedFunc.getName().starts_with("spirv_fn_"))
401 return emitError(unknownLoc,
402 "function name mismatch between OpEntryPoint "
403 "and OpFunction with <id> ")
404 << fnID << ": " << fnName << " vs. " << parsedFunc.getName();
405 parsedFunc.setName(fnName);
406 }
408 while (wordIndex < words.size()) {
409 auto arg = getGlobalVariable(words[wordIndex]);
410 if (!arg) {
411 return emitError(unknownLoc, "undefined result <id> ")
412 << words[wordIndex] << " while decoding OpEntryPoint";
413 }
414 interface.push_back(SymbolRefAttr::get(arg.getOperation()));
415 wordIndex++;
416 }
417 spirv::EntryPointOp::create(
418 opBuilder, unknownLoc, execModel,
419 SymbolRefAttr::get(opBuilder.getContext(), fnName),
420 opBuilder.getArrayAttr(interface));
421 return success();
422}
423
424template <>
425LogicalResult
427 unsigned wordIndex = 0;
428 if (wordIndex >= words.size()) {
429 return emitError(unknownLoc,
430 "missing function result <id> in OpExecutionMode");
431 }
432 // Get the function <id> to get the name of the function
433 auto fnID = words[wordIndex++];
434 auto fn = getFunction(fnID);
435 if (!fn) {
436 return emitError(unknownLoc, "no function matching <id> ") << fnID;
437 }
438 // Get the Execution mode
439 if (wordIndex >= words.size()) {
440 return emitError(unknownLoc, "missing Execution Mode in OpExecutionMode");
441 }
442 auto execMode = spirv::ExecutionModeAttr::get(
443 context, static_cast<spirv::ExecutionMode>(words[wordIndex++]));
444
445 // Get the values
446 SmallVector<Attribute, 4> attrListElems;
447 while (wordIndex < words.size()) {
448 attrListElems.push_back(opBuilder.getI32IntegerAttr(words[wordIndex++]));
449 }
450 auto values = opBuilder.getArrayAttr(attrListElems);
451 spirv::ExecutionModeOp::create(
452 opBuilder, unknownLoc,
453 SymbolRefAttr::get(opBuilder.getContext(), fn.getName()), execMode,
454 values);
455 return success();
456}
457
458template <>
459LogicalResult
461 unsigned wordIndex = 0;
462 unsigned const wordsSize = words.size();
463 if (wordIndex >= wordsSize)
464 return emitError(unknownLoc,
465 "missing function result <id> in OpExecutionModeId");
466
467 // Get the function <id> to get the name of the function.
468 uint32_t fnID = words[wordIndex++];
469 FuncOp fn = getFunction(fnID);
470 if (!fn)
471 return emitError(unknownLoc, "no function matching <id> ") << fnID;
472
473 // Get the Execution mode.
474 if (wordIndex >= wordsSize)
475 return emitError(unknownLoc, "missing Execution Mode in OpExecutionModeId");
476
477 ExecutionModeAttr execMode = spirv::ExecutionModeAttr::get(
478 context, static_cast<spirv::ExecutionMode>(words[wordIndex++]));
479
480 // Get the values.
481 SmallVector<Attribute, 4> attrListElems;
482 while (wordIndex < words.size()) {
483 std::string id = getSpecConstantSymbol(words[wordIndex++]);
484 attrListElems.push_back(FlatSymbolRefAttr::get(context, id));
485 }
486 ArrayAttr values = opBuilder.getArrayAttr(attrListElems);
487 spirv::ExecutionModeIdOp::create(
488 opBuilder, unknownLoc,
489 SymbolRefAttr::get(opBuilder.getContext(), fn.getName()), execMode,
490 values);
491 return success();
492}
493
494template <>
495LogicalResult
497 if (operands.size() < 3) {
498 return emitError(unknownLoc,
499 "OpFunctionCall must have at least 3 operands");
500 }
501
502 Type resultType = getType(operands[0]);
503 if (!resultType) {
504 return emitError(unknownLoc, "undefined result type from <id> ")
505 << operands[0];
506 }
507
508 // Use null type to mean no result type.
509 if (isVoidType(resultType))
510 resultType = nullptr;
511
512 auto resultID = operands[1];
513 auto functionID = operands[2];
514
515 auto functionName = getFunctionSymbol(functionID);
516
517 SmallVector<Value, 4> arguments;
518 for (auto operand : llvm::drop_begin(operands, 3)) {
519 auto value = getValue(operand);
520 if (!value) {
521 return emitError(unknownLoc, "unknown <id> ")
522 << operand << " used by OpFunctionCall";
523 }
524 arguments.push_back(value);
525 }
526
527 auto opFunctionCall = spirv::FunctionCallOp::create(
528 opBuilder, unknownLoc, resultType,
529 SymbolRefAttr::get(opBuilder.getContext(), functionName), arguments);
530
531 if (resultType)
532 valueMap[resultID] = opFunctionCall.getResult(0);
533 return success();
534}
535
536template <>
537LogicalResult
539 SmallVector<Type, 1> resultTypes;
540 size_t wordIndex = 0;
541 SmallVector<Value, 4> operands;
543
544 if (wordIndex < words.size()) {
545 auto arg = getValue(words[wordIndex]);
546
547 if (!arg) {
548 return emitError(unknownLoc, "unknown result <id> : ")
549 << words[wordIndex];
550 }
551
552 operands.push_back(arg);
553 wordIndex++;
554 }
555
556 if (wordIndex < words.size()) {
557 auto arg = getValue(words[wordIndex]);
558
559 if (!arg) {
560 return emitError(unknownLoc, "unknown result <id> : ")
561 << words[wordIndex];
562 }
563
564 operands.push_back(arg);
565 wordIndex++;
566 }
567
568 bool isAlignedAttr = false;
569
570 if (wordIndex < words.size()) {
571 auto attrValue = words[wordIndex++];
572 auto attr = opBuilder.getAttr<spirv::MemoryAccessAttr>(
573 static_cast<spirv::MemoryAccess>(attrValue));
574 attributes.push_back(
575 opBuilder.getNamedAttr(attributeName<MemoryAccess>(), attr));
576 isAlignedAttr = (attrValue == 2);
577 }
578
579 if (isAlignedAttr && wordIndex < words.size()) {
580 attributes.push_back(opBuilder.getNamedAttr(
581 "alignment", opBuilder.getI32IntegerAttr(words[wordIndex++])));
582 }
583
584 if (wordIndex < words.size()) {
585 auto attrValue = words[wordIndex++];
586 auto attr = opBuilder.getAttr<spirv::MemoryAccessAttr>(
587 static_cast<spirv::MemoryAccess>(attrValue));
588 attributes.push_back(opBuilder.getNamedAttr("source_memory_access", attr));
589 }
590
591 if (wordIndex < words.size()) {
592 attributes.push_back(opBuilder.getNamedAttr(
593 "source_alignment", opBuilder.getI32IntegerAttr(words[wordIndex++])));
594 }
595
596 if (wordIndex != words.size()) {
597 return emitError(unknownLoc,
598 "found more operands than expected when deserializing "
599 "spirv::CopyMemoryOp, only ")
600 << wordIndex << " of " << words.size() << " processed";
601 }
602
603 Location loc = createFileLineColLoc(opBuilder);
604 spirv::CopyMemoryOp::create(opBuilder, loc, resultTypes, operands,
605 attributes);
606
607 return success();
608}
609
610template <>
612 ArrayRef<uint32_t> words) {
613 if (words.size() != 4) {
614 return emitError(unknownLoc,
615 "expected 4 words in GenericCastToPtrExplicitOp"
616 " but got : ")
617 << words.size();
618 }
619 SmallVector<Type, 1> resultTypes;
620 SmallVector<Value, 4> operands;
621 uint32_t valueID = 0;
622 auto type = getType(words[0]);
623
624 if (!type)
625 return emitError(unknownLoc, "unknown type result <id> : ") << words[0];
626 resultTypes.push_back(type);
627
628 valueID = words[1];
629
630 auto arg = getValue(words[2]);
631 if (!arg)
632 return emitError(unknownLoc, "unknown result <id> : ") << words[2];
633 operands.push_back(arg);
634
635 Location loc = createFileLineColLoc(opBuilder);
636 Operation *op = spirv::GenericCastToPtrExplicitOp::create(
637 opBuilder, loc, resultTypes, operands);
638 valueMap[valueID] = op->getResult(0);
639 return success();
640}
641
642// Pull in auto-generated Deserializer::dispatchToAutogenDeserialization() and
643// various Deserializer::processOp<...>() specializations.
644#define GET_DESERIALIZATION_FNS
645#include "mlir/Dialect/SPIRV/IR/SPIRVSerialization.inc"
646
647} // namespace spirv
648} // namespace mlir
return success()
static spirv::Opcode extractOpcode(uint32_t word)
Extracts the opcode from the given first word of a SPIR-V instruction.
static FlatSymbolRefAttr get(StringAttr value)
Construct a symbol reference for the given value name.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
This class provides the API for ops that are known to be terminators.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Definition Operation.h:775
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition Operation.h:433
static Operation * create(Location location, OperationName name, TypeRange resultTypes, ValueRange operands, NamedAttrList &&attributes, PropertyRef properties, BlockRange successors, unsigned numRegions)
Create a new Operation with the specific fields.
Definition Operation.cpp:66
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
Value materializeSpecConstantOperation(uint32_t resultID, spirv::Opcode enclosedOpcode, uint32_t resultTypeID, ArrayRef< uint32_t > enclosedOpOperands)
Materializes/emits an OpSpecConstantOp instruction.
Value getValue(uint32_t id)
Get the Value associated with a result <id>.
LogicalResult processGlobalVariable(ArrayRef< uint32_t > operands)
Processes the OpVariable instructions at current offset into binary.
std::optional< SpecConstOperationMaterializationInfo > getSpecConstantOperation(uint32_t id)
Gets the info needed to materialize the spec constant operation op associated with the given <id>.
LogicalResult dispatchToAutogenDeserialization(spirv::Opcode opcode, ArrayRef< uint32_t > words)
Method to dispatch to the specialized deserialization function for an operation in SPIR-V dialect tha...
LogicalResult processConstantNull(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpConstantNull instruction with the given operands.
LogicalResult processSpecConstantComposite(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpSpecConstantComposite instruction with the given operands.
LogicalResult processInstruction(spirv::Opcode opcode, ArrayRef< uint32_t > operands, bool deferInstructions=true)
Processes a SPIR-V instruction with the given opcode and operands.
LogicalResult processBranchConditional(ArrayRef< uint32_t > operands)
spirv::GlobalVariableOp getGlobalVariable(uint32_t id)
Gets the global variable associated with a result <id> of OpVariable.
LogicalResult processGraphARM(ArrayRef< uint32_t > operands)
LogicalResult processLabel(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpLabel instruction with the given operands.
LogicalResult processExtInst(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpExtInst with given operands.
std::optional< spirv::GraphConstantARMOpMaterializationInfo > getGraphConstantARM(uint32_t id)
Gets the GraphConstantARM ID attribute and result type with the given result <id>.
std::optional< std::pair< Attribute, Type > > getConstant(uint32_t id)
Gets the constant's attribute and type associated with the given <id>.
LogicalResult processType(spirv::Opcode opcode, ArrayRef< uint32_t > operands)
Processes a SPIR-V type instruction with given opcode and operands and registers the type into module...
LogicalResult processLoopMerge(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpLoopMerge instruction with the given operands.
LogicalResult sliceInstruction(spirv::Opcode &opcode, ArrayRef< uint32_t > &operands, std::optional< spirv::Opcode > expectedOpcode=std::nullopt)
Slices the first instruction out of binary and returns its opcode and operands via opcode and operand...
spirv::SpecConstantCompositeOp getSpecConstantComposite(uint32_t id)
Gets the composite specialization constant with the given result <id>.
spirv::EXTSpecConstantCompositeReplicateOp getSpecConstantCompositeReplicate(uint32_t id)
Gets the replicated composite specialization constant with the given result <id>.
LogicalResult processOp(ArrayRef< uint32_t > words)
Method to deserialize an operation in the SPIR-V dialect that is a mirror of an instruction in the SP...
Type getUndefType(uint32_t id)
Get the type associated with the result <id> of an OpUndef.
LogicalResult processSpecConstantCompositeReplicateEXT(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpSpecConstantCompositeReplicateEXT instruction with the given operands.
LogicalResult processGraphEntryPointARM(ArrayRef< uint32_t > operands)
LogicalResult processFunction(ArrayRef< uint32_t > operands)
Creates a deserializer for the given SPIR-V binary module.
LogicalResult processDebugString(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpString instruction with the given operands.
LogicalResult dispatchToExtensionSetAutogenDeserialization(StringRef extensionSetName, uint32_t instructionID, ArrayRef< uint32_t > words)
Dispatches the deserialization of extended instruction set operation based on the extended instructio...
LogicalResult processPhi(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpPhi instruction with the given operands.
void clearDebugLine()
Discontinues any source-level location information that might be active from a previous OpLine instru...
LogicalResult processTypeForwardPointer(ArrayRef< uint32_t > operands)
LogicalResult processSwitch(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpSwitch instruction with the given operands.
LogicalResult processOpWithoutGrammarAttr(ArrayRef< uint32_t > words, StringRef opName, bool hasResult, unsigned numOperands)
Processes a SPIR-V instruction from the given operands.
LogicalResult processGraphEndARM(ArrayRef< uint32_t > operands)
LogicalResult processConstantComposite(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpConstantComposite instruction with the given operands.
LogicalResult processBranch(ArrayRef< uint32_t > operands)
std::optional< std::pair< Attribute, Type > > getConstantCompositeReplicate(uint32_t id)
Gets the replicated composite constant's attribute and type associated with the given <id>.
LogicalResult processUndef(ArrayRef< uint32_t > operands)
Processes a OpUndef instruction.
LogicalResult processSpecConstantOperation(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpSpecConstantOp instruction with the given operands.
LogicalResult processConstant(ArrayRef< uint32_t > operands, bool isSpec)
Processes a SPIR-V Op{|Spec}Constant instruction with the given operands.
Location createFileLineColLoc(OpBuilder opBuilder)
Creates a FileLineColLoc with the OpLine location information.
LogicalResult processGraphConstantARM(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpGraphConstantARM instruction with the given operands.
LogicalResult processConstantBool(bool isTrue, ArrayRef< uint32_t > operands, bool isSpec)
Processes a SPIR-V Op{|Spec}Constant{True|False} instruction with the given operands.
spirv::SpecConstantOp getSpecConstant(uint32_t id)
Gets the specialization constant with the given result <id>.
LogicalResult processConstantCompositeReplicateEXT(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpConstantCompositeReplicateEXT instruction with the given operands.
LogicalResult processSelectionMerge(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpSelectionMerge instruction with the given operands.
LogicalResult processOpGraphSetOutputARM(ArrayRef< uint32_t > operands)
LogicalResult processDebugLine(ArrayRef< uint32_t > operands)
Processes a SPIR-V OpLine instruction with the given operands.
StringRef decodeStringLiteral(ArrayRef< uint32_t > words, unsigned &wordIndex)
Decodes a string literal in words starting at wordIndex.
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
Definition Utils.cpp:307
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addTypes(ArrayRef< Type > newTypes)