19#include "llvm/ADT/DepthFirstIterator.h"
20#include "llvm/ADT/StringExtras.h"
21#include "llvm/Support/Debug.h"
23#define DEBUG_TYPE "spirv-serialization"
45 bool skipHeader =
false,
BlockRange skipBlocks = {}) {
46 llvm::df_iterator_default_set<Block *, 4> doneBlocks;
47 doneBlocks.insert(skipBlocks.begin(), skipBlocks.end());
49 for (
Block *block : llvm::depth_first_ext(headerBlock, doneBlocks)) {
50 if (skipHeader && block == headerBlock)
52 if (
failed(blockHandler(block)))
60LogicalResult Serializer::processConstantOp(spirv::ConstantOp op) {
62 prepareConstant(op.getLoc(), op.getType(), op.getValue())) {
63 valueIDMap[op.getResult()] = resultID;
69LogicalResult Serializer::processConstantCompositeReplicateOp(
70 spirv::EXTConstantCompositeReplicateOp op) {
71 if (uint32_t resultID = prepareConstantCompositeReplicate(
72 op.getLoc(), op.getType(), op.getValue())) {
73 valueIDMap[op.getResult()] = resultID;
79LogicalResult Serializer::processSpecConstantOp(spirv::SpecConstantOp op) {
80 if (
auto resultID = prepareConstantScalar(op.getLoc(), op.getDefaultValue(),
83 if (
auto specID = op->getAttrOfType<IntegerAttr>(
"spec_id")) {
84 auto val =
static_cast<uint32_t
>(specID.getInt());
85 if (
failed(emitDecoration(resultID, spirv::Decoration::SpecId, {val})))
89 specConstIDMap[op.getSymName()] = resultID;
90 return processName(resultID, op.getSymName());
96Serializer::processSpecConstantCompositeOp(spirv::SpecConstantCompositeOp op) {
98 if (
failed(processType(op.getLoc(), op.getType(), typeID))) {
102 auto resultID = getNextID();
104 SmallVector<uint32_t, 8> operands;
105 operands.push_back(typeID);
106 operands.push_back(resultID);
108 auto constituents = op.getConstituents();
110 for (
auto index : llvm::seq<uint32_t>(0, constituents.size())) {
111 auto constituent = dyn_cast<FlatSymbolRefAttr>(constituents[index]);
113 auto constituentName = constituent.getValue();
114 auto constituentID = getSpecConstID(constituentName);
116 if (!constituentID) {
117 return op.emitError(
"unknown result <id> for specialization constant ")
121 operands.push_back(constituentID);
125 spirv::Opcode::OpSpecConstantComposite, operands);
126 specConstIDMap[op.getSymName()] = resultID;
128 return processName(resultID, op.getSymName());
131LogicalResult Serializer::processSpecConstantCompositeReplicateOp(
132 spirv::EXTSpecConstantCompositeReplicateOp op) {
134 if (
failed(processType(op.getLoc(), op.getType(), typeID))) {
138 auto constituent = dyn_cast<FlatSymbolRefAttr>(op.getConstituent());
141 "expected flat symbol reference for constituent instead of ")
142 << op.getConstituent();
144 StringRef constituentName = constituent.getValue();
145 uint32_t constituentID = getSpecConstID(constituentName);
146 if (!constituentID) {
147 return op.emitError(
"unknown result <id> for replicated spec constant ")
151 uint32_t resultID = getNextID();
152 uint32_t operands[] = {typeID, resultID, constituentID};
155 spirv::Opcode::OpSpecConstantCompositeReplicateEXT,
158 specConstIDMap[op.getSymName()] = resultID;
160 return processName(resultID, op.getSymName());
164Serializer::processSpecConstantOperationOp(spirv::SpecConstantOperationOp op) {
166 if (
failed(processType(op.getLoc(), op.getType(), typeID))) {
170 auto resultID = getNextID();
172 SmallVector<uint32_t, 8> operands;
173 operands.push_back(typeID);
174 operands.push_back(resultID);
176 Block &block = op.getRegion().getBlocks().front();
179 std::string enclosedOpName;
180 llvm::raw_string_ostream rss(enclosedOpName);
182 auto enclosedOpcode = spirv::symbolizeOpcode(enclosedOpName);
184 if (!enclosedOpcode) {
185 op.emitError(
"Couldn't find op code for op ")
190 operands.push_back(
static_cast<uint32_t
>(*enclosedOpcode));
194 uint32_t
id = getValueID(operand);
195 assert(
id &&
"use before def!");
196 operands.push_back(
id);
201 valueIDMap[op.getResult()] = resultID;
207Serializer::processGraphConstantARMOp(spirv::GraphConstantARMOp op) {
208 if (uint32_t resultID = prepareGraphConstantId(op.getLoc(), op.getType(),
209 op.getGraphConstantIdAttr())) {
210 valueIDMap[op.getResult()] = resultID;
216LogicalResult Serializer::processUndefOp(spirv::UndefOp op) {
217 auto undefType = op.getType();
218 auto &
id = undefValIDMap[undefType];
222 if (
failed(processType(op.getLoc(), undefType, typeID)))
227 valueIDMap[op.getResult()] = id;
231LogicalResult Serializer::processFuncParameter(spirv::FuncOp op) {
232 for (
auto [idx, arg] : llvm::enumerate(op.getArguments())) {
233 uint32_t argTypeID = 0;
234 if (
failed(processType(op.getLoc(), arg.getType(), argTypeID))) {
237 auto argValueID = getNextID();
240 auto funcOp = cast<FunctionOpInterface>(*op);
241 for (
auto argAttr : funcOp.getArgAttrs(idx)) {
242 if (argAttr.getName() != DecorationAttr::name)
245 if (
auto decAttr = dyn_cast<DecorationAttr>(argAttr.getValue())) {
246 if (
failed(processDecorationAttr(op->getLoc(), argValueID,
247 decAttr.getValue(), decAttr)))
252 valueIDMap[arg] = argValueID;
254 {argTypeID, argValueID});
259LogicalResult Serializer::processFuncOp(spirv::FuncOp op) {
260 LLVM_DEBUG(llvm::dbgs() <<
"-- start function '" << op.getName() <<
"' --\n");
261 assert(functionHeader.empty() && functionBody.empty());
263 uint32_t fnTypeID = 0;
265 if (
failed(processType(op.getLoc(), op.getFunctionType(), fnTypeID)))
269 SmallVector<uint32_t, 4> operands;
270 uint32_t resTypeID = 0;
271 auto resultTypes = op.getFunctionType().getResults();
272 if (resultTypes.size() > 1) {
273 return op.emitError(
"cannot serialize function with multiple return types");
275 if (
failed(processType(op.getLoc(),
276 (resultTypes.empty() ? getVoidType() : resultTypes[0]),
280 operands.push_back(resTypeID);
281 auto funcID = getOrCreateFunctionID(op.getName());
282 operands.push_back(funcID);
283 operands.push_back(
static_cast<uint32_t
>(op.getFunctionControl()));
284 operands.push_back(fnTypeID);
288 if (
failed(processName(funcID, op.getName()))) {
293 auto linkageAttr = op.getLinkageAttributes();
294 auto hasImportLinkage =
295 linkageAttr && (linkageAttr.value().getLinkageType().getValue() ==
296 spirv::LinkageType::Import);
297 if (op.isExternal() && !hasImportLinkage) {
299 "'spirv.module' cannot contain external functions "
300 "without 'Import' linkage_attributes (LinkageAttributes)");
302 if (op.isExternal() && hasImportLinkage) {
312 if (
failed(processFuncParameter(op)))
319 for (Value arg : op.getArguments())
320 valueIDMap.erase(arg);
327 if (
failed(processFuncParameter(op)))
339 {getOrCreateBlockID(&op.front())});
340 if (
failed(processBlock(&op.front(),
true)))
343 &op.front(), [&](
Block *block) { return processBlock(block); },
350 for (
const auto &deferredValue : deferredPhiValues) {
351 Value value = deferredValue.first;
352 uint32_t
id = getValueID(value);
353 LLVM_DEBUG(llvm::dbgs() <<
"[phi] fix reference of value " << value
354 <<
" to id = " <<
id <<
'\n');
355 assert(
id &&
"OpPhi references undefined value!");
356 for (
size_t offset : deferredValue.second)
357 functionBody[offset] = id;
359 deferredPhiValues.clear();
361 LLVM_DEBUG(llvm::dbgs() <<
"-- completed function '" << op.getName()
367 for (
auto attr : op->getAttrs()) {
369 auto isValidDecoration = mlir::spirv::symbolizeEnum<spirv::Decoration>(
370 llvm::convertToCamelFromSnakeCase(attr.getName().strref(),
372 if (isValidDecoration != std::nullopt) {
373 if (
failed(processDecoration(op.getLoc(), funcID, attr))) {
381 functions.append(functionHeader.begin(), functionHeader.end());
382 functions.append(functionBody.begin(), functionBody.end());
383 functionHeader.clear();
384 functionBody.clear();
389LogicalResult Serializer::processGraphARMOp(spirv::GraphARMOp op) {
390 if (op.getNumResults() < 1) {
391 return op.emitError(
"cannot serialize graph with no return types");
394 LLVM_DEBUG(llvm::dbgs() <<
"-- start graph '" << op.getName() <<
"' --\n");
395 assert(functionHeader.empty() && functionBody.empty());
397 uint32_t funcID = getOrCreateFunctionID(op.getName());
398 uint32_t fnTypeID = 0;
400 if (
failed(processType(op.getLoc(), op.getFunctionType(), fnTypeID)))
406 for (
auto [idx, arg] : llvm::enumerate(op.getArguments())) {
407 uint32_t argTypeID = 0;
408 SmallVector<uint32_t, 3> inputOperands;
410 if (
failed(processType(op.getLoc(), arg.getType(), argTypeID))) {
414 uint32_t argValueID = getNextID();
415 valueIDMap[arg] = argValueID;
417 auto attr = IntegerAttr::get(IntegerType::get(op.getContext(), 32), idx);
418 uint32_t indexID = prepareConstantInt(op.getLoc(), attr,
false);
420 inputOperands.push_back(argTypeID);
421 inputOperands.push_back(argValueID);
422 inputOperands.push_back(indexID);
428 if (
failed(processBlock(&op.front(),
true)))
431 &op.front(), [&](
Block *block) { return processBlock(block); },
436 LLVM_DEBUG(llvm::dbgs() <<
"-- completed graph '" << op.getName()
441 llvm::append_range(graphs, functionHeader);
442 llvm::append_range(graphs, functionBody);
443 functionHeader.clear();
444 functionBody.clear();
450Serializer::processGraphEntryPointARMOp(spirv::GraphEntryPointARMOp op) {
451 SmallVector<uint32_t, 4> operands;
452 StringRef graph = op.getFn();
454 uint32_t graphID = getOrCreateFunctionID(graph);
455 operands.push_back(graphID);
460 if (
ArrayAttr interface = op.getInterface()) {
461 for (Attribute var : interface.getValue()) {
462 StringRef value = cast<FlatSymbolRefAttr>(var).getValue();
463 if (uint32_t
id = getVariableID(value)) {
464 operands.push_back(
id);
467 "referencing undefined global variable."
468 "spirv.GraphEntryPointARM is at the end of spirv.module. All "
469 "referenced variables should already be defined");
478Serializer::processGraphOutputsARMOp(spirv::GraphOutputsARMOp op) {
479 for (
auto [idx, value] : llvm::enumerate(op->getOperands())) {
480 SmallVector<uint32_t, 2> outputOperands;
482 Type resType = value.getType();
483 uint32_t resTypeID = 0;
484 if (
failed(processType(op.getLoc(), resType, resTypeID))) {
488 uint32_t outputID = getValueID(value);
489 auto attr = IntegerAttr::get(IntegerType::get(op.getContext(), 32), idx);
490 uint32_t indexID = prepareConstantInt(op.getLoc(), attr,
false);
492 outputOperands.push_back(outputID);
493 outputOperands.push_back(indexID);
501LogicalResult Serializer::processVariableOp(spirv::VariableOp op) {
502 SmallVector<uint32_t, 4> operands;
503 SmallVector<StringRef, 2> elidedAttrs;
504 uint32_t resultID = 0;
505 uint32_t resultTypeID = 0;
506 if (
failed(processType(op.getLoc(), op.getType(), resultTypeID))) {
509 operands.push_back(resultTypeID);
510 resultID = getNextID();
511 valueIDMap[op.getResult()] = resultID;
512 operands.push_back(resultID);
513 auto attr = op->getAttr(spirv::attributeName<spirv::StorageClass>());
516 static_cast<uint32_t
>(cast<spirv::StorageClassAttr>(attr).getValue()));
518 elidedAttrs.push_back(spirv::attributeName<spirv::StorageClass>());
519 for (
auto arg : op.getODSOperands(0)) {
520 auto argID = getValueID(arg);
522 return emitError(op.getLoc(),
"operand 0 has a use before def");
524 operands.push_back(argID);
526 if (
failed(emitDebugLine(functionHeader, op.getLoc())))
529 for (
auto attr : op->getAttrs()) {
530 if (llvm::any_of(elidedAttrs, [&](StringRef elided) {
531 return attr.getName() == elided;
535 if (
failed(processDecoration(op.getLoc(), resultID, attr))) {
543Serializer::processGlobalVariableOp(spirv::GlobalVariableOp varOp) {
545 uint32_t resultTypeID = 0;
546 SmallVector<StringRef, 4> elidedAttrs;
547 if (
failed(processType(varOp.getLoc(), varOp.getType(), resultTypeID))) {
551 elidedAttrs.push_back(
"type");
552 SmallVector<uint32_t, 4> operands;
553 operands.push_back(resultTypeID);
554 auto resultID = getNextID();
557 auto varName = varOp.getSymName();
559 if (
failed(processName(resultID, varName))) {
562 globalVarIDMap[varName] = resultID;
563 operands.push_back(resultID);
566 operands.push_back(
static_cast<uint32_t
>(varOp.storageClass()));
569 StringRef initAttrName = varOp.getInitializerAttrName().getValue();
570 if (std::optional<StringRef> initSymbolName = varOp.getInitializer()) {
571 uint32_t initializerID = 0;
572 auto initRef = varOp->getAttrOfType<FlatSymbolRefAttr>(initAttrName);
574 varOp->getParentOp(), initRef.getAttr());
577 if (isa<spirv::GlobalVariableOp>(initOp))
578 initializerID = getVariableID(*initSymbolName);
580 initializerID = getSpecConstID(*initSymbolName);
584 "invalid usage of undefined variable as initializer");
586 operands.push_back(initializerID);
587 elidedAttrs.push_back(initAttrName);
590 if (
failed(emitDebugLine(typesGlobalValues, varOp.getLoc())))
593 elidedAttrs.push_back(initAttrName);
596 for (
auto attr : varOp->getAttrs()) {
597 if (llvm::any_of(elidedAttrs, [&](StringRef elided) {
598 return attr.getName() == elided;
602 if (
failed(processDecoration(varOp.getLoc(), resultID, attr))) {
609LogicalResult Serializer::processSelectionOp(spirv::SelectionOp selectionOp) {
612 auto &body = selectionOp.getBody();
613 for (
Block &block : body)
614 getOrCreateBlockID(&block);
616 auto *headerBlock = selectionOp.getHeaderBlock();
617 auto *mergeBlock = selectionOp.getMergeBlock();
618 auto headerID = getBlockID(headerBlock);
619 auto mergeID = getBlockID(mergeBlock);
620 auto loc = selectionOp.getLoc();
626 auto mergeOp = cast<spirv::MergeOp>(mergeBlock->back());
627 assert(selectionOp.getNumResults() == mergeOp.getNumOperands());
628 for (
unsigned i = 0, e = selectionOp.getNumResults(); i != e; ++i)
629 selectionOp.getResult(i).replaceAllUsesWith(mergeOp.getOperand(i));
641 auto emitSelectionMerge = [&]() {
642 if (
failed(emitDebugLine(functionBody, loc)))
644 lastProcessedWasMergeInst =
true;
646 functionBody, spirv::Opcode::OpSelectionMerge,
647 {mergeID,
static_cast<uint32_t
>(selectionOp.getSelectionControl())});
651 processBlock(headerBlock,
false, emitSelectionMerge)))
658 headerBlock, [&](
Block *block) {
return processBlock(block); },
659 true, {mergeBlock})))
670 if (
failed(emitPhiForBlockArguments(mergeBlock)))
673 LLVM_DEBUG(llvm::dbgs() <<
"done merge ");
674 LLVM_DEBUG(printBlock(mergeBlock, llvm::dbgs()));
675 LLVM_DEBUG(llvm::dbgs() <<
"\n");
679LogicalResult Serializer::processLoopOp(spirv::LoopOp loopOp) {
683 auto &body = loopOp.getBody();
684 for (
Block &block : llvm::drop_begin(body))
685 getOrCreateBlockID(&block);
687 auto *headerBlock = loopOp.getHeaderBlock();
688 auto *continueBlock = loopOp.getContinueBlock();
689 auto *mergeBlock = loopOp.getMergeBlock();
690 auto headerID = getBlockID(headerBlock);
691 auto continueID = getBlockID(continueBlock);
692 auto mergeID = getBlockID(mergeBlock);
693 auto loc = loopOp.getLoc();
697 auto mergeOp = cast<spirv::MergeOp>(mergeBlock->back());
698 assert(loopOp.getNumResults() == mergeOp.getNumOperands());
699 for (
unsigned i = 0, e = loopOp.getNumResults(); i != e; ++i)
700 loopOp.getResult(i).replaceAllUsesWith(mergeOp.getOperand(i));
716 auto emitLoopMerge = [&]() {
717 if (
failed(emitDebugLine(functionBody, loc)))
719 lastProcessedWasMergeInst =
true;
721 functionBody, spirv::Opcode::OpLoopMerge,
722 {mergeID, continueID,
static_cast<uint32_t
>(loopOp.getLoopControl())});
725 if (
failed(processBlock(headerBlock,
false, emitLoopMerge)))
732 headerBlock, [&](
Block *block) {
return processBlock(block); },
733 true, {continueBlock, mergeBlock})))
737 if (
failed(processBlock(continueBlock)))
745 LLVM_DEBUG(llvm::dbgs() <<
"done merge ");
746 LLVM_DEBUG(printBlock(mergeBlock, llvm::dbgs()));
747 LLVM_DEBUG(llvm::dbgs() <<
"\n");
751LogicalResult Serializer::processBranchConditionalOp(
752 spirv::BranchConditionalOp condBranchOp) {
753 auto conditionID = getValueID(condBranchOp.getCondition());
754 auto trueLabelID = getOrCreateBlockID(condBranchOp.getTrueBlock());
755 auto falseLabelID = getOrCreateBlockID(condBranchOp.getFalseBlock());
756 SmallVector<uint32_t, 5> arguments{conditionID, trueLabelID, falseLabelID};
758 if (
auto weights = condBranchOp.getBranchWeights()) {
759 for (
auto val : weights->getValue())
760 arguments.push_back(cast<IntegerAttr>(val).getInt());
763 if (
failed(emitDebugLine(functionBody, condBranchOp.getLoc())))
770LogicalResult Serializer::processBranchOp(spirv::BranchOp branchOp) {
771 if (
failed(emitDebugLine(functionBody, branchOp.getLoc())))
774 {getOrCreateBlockID(branchOp.getTarget())});
778LogicalResult Serializer::processSwitchOp(spirv::SwitchOp switchOp) {
779 uint32_t selectorID = getValueID(switchOp.getSelector());
780 uint32_t defaultLabelID = getOrCreateBlockID(switchOp.getDefaultTarget());
781 SmallVector<uint32_t> arguments{selectorID, defaultLabelID};
783 std::optional<mlir::DenseIntElementsAttr> literals = switchOp.getLiterals();
784 BlockRange targets = switchOp.getTargets();
786 for (
auto [literal,
target] : llvm::zip_equal(*literals, targets)) {
787 arguments.push_back(literal.getLimitedValue());
788 uint32_t targetLabelID = getOrCreateBlockID(
target);
789 arguments.push_back(targetLabelID);
793 if (
failed(emitDebugLine(functionBody, switchOp.getLoc())))
799LogicalResult Serializer::processAddressOfOp(spirv::AddressOfOp addressOfOp) {
800 auto varName = addressOfOp.getVariable();
801 auto variableID = getVariableID(varName);
803 return addressOfOp.emitError(
"unknown result <id> for variable ")
806 valueIDMap[addressOfOp.getPointer()] = variableID;
811Serializer::processReferenceOfOp(spirv::ReferenceOfOp referenceOfOp) {
812 auto constName = referenceOfOp.getSpecConst();
813 auto constID = getSpecConstID(constName);
815 return referenceOfOp.emitError(
816 "unknown result <id> for specialization constant ")
819 valueIDMap[referenceOfOp.getReference()] = constID;
825Serializer::processOp<spirv::EntryPointOp>(spirv::EntryPointOp op) {
828 operands.push_back(
static_cast<uint32_t
>(op.getExecutionModel()));
830 auto funcID = getFunctionID(op.getFn());
832 return op.emitError(
"missing <id> for function ")
834 <<
"; function needs to be defined before spirv.EntryPoint is "
837 operands.push_back(funcID);
842 if (
auto interface = op.getInterface()) {
843 for (
auto var : interface.getValue()) {
844 auto id = getVariableID(cast<FlatSymbolRefAttr>(var).getValue());
847 "referencing undefined global variable."
848 "spirv.EntryPoint is at the end of spirv.module. All "
849 "referenced variables should already be defined");
851 operands.push_back(
id);
860Serializer::processOp<spirv::ExecutionModeOp>(spirv::ExecutionModeOp op) {
863 auto funcID = getFunctionID(op.getFn());
865 return op.emitError(
"missing <id> for function ")
867 <<
"; function needs to be serialized before ExecutionModeOp is "
870 operands.push_back(funcID);
872 operands.push_back(
static_cast<uint32_t
>(op.getExecutionMode()));
875 auto values = op.getValues();
877 for (
auto &intVal : values.getValue()) {
878 operands.push_back(
static_cast<uint32_t
>(
879 cast<IntegerAttr>(intVal).getValue().getZExtValue()));
889Serializer::processOp<spirv::ExecutionModeIdOp>(spirv::ExecutionModeIdOp op) {
892 uint32_t funcID = getFunctionID(op.getFn());
894 return op.emitError(
"missing <id> for function ")
896 <<
"; function needs to be serialized before ExecutionModeIdOp is "
899 operands.push_back(funcID);
900 operands.push_back(
static_cast<uint32_t
>(op.getExecutionMode()));
902 for (
Attribute refVal : op.getValues().getValue()) {
903 uint32_t
id = getSpecConstID(cast<FlatSymbolRefAttr>(refVal).getValue());
905 return op.emitError(
"unknown <id> for specialization constant ")
906 << cast<FlatSymbolRefAttr>(refVal).getValue();
908 operands.push_back(
id);
917Serializer::processOp<spirv::FunctionCallOp>(spirv::FunctionCallOp op) {
918 auto funcName = op.getCallee();
919 uint32_t resTypeID = 0;
921 Type resultTy = op.getNumResults() ? *op.result_type_begin() : getVoidType();
922 if (failed(processType(op.getLoc(), resultTy, resTypeID)))
925 auto funcID = getOrCreateFunctionID(funcName);
926 auto funcCallID = getNextID();
929 for (
auto value : op.getArguments()) {
930 auto valueID = getValueID(value);
931 assert(valueID &&
"cannot find a value for spirv.FunctionCall");
932 operands.push_back(valueID);
935 if (!isa<NoneType>(resultTy))
936 valueIDMap[op.getResult(0)] = funcCallID;
944Serializer::processOp<spirv::CopyMemoryOp>(spirv::CopyMemoryOp op) {
948 for (
Value operand : op->getOperands()) {
949 auto id = getValueID(operand);
950 assert(
id &&
"use before def!");
951 operands.push_back(
id);
954 StringAttr memoryAccess = op.getMemoryAccessAttrName();
955 if (
auto attr = op->getAttr(memoryAccess)) {
957 static_cast<uint32_t
>(cast<spirv::MemoryAccessAttr>(attr).getValue()));
960 elidedAttrs.push_back(memoryAccess.strref());
962 StringAttr alignment = op.getAlignmentAttrName();
963 if (
auto attr = op->getAttr(alignment)) {
964 operands.push_back(
static_cast<uint32_t
>(
965 cast<IntegerAttr>(attr).getValue().getZExtValue()));
968 elidedAttrs.push_back(alignment.strref());
970 StringAttr sourceMemoryAccess = op.getSourceMemoryAccessAttrName();
971 if (
auto attr = op->getAttr(sourceMemoryAccess)) {
973 static_cast<uint32_t
>(cast<spirv::MemoryAccessAttr>(attr).getValue()));
976 elidedAttrs.push_back(sourceMemoryAccess.strref());
978 StringAttr sourceAlignment = op.getSourceAlignmentAttrName();
979 if (
auto attr = op->getAttr(sourceAlignment)) {
980 operands.push_back(
static_cast<uint32_t
>(
981 cast<IntegerAttr>(attr).getValue().getZExtValue()));
984 elidedAttrs.push_back(sourceAlignment.strref());
985 if (failed(emitDebugLine(functionBody, op.getLoc())))
992LogicalResult Serializer::processOp<spirv::GenericCastToPtrExplicitOp>(
993 spirv::GenericCastToPtrExplicitOp op) {
997 uint32_t resultTypeID = 0;
998 uint32_t resultID = 0;
999 resultTy = op->getResult(0).getType();
1000 if (failed(processType(loc, resultTy, resultTypeID)))
1002 operands.push_back(resultTypeID);
1004 resultID = getNextID();
1005 operands.push_back(resultID);
1006 valueIDMap[op->getResult(0)] = resultID;
1008 for (
Value operand : op->getOperands())
1009 operands.push_back(getValueID(operand));
1010 spirv::StorageClass resultStorage =
1011 cast<spirv::PointerType>(resultTy).getStorageClass();
1012 operands.push_back(
static_cast<uint32_t
>(resultStorage));
1020#define GET_SERIALIZATION_FNS
1021#include "mlir/Dialect/SPIRV/IR/SPIRVSerialization.inc"
static LogicalResult visitInPrettyBlockOrder(Block *headerBlock, function_ref< LogicalResult(Block *)> blockHandler, bool skipHeader=false, BlockRange skipBlocks={})
A pre-order depth-first visitor function for processing basic blocks.
Attributes are known-constant values of operations.
This class provides an abstraction over the different types of ranges over Blocks.
Block represents an ordered list of Operations.
OpListType & getOperations()
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
StringRef stripDialect() const
Return the operation name with dialect name stripped, if it has one.
OperationName getName()
The name of an operation is the key identifier for it.
operand_range getOperands()
Returns an iterator on the underlying Value's.
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
void encodeStringLiteralInto(SmallVectorImpl< uint32_t > &binary, StringRef literal)
Encodes an SPIR-V literal string into the given binary vector.
void encodeInstructionInto(SmallVectorImpl< uint32_t > &binary, spirv::Opcode op, ArrayRef< uint32_t > operands)
Encodes an SPIR-V instruction with the given opcode and operands into the given binary vector.
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
llvm::function_ref< Fn > function_ref