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::processAddressOfOp(spirv::AddressOfOp addressOfOp) {
779 auto varName = addressOfOp.getVariable();
780 auto variableID = getVariableID(varName);
782 return addressOfOp.emitError(
"unknown result <id> for variable ")
785 valueIDMap[addressOfOp.getPointer()] = variableID;
790Serializer::processReferenceOfOp(spirv::ReferenceOfOp referenceOfOp) {
791 auto constName = referenceOfOp.getSpecConst();
792 auto constID = getSpecConstID(constName);
794 return referenceOfOp.emitError(
795 "unknown result <id> for specialization constant ")
798 valueIDMap[referenceOfOp.getReference()] = constID;
804Serializer::processOp<spirv::EntryPointOp>(spirv::EntryPointOp op) {
807 operands.push_back(
static_cast<uint32_t
>(op.getExecutionModel()));
809 auto funcID = getFunctionID(op.getFn());
811 return op.emitError(
"missing <id> for function ")
813 <<
"; function needs to be defined before spirv.EntryPoint is "
816 operands.push_back(funcID);
821 if (
auto interface = op.getInterface()) {
822 for (
auto var : interface.getValue()) {
823 auto id = getVariableID(cast<FlatSymbolRefAttr>(var).getValue());
826 "referencing undefined global variable."
827 "spirv.EntryPoint is at the end of spirv.module. All "
828 "referenced variables should already be defined");
830 operands.push_back(
id);
839Serializer::processOp<spirv::ExecutionModeOp>(spirv::ExecutionModeOp op) {
842 auto funcID = getFunctionID(op.getFn());
844 return op.emitError(
"missing <id> for function ")
846 <<
"; function needs to be serialized before ExecutionModeOp is "
849 operands.push_back(funcID);
851 operands.push_back(
static_cast<uint32_t
>(op.getExecutionMode()));
854 auto values = op.getValues();
856 for (
auto &intVal : values.getValue()) {
857 operands.push_back(
static_cast<uint32_t
>(
858 llvm::cast<IntegerAttr>(intVal).getValue().getZExtValue()));
868Serializer::processOp<spirv::FunctionCallOp>(spirv::FunctionCallOp op) {
869 auto funcName = op.getCallee();
870 uint32_t resTypeID = 0;
872 Type resultTy = op.getNumResults() ? *op.result_type_begin() : getVoidType();
873 if (failed(processType(op.getLoc(), resultTy, resTypeID)))
876 auto funcID = getOrCreateFunctionID(funcName);
877 auto funcCallID = getNextID();
880 for (
auto value : op.getArguments()) {
881 auto valueID = getValueID(value);
882 assert(valueID &&
"cannot find a value for spirv.FunctionCall");
883 operands.push_back(valueID);
886 if (!isa<NoneType>(resultTy))
887 valueIDMap[op.getResult(0)] = funcCallID;
895Serializer::processOp<spirv::CopyMemoryOp>(spirv::CopyMemoryOp op) {
899 for (
Value operand : op->getOperands()) {
900 auto id = getValueID(operand);
901 assert(
id &&
"use before def!");
902 operands.push_back(
id);
905 StringAttr memoryAccess = op.getMemoryAccessAttrName();
906 if (
auto attr = op->getAttr(memoryAccess)) {
908 static_cast<uint32_t
>(cast<spirv::MemoryAccessAttr>(attr).getValue()));
911 elidedAttrs.push_back(memoryAccess.strref());
913 StringAttr alignment = op.getAlignmentAttrName();
914 if (
auto attr = op->getAttr(alignment)) {
915 operands.push_back(
static_cast<uint32_t
>(
916 cast<IntegerAttr>(attr).getValue().getZExtValue()));
919 elidedAttrs.push_back(alignment.strref());
921 StringAttr sourceMemoryAccess = op.getSourceMemoryAccessAttrName();
922 if (
auto attr = op->getAttr(sourceMemoryAccess)) {
924 static_cast<uint32_t
>(cast<spirv::MemoryAccessAttr>(attr).getValue()));
927 elidedAttrs.push_back(sourceMemoryAccess.strref());
929 StringAttr sourceAlignment = op.getSourceAlignmentAttrName();
930 if (
auto attr = op->getAttr(sourceAlignment)) {
931 operands.push_back(
static_cast<uint32_t
>(
932 cast<IntegerAttr>(attr).getValue().getZExtValue()));
935 elidedAttrs.push_back(sourceAlignment.strref());
936 if (failed(emitDebugLine(functionBody, op.getLoc())))
943LogicalResult Serializer::processOp<spirv::GenericCastToPtrExplicitOp>(
944 spirv::GenericCastToPtrExplicitOp op) {
948 uint32_t resultTypeID = 0;
949 uint32_t resultID = 0;
950 resultTy = op->getResult(0).getType();
951 if (failed(processType(loc, resultTy, resultTypeID)))
953 operands.push_back(resultTypeID);
955 resultID = getNextID();
956 operands.push_back(resultID);
957 valueIDMap[op->getResult(0)] = resultID;
959 for (
Value operand : op->getOperands())
960 operands.push_back(getValueID(operand));
961 spirv::StorageClass resultStorage =
962 cast<spirv::PointerType>(resultTy).getStorageClass();
963 operands.push_back(
static_cast<uint32_t
>(resultStorage));
971#define GET_SERIALIZATION_FNS
972#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