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();
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();
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())) {
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) {
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);
516 static_cast<uint32_t
>(cast<spirv::StorageClassAttr>(attr).getValue()));
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());
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 llvm::cast<IntegerAttr>(intVal).getValue().getZExtValue()));
889Serializer::processOp<spirv::FunctionCallOp>(spirv::FunctionCallOp op) {
890 auto funcName = op.getCallee();
891 uint32_t resTypeID = 0;
893 Type resultTy = op.getNumResults() ? *op.result_type_begin() : getVoidType();
894 if (failed(processType(op.getLoc(), resultTy, resTypeID)))
897 auto funcID = getOrCreateFunctionID(funcName);
898 auto funcCallID = getNextID();
901 for (
auto value : op.getArguments()) {
902 auto valueID = getValueID(value);
903 assert(valueID &&
"cannot find a value for spirv.FunctionCall");
904 operands.push_back(valueID);
907 if (!isa<NoneType>(resultTy))
908 valueIDMap[op.getResult(0)] = funcCallID;
916Serializer::processOp<spirv::CopyMemoryOp>(spirv::CopyMemoryOp op) {
920 for (
Value operand : op->getOperands()) {
921 auto id = getValueID(operand);
922 assert(
id &&
"use before def!");
923 operands.push_back(
id);
926 StringAttr memoryAccess = op.getMemoryAccessAttrName();
927 if (
auto attr = op->getAttr(memoryAccess)) {
929 static_cast<uint32_t
>(cast<spirv::MemoryAccessAttr>(attr).getValue()));
932 elidedAttrs.push_back(memoryAccess.strref());
934 StringAttr alignment = op.getAlignmentAttrName();
935 if (
auto attr = op->getAttr(alignment)) {
936 operands.push_back(
static_cast<uint32_t
>(
937 cast<IntegerAttr>(attr).getValue().getZExtValue()));
940 elidedAttrs.push_back(alignment.strref());
942 StringAttr sourceMemoryAccess = op.getSourceMemoryAccessAttrName();
943 if (
auto attr = op->getAttr(sourceMemoryAccess)) {
945 static_cast<uint32_t
>(cast<spirv::MemoryAccessAttr>(attr).getValue()));
948 elidedAttrs.push_back(sourceMemoryAccess.strref());
950 StringAttr sourceAlignment = op.getSourceAlignmentAttrName();
951 if (
auto attr = op->getAttr(sourceAlignment)) {
952 operands.push_back(
static_cast<uint32_t
>(
953 cast<IntegerAttr>(attr).getValue().getZExtValue()));
956 elidedAttrs.push_back(sourceAlignment.strref());
957 if (failed(emitDebugLine(functionBody, op.getLoc())))
964LogicalResult Serializer::processOp<spirv::GenericCastToPtrExplicitOp>(
965 spirv::GenericCastToPtrExplicitOp op) {
969 uint32_t resultTypeID = 0;
970 uint32_t resultID = 0;
971 resultTy = op->getResult(0).getType();
972 if (failed(processType(loc, resultTy, resultTypeID)))
974 operands.push_back(resultTypeID);
976 resultID = getNextID();
977 operands.push_back(resultID);
978 valueIDMap[op->getResult(0)] = resultID;
980 for (
Value operand : op->getOperands())
981 operands.push_back(getValueID(operand));
982 spirv::StorageClass resultStorage =
983 cast<spirv::PointerType>(resultTy).getStorageClass();
984 operands.push_back(
static_cast<uint32_t
>(resultStorage));
992#define GET_SERIALIZATION_FNS
993#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.
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.
Operation is the basic unit of execution within MLIR.
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.
constexpr StringRef attributeName()
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