31#include "llvm/ADT/APFloat.h"
32#include "llvm/ADT/APInt.h"
33#include "llvm/ADT/ArrayRef.h"
34#include "llvm/ADT/STLExtras.h"
35#include "llvm/ADT/StringExtras.h"
36#include "llvm/ADT/TypeSwitch.h"
37#include "llvm/Support/InterleavedRange.h"
50 auto constOp = dyn_cast_or_null<spirv::ConstantOp>(op);
54 auto valueAttr = constOp.getValue();
55 auto integerValueAttr = dyn_cast<IntegerAttr>(valueAttr);
56 if (!integerValueAttr) {
60 if (integerValueAttr.getType().isSignlessInteger())
61 value = integerValueAttr.getInt();
63 value = integerValueAttr.getSInt();
70 spirv::MemorySemantics memorySemantics) {
77 auto atMostOneInSet = spirv::MemorySemantics::Acquire |
78 spirv::MemorySemantics::Release |
79 spirv::MemorySemantics::AcquireRelease |
80 spirv::MemorySemantics::SequentiallyConsistent;
83 llvm::popcount(
static_cast<uint32_t
>(memorySemantics & atMostOneInSet));
86 "expected at most one of these four memory constraints "
87 "to be set: `Acquire`, `Release`,"
88 "`AcquireRelease` or `SequentiallyConsistent`");
99 auto pointeePtrType = dyn_cast<spirv::PointerType>(pointeeType);
100 if (!pointeePtrType) {
101 if (
auto pointeeArrayType = dyn_cast<spirv::ArrayType>(pointeeType)) {
103 dyn_cast<spirv::PointerType>(pointeeArrayType.getElementType());
107 if (!pointeePtrType || pointeePtrType.getStorageClass() !=
108 spirv::StorageClass::PhysicalStorageBuffer)
111 auto getDecorationAttr = [op](spirv::Decoration decoration) {
116 getDecorationAttr(spirv::Decoration::AliasedPointer) !=
nullptr;
117 bool hasRestrictPtr =
118 getDecorationAttr(spirv::Decoration::RestrictPointer) !=
nullptr;
120 if (!hasAliasedPtr && !hasRestrictPtr)
122 <<
" with physical buffer pointer must be decorated "
123 "either 'AliasedPointer' or 'RestrictPointer'";
125 if (hasAliasedPtr && hasRestrictPtr)
127 <<
" with physical buffer pointer must have exactly one "
128 "aliasing decoration";
139 auto descriptorSetName = llvm::convertToSnakeFromCamelCase(
140 stringifyDecoration(spirv::Decoration::DescriptorSet));
141 auto bindingName = llvm::convertToSnakeFromCamelCase(
142 stringifyDecoration(spirv::Decoration::Binding));
144 dyn_cast_or_null<IntegerAttr>(attrs.
get(descriptorSetName));
145 auto binding = dyn_cast_or_null<IntegerAttr>(attrs.
get(bindingName));
146 if (descriptorSet && binding) {
147 elidedAttrs.push_back(descriptorSetName);
148 elidedAttrs.push_back(bindingName);
149 printer <<
" bind(" << descriptorSet.getInt() <<
", " << binding.getInt()
154 auto builtInName = llvm::convertToSnakeFromCamelCase(
155 stringifyDecoration(spirv::Decoration::BuiltIn));
156 if (
auto builtin = dyn_cast_or_null<StringAttr>(attrs.
get(builtInName))) {
157 printer <<
" " << builtInName <<
"(\"" <<
builtin.getValue() <<
"\")";
158 elidedAttrs.push_back(builtInName);
176 auto fnType = dyn_cast<FunctionType>(type);
178 parser.
emitError(loc,
"expected function type");
183 result.addTypes(fnType.getResults());
194 assert(op->
getNumResults() == 1 &&
"op should have one result");
200 [&](
Type type) { return type != resultType; })) {
209 p <<
" : " << resultType;
212template <
typename BlockReadWriteOpTy>
216 if (
auto valVecTy = dyn_cast<VectorType>(valType))
217 valType = valVecTy.getElementType();
219 if (valType != cast<spirv::PointerType>(
ptr.getType()).getPointeeType()) {
220 return op.emitOpError(
"mismatch in result type and pointer type");
232 emitErrorFn(
"expected at least one index for spirv.CompositeExtract");
237 if (
auto cType = dyn_cast<spirv::CompositeType>(type)) {
238 if (cType.hasCompileTimeKnownNumElements() &&
240 static_cast<uint64_t
>(
index) >= cType.getNumElements())) {
241 emitErrorFn(
"index ") <<
index <<
" out of bounds for " << type;
244 type = cType.getElementType(
index);
246 emitErrorFn(
"cannot extract from non-composite type ")
247 << type <<
" with index " <<
index;
257 auto indicesArrayAttr = dyn_cast<ArrayAttr>(
indices);
258 if (!indicesArrayAttr) {
259 emitErrorFn(
"expected a 32-bit integer array attribute for 'indices'");
262 if (indicesArrayAttr.empty()) {
263 emitErrorFn(
"expected at least one index for spirv.CompositeExtract");
268 for (
auto indexAttr : indicesArrayAttr) {
269 auto indexIntAttr = dyn_cast<IntegerAttr>(indexAttr);
271 emitErrorFn(
"expected an 32-bit integer for index, but found '")
275 indexVals.push_back(indexIntAttr.getInt());
282 return ::mlir::emitError(loc, err);
295template <
typename ExtendedBinaryOp>
297 auto resultType = cast<spirv::StructType>(op.getType());
298 if (resultType.getNumElements() != 2)
299 return op.emitOpError(
"expected result struct type containing two members");
301 if (!llvm::all_equal({op.getOperand1().getType(), op.getOperand2().getType(),
302 resultType.getElementType(0),
303 resultType.getElementType(1)}))
304 return op.emitOpError(
305 "expected all operand types and struct member types are the same");
322 auto structType = dyn_cast<spirv::StructType>(resultType);
323 if (!structType || structType.getNumElements() != 2)
324 return parser.
emitError(loc,
"expected spirv.struct type with two members");
330 result.addTypes(resultType);
344 return op->
emitError(
"expected the same type for the first operand and "
345 "result, but provided ")
357 spirv::GlobalVariableOp var) {
358 build(builder, state, var.getType(), SymbolRefAttr::get(var));
364 *
this, getVariableAttr());
366 return emitOpError(
"expected spirv.GlobalVariable symbol");
370 "result type mismatch with the referenced global variable's type");
379LogicalResult spirv::CompositeConstructOp::verify() {
380 operand_range constituents = this->getConstituents();
395 if (coopElementType) {
396 if (constituents.size() != 1)
397 return emitOpError(
"has incorrect number of operands: expected ")
398 <<
"1, but provided " << constituents.size();
399 if (coopElementType != constituents.front().getType())
400 return emitOpError(
"operand type mismatch: expected operand type ")
401 << coopElementType <<
", but provided "
402 << constituents.front().getType();
407 auto cType = cast<spirv::CompositeType>(
getType());
408 if (constituents.size() == cType.getNumElements()) {
409 for (
auto index : llvm::seq<uint32_t>(0, constituents.size())) {
411 return emitOpError(
"operand type mismatch: expected operand type ")
412 << cType.getElementType(
index) <<
", but provided "
413 << constituents[
index].getType();
420 auto resultType = dyn_cast<VectorType>(cType);
423 "expected to return a vector or cooperative matrix when the number of "
424 "constituents is less than what the result needs");
426 if (constituents.size() < 2)
427 return emitOpError(
"has incorrect number of operands: expected at least "
428 "2 for a vector result, but provided ")
429 << constituents.size();
432 for (
Value component : constituents) {
433 if (!isa<VectorType>(component.getType()) &&
434 !component.getType().isIntOrFloat())
435 return emitOpError(
"operand type mismatch: expected operand to have "
436 "a scalar or vector type, but provided ")
437 << component.getType();
439 Type elementType = component.getType();
440 if (
auto vectorType = dyn_cast<VectorType>(component.getType())) {
441 sizes.push_back(vectorType.getNumElements());
442 elementType = vectorType.getElementType();
447 if (elementType != resultType.getElementType())
448 return emitOpError(
"operand element type mismatch: expected to be ")
449 << resultType.getElementType() <<
", but provided " << elementType;
451 unsigned totalCount = llvm::sum_of(sizes);
452 if (totalCount != cType.getNumElements())
453 return emitOpError(
"has incorrect number of operands: expected ")
454 << cType.getNumElements() <<
", but provided " << totalCount;
471 build(builder, state, elementType, composite, indexAttr);
474ParseResult spirv::CompositeExtractOp::parse(
OpAsmParser &parser,
478 StringRef indicesAttrName =
479 spirv::CompositeExtractOp::getIndicesAttrName(
result.name);
496 result.addTypes(resultType);
500void spirv::CompositeExtractOp::print(
OpAsmPrinter &printer) {
501 printer <<
' ' << getComposite() <<
getIndices() <<
" : "
505LogicalResult spirv::CompositeExtractOp::verify() {
506 auto indicesArrayAttr = dyn_cast<ArrayAttr>(
getIndices());
513 return emitOpError(
"invalid result type: expected ")
514 << resultType <<
" but provided " <<
getType();
528 build(builder, state, composite.
getType(),
object, composite, indexAttr);
531ParseResult spirv::CompositeInsertOp::parse(
OpAsmParser &parser,
534 Type objectType, compositeType;
536 StringRef indicesAttrName =
537 spirv::CompositeInsertOp::getIndicesAttrName(
result.name);
550LogicalResult spirv::CompositeInsertOp::verify() {
551 auto indicesArrayAttr = dyn_cast<ArrayAttr>(
getIndices());
557 if (objectType != getObject().
getType()) {
558 return emitOpError(
"object operand type should be ")
559 << objectType <<
", but found " << getObject().getType();
563 return emitOpError(
"result type should be the same as "
564 "the composite type, but found ")
565 << getComposite().getType() <<
" vs " <<
getType();
571void spirv::CompositeInsertOp::print(
OpAsmPrinter &printer) {
572 printer <<
" " << getObject() <<
", " << getComposite() <<
getIndices()
573 <<
" : " << getObject().
getType() <<
" into "
574 << getComposite().getType();
581ParseResult spirv::ConstantOp::parse(
OpAsmParser &parser,
584 StringRef valueAttrName = spirv::ConstantOp::getValueAttrName(
result.name);
589 if (
auto typedAttr = dyn_cast<TypedAttr>(value))
590 type = typedAttr.getType();
591 if (isa<NoneType, TensorType>(type)) {
596 if (isa<TensorArmType>(type)) {
606 printer <<
' ' << getValue();
607 if (isa<spirv::ArrayType, spirv::StructType>(
getType()) &&
608 !isa<spirv::NullAttr>(getValue()))
614 if (isa<spirv::CooperativeMatrixType>(opType)) {
615 auto denseAttr = dyn_cast<DenseElementsAttr>(value);
616 if (!denseAttr || !denseAttr.isSplat())
617 return op.emitOpError(
"expected a splat dense attribute for cooperative "
618 "matrix constant, but found ")
621 if (isa<spirv::NullAttr>(value) &&
622 !isa<spirv::ArrayType, spirv::PointerType, spirv::StructType>(opType))
623 return op.emitOpError(
"must have spirv.ptr, spirv.array or spirv.struct "
624 "result type for null value");
625 if (isa<IntegerAttr, FloatAttr, spirv::NullAttr>(value)) {
626 auto valueType = cast<TypedAttr>(value).getType();
627 if (valueType != opType)
628 return op.emitOpError(
"result type (")
629 << opType <<
") does not match value type (" << valueType <<
")";
632 if (isa<DenseTypedElementsAttr, SparseElementsAttr>(value)) {
633 auto valueType = cast<TypedAttr>(value).getType();
634 if (valueType == opType)
636 auto arrayType = dyn_cast<spirv::ArrayType>(opType);
637 auto shapedType = dyn_cast<ShapedType>(valueType);
639 return op.emitOpError(
"result or element type (")
640 << opType <<
") does not match value type (" << valueType
641 <<
"), must be the same or spirv.array";
643 int numElements = arrayType.getNumElements();
644 auto opElemType = arrayType.getElementType();
645 while (
auto t = dyn_cast<spirv::ArrayType>(opElemType)) {
646 numElements *= t.getNumElements();
647 opElemType = t.getElementType();
649 if (!opElemType.isIntOrFloat())
650 return op.emitOpError(
"only support nested array result type");
652 auto valueElemType = shapedType.getElementType();
653 if (valueElemType != opElemType) {
654 return op.emitOpError(
"result element type (")
655 << opElemType <<
") does not match value element type ("
656 << valueElemType <<
")";
659 if (numElements != shapedType.getNumElements()) {
660 return op.emitOpError(
"result number of elements (")
661 << numElements <<
") does not match value number of elements ("
662 << shapedType.getNumElements() <<
")";
666 if (
auto arrayAttr = dyn_cast<ArrayAttr>(value)) {
667 if (
auto structType = dyn_cast<spirv::StructType>(opType)) {
669 if (structType.isIdentified())
670 return op.emitOpError(
671 "cannot have an identified struct as a constant type");
672 if (arrayAttr.size() != structType.getNumElements())
673 return op.emitOpError(
"number of constituents (")
675 <<
") does not match number of struct members ("
676 << structType.getNumElements() <<
")";
677 for (
auto [idx, element] : llvm::enumerate(arrayAttr.getValue())) {
679 structType.getElementType(idx))))
684 auto arrayType = dyn_cast<spirv::ArrayType>(opType);
686 return op.emitOpError(
687 "must have spirv.array or spirv.struct result type for array value");
688 Type elemType = arrayType.getElementType();
689 for (
Attribute element : arrayAttr.getValue()) {
696 return op.emitOpError(
"cannot have attribute: ") << value;
699LogicalResult spirv::ConstantOp::verify() {
706bool spirv::ConstantOp::isBuildableWith(
Type type) {
708 if (!isa<spirv::SPIRVType>(type))
712 if (
auto structType = dyn_cast<spirv::StructType>(type))
713 return !structType.isIdentified();
714 return isa<spirv::ArrayType>(type);
720spirv::ConstantOp spirv::ConstantOp::getZero(
Type type,
Location loc,
722 if (
auto intType = dyn_cast<IntegerType>(type)) {
723 unsigned width = intType.getWidth();
725 return spirv::ConstantOp::create(builder, loc, type,
727 return spirv::ConstantOp::create(
728 builder, loc, type, builder.
getIntegerAttr(type, APInt(width, 0)));
730 if (
auto floatType = dyn_cast<FloatType>(type)) {
731 return spirv::ConstantOp::create(builder, loc, type,
734 if (
auto vectorType = dyn_cast<VectorType>(type)) {
735 Type elemType = vectorType.getElementType();
736 if (isa<IntegerType>(elemType)) {
737 return spirv::ConstantOp::create(
740 IntegerAttr::get(elemType, 0).getValue()));
742 if (isa<FloatType>(elemType)) {
743 return spirv::ConstantOp::create(
746 FloatAttr::get(elemType, 0.0).getValue()));
750 llvm_unreachable(
"unimplemented types for ConstantOp::getZero()");
753spirv::ConstantOp spirv::ConstantOp::getOne(
Type type,
Location loc,
755 if (
auto intType = dyn_cast<IntegerType>(type)) {
756 unsigned width = intType.getWidth();
758 return spirv::ConstantOp::create(builder, loc, type,
760 return spirv::ConstantOp::create(
761 builder, loc, type, builder.
getIntegerAttr(type, APInt(width, 1)));
763 if (
auto floatType = dyn_cast<FloatType>(type)) {
764 return spirv::ConstantOp::create(builder, loc, type,
767 if (
auto vectorType = dyn_cast<VectorType>(type)) {
768 Type elemType = vectorType.getElementType();
769 if (isa<IntegerType>(elemType)) {
770 return spirv::ConstantOp::create(
773 IntegerAttr::get(elemType, 1).getValue()));
775 if (isa<FloatType>(elemType)) {
776 return spirv::ConstantOp::create(
779 FloatAttr::get(elemType, 1.0).getValue()));
783 llvm_unreachable(
"unimplemented types for ConstantOp::getOne()");
786void mlir::spirv::ConstantOp::getAsmResultNames(
791 llvm::raw_svector_ostream specialName(specialNameBuffer);
792 specialName <<
"cst";
794 IntegerType intTy = dyn_cast<IntegerType>(type);
796 if (IntegerAttr intCst = dyn_cast<IntegerAttr>(getValue())) {
799 if (intTy.getWidth() == 1) {
800 return setNameFn(getResult(), (intCst.getInt() ?
"true" :
"false"));
803 if (intTy.isSignless()) {
804 specialName << intCst.getInt();
805 }
else if (intTy.isUnsigned()) {
806 specialName << intCst.getUInt();
808 specialName << intCst.getSInt();
812 if (intTy || isa<FloatType>(type)) {
813 specialName <<
'_' << type;
816 if (
auto vecType = dyn_cast<VectorType>(type)) {
817 specialName <<
"_vec_";
818 specialName << vecType.getDimSize(0);
820 Type elementType = vecType.getElementType();
822 if (isa<IntegerType>(elementType) || isa<FloatType>(elementType)) {
823 specialName <<
"x" << elementType;
827 setNameFn(getResult(), specialName.str());
830void mlir::spirv::AddressOfOp::getAsmResultNames(
833 llvm::raw_svector_ostream specialName(specialNameBuffer);
834 specialName << getVariable() <<
"_addr";
835 setNameFn(getResult(), specialName.str());
846 if (
auto typedAttr = dyn_cast<TypedAttr>(attr)) {
847 return typedAttr.getType();
850 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
857LogicalResult spirv::EXTConstantCompositeReplicateOp::verify() {
860 return emitError(
"unknown value attribute type");
862 auto compositeType = dyn_cast<spirv::CompositeType>(
getType());
864 return emitError(
"result type is not a composite type");
866 Type compositeElementType = compositeType.getElementType(0);
869 while (
auto type = dyn_cast<spirv::CompositeType>(compositeElementType)) {
870 compositeElementType = type.getElementType(0);
871 possibleTypes.push_back(compositeElementType);
874 if (!is_contained(possibleTypes, valueType)) {
875 return emitError(
"expected value attribute type ")
876 << interleaved(possibleTypes,
" or ") <<
", but got: " << valueType;
886LogicalResult spirv::ControlBarrierOp::verify() {
895 spirv::ExecutionModel executionModel,
896 spirv::FuncOp function,
898 build(builder, state,
899 spirv::ExecutionModelAttr::get(builder.
getContext(), executionModel),
900 SymbolRefAttr::get(function), builder.
getArrayAttr(interfaceVars));
903ParseResult spirv::EntryPointOp::parse(
OpAsmParser &parser,
905 spirv::ExecutionModel execModel;
918 FlatSymbolRefAttr var;
920 if (parser.parseAttribute(var, Type(),
"var_symbol", attrs))
922 interfaceVars.push_back(var);
927 result.addAttribute(spirv::EntryPointOp::getInterfaceAttrName(
result.name),
935 auto interfaceVars = getInterface().getValue();
936 if (!interfaceVars.empty())
937 printer <<
", " << llvm::interleaved(interfaceVars);
940LogicalResult spirv::EntryPointOp::verify() {
954struct ExecutionModeOperandSchema {
956 unsigned numOperands;
959ExecutionModeOperandSchema
960getExecutionModeOperandSchema(spirv::ExecutionMode mode) {
962 case spirv::ExecutionMode::Invocations:
963 case spirv::ExecutionMode::OutputVertices:
964 case spirv::ExecutionMode::VecTypeHint:
965 case spirv::ExecutionMode::SubgroupSize:
966 case spirv::ExecutionMode::SubgroupsPerWorkgroup:
967 case spirv::ExecutionMode::DenormPreserve:
968 case spirv::ExecutionMode::DenormFlushToZero:
969 case spirv::ExecutionMode::SignedZeroInfNanPreserve:
970 case spirv::ExecutionMode::RoundingModeRTE:
971 case spirv::ExecutionMode::RoundingModeRTZ:
972 case spirv::ExecutionMode::OutputPrimitivesEXT:
973 case spirv::ExecutionMode::SharedLocalMemorySizeINTEL:
974 case spirv::ExecutionMode::RoundingModeRTPINTEL:
975 case spirv::ExecutionMode::RoundingModeRTNINTEL:
976 case spirv::ExecutionMode::FloatingPointModeALTINTEL:
977 case spirv::ExecutionMode::FloatingPointModeIEEEINTEL:
978 case spirv::ExecutionMode::MaxWorkDimINTEL:
979 case spirv::ExecutionMode::NumSIMDWorkitemsINTEL:
980 case spirv::ExecutionMode::SchedulerTargetFmaxMhzINTEL:
981 case spirv::ExecutionMode::StreamingInterfaceINTEL:
982 case spirv::ExecutionMode::NamedBarrierCountINTEL:
984 case spirv::ExecutionMode::LocalSize:
985 case spirv::ExecutionMode::LocalSizeHint:
986 case spirv::ExecutionMode::MaxWorkgroupSizeINTEL:
988 case spirv::ExecutionMode::SubgroupsPerWorkgroupId:
990 case spirv::ExecutionMode::LocalSizeId:
991 case spirv::ExecutionMode::LocalSizeHintId:
1004 spirv::FuncOp function,
1005 spirv::ExecutionMode executionMode,
1007 build(builder, state, SymbolRefAttr::get(function),
1008 spirv::ExecutionModeAttr::get(builder.
getContext(), executionMode),
1012ParseResult spirv::ExecutionModeOp::parse(
OpAsmParser &parser,
1014 spirv::ExecutionMode execMode;
1029 values.push_back(cast<IntegerAttr>(value).getInt());
1031 StringRef valuesAttrName =
1032 spirv::ExecutionModeOp::getValuesAttrName(
result.name);
1033 result.addAttribute(valuesAttrName,
1038void spirv::ExecutionModeOp::print(
OpAsmPrinter &printer) {
1041 printer <<
" \"" << stringifyExecutionMode(getExecutionMode()) <<
"\"";
1043 if (!values.empty())
1044 printer <<
", " << llvm::interleaved(values.getAsValueRange<IntegerAttr>());
1047LogicalResult spirv::ExecutionModeOp::verify() {
1048 ExecutionModeOperandSchema schema =
1049 getExecutionModeOperandSchema(getExecutionMode());
1051 if (schema.isIdOperand)
1052 return emitOpError(
"expected ExecutionMode that takes extra operands "
1053 "that are not <id> operands, got: ")
1054 << stringifyExecutionMode(getExecutionMode());
1056 if (getValues().size() != schema.numOperands)
1057 return emitOpError(
"expected ")
1058 << schema.numOperands <<
" value operand(s), got "
1059 << getValues().size();
1068ParseResult spirv::ExecutionModeIdOp::parse(
OpAsmParser &parser,
1070 ExecutionMode execMode;
1079 FlatSymbolRefAttr attr;
1080 if (parser.parseAttribute(attr))
1082 values.push_back(attr);
1088 StringRef valuesAttrName = getValuesAttrName(
result.name);
1090 result.addAttribute(valuesAttrName, valuesAttr);
1094void spirv::ExecutionModeIdOp::print(
OpAsmPrinter &printer) {
1097 printer <<
" \"" << stringifyExecutionMode(getExecutionMode()) <<
"\" ";
1099 llvm::interleaveComma(
1100 getValues().getAsValueRange<FlatSymbolRefAttr>(), printer,
1104LogicalResult spirv::ExecutionModeIdOp::verify() {
1105 ExecutionModeOperandSchema schema =
1106 getExecutionModeOperandSchema(getExecutionMode());
1108 if (!schema.isIdOperand)
1109 return emitOpError(
"expected ExecutionMode that takes extra operands that "
1110 "are <id> operands, got: ")
1111 << stringifyExecutionMode(getExecutionMode());
1113 if (getValues().size() != schema.numOperands)
1114 return emitOpError(
"expected ")
1115 << schema.numOperands <<
" value operand(s), got "
1116 << getValues().size();
1118 if (!llvm::all_of(getValues(), llvm::IsaPred<FlatSymbolRefAttr>))
1119 return emitOpError(
"expected value operands to be symbol reference");
1126 for (
auto valueSymbol : getValues().getAsRange<FlatSymbolRefAttr>()) {
1128 return emitOpError(
"cannot find symbol referenced by value operand: ")
1129 << valueSymbol.getValue();
1147 StringAttr nameAttr;
1153 bool isVariadic =
false;
1155 parser,
false, entryArgs, isVariadic, resultTypes,
1160 for (
auto &arg : entryArgs)
1161 argTypes.push_back(arg.type);
1163 result.addAttribute(getFunctionTypeAttrName(
result.name),
1164 TypeAttr::get(fnType));
1167 spirv::FunctionControl fnControl;
1176 assert(resultAttrs.size() == resultTypes.size());
1178 builder,
result, entryArgs, resultAttrs, getArgAttrsAttrName(
result.name),
1179 getResAttrsAttrName(
result.name));
1182 auto *body =
result.addRegion();
1191 if (StringAttr visibility = getSymVisibilityAttr())
1192 printer << visibility.getValue() <<
' ';
1194 auto fnType = getFunctionType();
1196 printer, *
this, fnType.getInputs(),
1197 false, fnType.getResults());
1198 printer <<
" \"" << spirv::stringifyFunctionControl(getFunctionControl())
1202 {spirv::attributeName<spirv::FunctionControl>(),
1203 getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
1204 getFunctionControlAttrName(), getSymVisibilityAttrName()});
1207 Region &body = this->getBody();
1208 if (!body.empty()) {
1215LogicalResult spirv::FuncOp::verifyType() {
1216 FunctionType fnType = getFunctionType();
1217 if (fnType.getNumResults() > 1)
1218 return emitOpError(
"cannot have more than one result");
1220 auto hasDecorationAttr = [&](spirv::Decoration decoration,
1221 unsigned argIndex) {
1222 auto func = cast<FunctionOpInterface>(getOperation());
1223 for (
auto argAttr : cast<FunctionOpInterface>(
func).
getArgAttrs(argIndex)) {
1224 if (argAttr.getName() != spirv::DecorationAttr::name)
1226 if (
auto decAttr = dyn_cast<spirv::DecorationAttr>(argAttr.getValue()))
1227 return decAttr.getValue() == decoration;
1232 for (
unsigned i = 0, e = this->getNumArguments(); i != e; ++i) {
1233 Type param = fnType.getInputs()[i];
1234 auto inputPtrType = dyn_cast<spirv::PointerType>(param);
1238 auto pointeePtrType =
1239 dyn_cast<spirv::PointerType>(inputPtrType.getPointeeType());
1240 if (pointeePtrType) {
1246 if (pointeePtrType.getStorageClass() !=
1247 spirv::StorageClass::PhysicalStorageBuffer)
1250 bool hasAliasedPtr =
1251 hasDecorationAttr(spirv::Decoration::AliasedPointer, i);
1252 bool hasRestrictPtr =
1253 hasDecorationAttr(spirv::Decoration::RestrictPointer, i);
1254 if (!hasAliasedPtr && !hasRestrictPtr)
1255 return emitOpError()
1256 <<
"with a pointer points to a physical buffer pointer must "
1257 "be decorated either 'AliasedPointer' or 'RestrictPointer'";
1264 if (
auto pointeeArrayType =
1265 dyn_cast<spirv::ArrayType>(inputPtrType.getPointeeType())) {
1267 dyn_cast<spirv::PointerType>(pointeeArrayType.getElementType());
1269 pointeePtrType = inputPtrType;
1272 if (!pointeePtrType || pointeePtrType.getStorageClass() !=
1273 spirv::StorageClass::PhysicalStorageBuffer)
1276 bool hasAliased = hasDecorationAttr(spirv::Decoration::Aliased, i);
1277 bool hasRestrict = hasDecorationAttr(spirv::Decoration::Restrict, i);
1278 if (!hasAliased && !hasRestrict)
1279 return emitOpError() <<
"with physical buffer pointer must be decorated "
1280 "either 'Aliased' or 'Restrict'";
1286LogicalResult spirv::FuncOp::verifyBody() {
1287 FunctionType fnType = getFunctionType();
1288 if (!isExternal()) {
1289 Block &entryBlock = front();
1291 unsigned numArguments = this->getNumArguments();
1293 return emitOpError(
"entry block must have ")
1294 << numArguments <<
" arguments to match function signature";
1296 for (
auto [
index, fnArgType, blockArgType] :
1298 if (blockArgType != fnArgType) {
1299 return emitOpError(
"type of entry block argument #")
1300 <<
index <<
'(' << blockArgType
1301 <<
") must match the type of the corresponding argument in "
1302 <<
"function signature(" << fnArgType <<
')';
1308 if (
auto retOp = dyn_cast<spirv::ReturnOp>(op)) {
1309 if (fnType.getNumResults() != 0)
1310 return retOp.emitOpError(
"cannot be used in functions returning value");
1311 }
else if (
auto retOp = dyn_cast<spirv::ReturnValueOp>(op)) {
1312 if (fnType.getNumResults() != 1)
1313 return retOp.emitOpError(
1314 "returns 1 value but enclosing function requires ")
1315 << fnType.getNumResults() <<
" results";
1317 auto retOperandType = retOp.getValue().getType();
1318 auto fnResultType = fnType.getResult(0);
1319 if (retOperandType != fnResultType)
1320 return retOp.emitOpError(
" return value's type (")
1321 << retOperandType <<
") mismatch with function's result type ("
1322 << fnResultType <<
")";
1329 return failure(walkResult.wasInterrupted());
1333 StringRef name, FunctionType type,
1334 spirv::FunctionControl control,
1338 state.
addAttribute(getFunctionTypeAttrName(state.
name), TypeAttr::get(type));
1339 state.
addAttribute(spirv::attributeName<spirv::FunctionControl>(),
1340 builder.
getAttr<spirv::FunctionControlAttr>(control));
1349ParseResult spirv::GLFClampOp::parse(
OpAsmParser &parser,
1359ParseResult spirv::GLUClampOp::parse(
OpAsmParser &parser,
1369ParseResult spirv::GLSClampOp::parse(
OpAsmParser &parser,
1379ParseResult spirv::GLNClampOp::parse(
OpAsmParser &parser,
1389ParseResult spirv::GLSmoothStepOp::parse(
OpAsmParser &parser,
1411 Type type, StringRef name,
1412 unsigned descriptorSet,
unsigned binding) {
1413 build(builder, state, TypeAttr::get(type), builder.
getStringAttr(name));
1415 spirv::SPIRVDialect::getAttributeName(spirv::Decoration::DescriptorSet),
1418 spirv::SPIRVDialect::getAttributeName(spirv::Decoration::Binding),
1423 Type type, StringRef name,
1425 build(builder, state, TypeAttr::get(type), builder.
getStringAttr(name));
1427 spirv::SPIRVDialect::getAttributeName(spirv::Decoration::BuiltIn),
1431ParseResult spirv::GlobalVariableOp::parse(
OpAsmParser &parser,
1436 StringAttr nameAttr;
1437 StringRef initializerAttrName =
1438 spirv::GlobalVariableOp::getInitializerAttrName(
result.name);
1459 StringRef typeAttrName =
1460 spirv::GlobalVariableOp::getTypeAttrName(
result.name);
1465 if (!isa<spirv::PointerType>(type)) {
1466 return parser.
emitError(loc,
"expected spirv.ptr type");
1468 result.addAttribute(typeAttrName, TypeAttr::get(type));
1473void spirv::GlobalVariableOp::print(
OpAsmPrinter &printer) {
1475 spirv::attributeName<spirv::StorageClass>()};
1479 if (StringAttr visibility = getSymVisibilityAttr())
1480 printer << visibility.getValue() <<
' ';
1482 elidedAttrs.push_back(getSymNameAttrName());
1483 elidedAttrs.push_back(getSymVisibilityAttrName());
1485 StringRef initializerAttrName = this->getInitializerAttrName();
1487 if (
auto initializer = this->getInitializer()) {
1488 printer <<
" " << initializerAttrName <<
'(';
1491 elidedAttrs.push_back(initializerAttrName);
1494 StringRef typeAttrName = this->getTypeAttrName();
1495 elidedAttrs.push_back(typeAttrName);
1497 printer <<
" : " <<
getType();
1500LogicalResult spirv::GlobalVariableOp::verify() {
1501 if (!isa<spirv::PointerType>(
getType()))
1502 return emitOpError(
"result must be of a !spv.ptr type");
1508 auto storageClass = this->storageClass();
1509 if (storageClass == spirv::StorageClass::Generic ||
1510 storageClass == spirv::StorageClass::Function) {
1511 return emitOpError(
"storage class cannot be '")
1512 << stringifyStorageClass(storageClass) <<
"'";
1517 if (std::optional<spirv::LinkageAttributesAttr> linkage =
1518 getLinkageAttributes()) {
1519 if (linkage->getLinkageType().getValue() == spirv::LinkageType::Import &&
1522 "with Import linkage type must not have an initializer");
1526 Type pointeeType = cast<spirv::PointerType>(
getType()).getPointeeType();
1545 !isa<spirv::SpecConstantOp, spirv::SpecConstantCompositeOp>(initOp)) {
1546 return emitOpError(
"initializer must be result of a "
1547 "spirv.SpecConstant or "
1548 "spirv.SpecConstantCompositeOp op");
1559LogicalResult spirv::INTELSubgroupBlockReadOp::verify() {
1570ParseResult spirv::INTELSubgroupBlockWriteOp::parse(
OpAsmParser &parser,
1573 spirv::StorageClass storageClass;
1584 if (
auto valVecTy = dyn_cast<VectorType>(elementType))
1594void spirv::INTELSubgroupBlockWriteOp::print(
OpAsmPrinter &printer) {
1595 StringRef sc = stringifyStorageClass(
1596 cast<spirv::PointerType>(getPtr().
getType()).getStorageClass());
1597 printer <<
" \"" << sc <<
"\" " << getPtr() <<
", " << getValue() <<
" : "
1598 << getValue().getType();
1601LogicalResult spirv::INTELSubgroupBlockWriteOp::verify() {
1612LogicalResult spirv::IAddCarryOp::verify() {
1613 return ::verifyArithmeticExtendedBinaryOp(*
this);
1616ParseResult spirv::IAddCarryOp::parse(
OpAsmParser &parser,
1618 return ::parseArithmeticExtendedBinaryOp(parser,
result);
1629LogicalResult spirv::ISubBorrowOp::verify() {
1630 return ::verifyArithmeticExtendedBinaryOp(*
this);
1633ParseResult spirv::ISubBorrowOp::parse(
OpAsmParser &parser,
1635 return ::parseArithmeticExtendedBinaryOp(parser,
result);
1638void spirv::ISubBorrowOp::print(
OpAsmPrinter &printer) {
1646LogicalResult spirv::SMulExtendedOp::verify() {
1647 return ::verifyArithmeticExtendedBinaryOp(*
this);
1650ParseResult spirv::SMulExtendedOp::parse(
OpAsmParser &parser,
1652 return ::parseArithmeticExtendedBinaryOp(parser,
result);
1655void spirv::SMulExtendedOp::print(
OpAsmPrinter &printer) {
1663LogicalResult spirv::UMulExtendedOp::verify() {
1664 return ::verifyArithmeticExtendedBinaryOp(*
this);
1667ParseResult spirv::UMulExtendedOp::parse(
OpAsmParser &parser,
1669 return ::parseArithmeticExtendedBinaryOp(parser,
result);
1672void spirv::UMulExtendedOp::print(
OpAsmPrinter &printer) {
1680LogicalResult spirv::MemoryBarrierOp::verify() {
1688LogicalResult spirv::MemoryNamedBarrierOp::verify() {
1697 std::optional<StringRef> name) {
1707 spirv::AddressingModel addressingModel,
1708 spirv::MemoryModel memoryModel,
1709 std::optional<VerCapExtAttr> vceTriple,
1710 std::optional<StringRef> name) {
1713 builder.
getAttr<spirv::AddressingModelAttr>(addressingModel));
1715 builder.
getAttr<spirv::MemoryModelAttr>(memoryModel));
1719 state.
addAttribute(getVCETripleAttrName(), *vceTriple);
1725ParseResult spirv::ModuleOp::parse(
OpAsmParser &parser,
1732 StringAttr nameAttr;
1734 nameAttr, getSymNameAttrName(
result.name),
result.attributes);
1737 spirv::AddressingModel addrModel;
1738 spirv::MemoryModel memoryModel;
1748 spirv::ModuleOp::getVCETripleAttrName(),
1765 if (StringAttr visibility = getSymVisibilityAttr())
1766 printer <<
' ' << visibility.getValue();
1767 if (std::optional<StringRef> name = getName()) {
1776 auto addressingModelAttrName = spirv::attributeName<spirv::AddressingModel>();
1777 auto memoryModelAttrName = spirv::attributeName<spirv::MemoryModel>();
1778 elidedAttrs.assign({addressingModelAttrName, memoryModelAttrName,
1779 getSymNameAttrName(), getSymVisibilityAttrName()});
1781 if (std::optional<spirv::VerCapExtAttr> triple = getVceTriple()) {
1782 printer <<
" requires " << *triple;
1783 elidedAttrs.push_back(spirv::ModuleOp::getVCETripleAttrName());
1787 (*this)->getDiscardableAttrDictionary().getValue(), elidedAttrs);
1792LogicalResult spirv::ModuleOp::verifyRegions() {
1793 Dialect *dialect = (*this)->getDialect();
1798 for (
auto &op : *getBody()) {
1800 return op.
emitError(
"'spirv.module' can only contain spirv.* ops");
1805 if (
auto entryPointOp = dyn_cast<spirv::EntryPointOp>(op)) {
1806 auto funcOp = table.lookup<spirv::FuncOp>(entryPointOp.getFn());
1808 return entryPointOp.emitError(
"function '")
1809 << entryPointOp.getFn() <<
"' not found in 'spirv.module'";
1811 if (
auto interface = entryPointOp.getInterface()) {
1813 auto varSymRef = dyn_cast<FlatSymbolRefAttr>(varRef);
1815 return entryPointOp.emitError(
1816 "expected symbol reference for interface "
1817 "specification instead of '")
1821 table.lookup<spirv::GlobalVariableOp>(varSymRef.getValue());
1823 return entryPointOp.emitError(
"expected spirv.GlobalVariable "
1824 "symbol reference instead of'")
1825 << varSymRef <<
"'";
1830 auto key = std::pair<spirv::FuncOp, spirv::ExecutionModel>(
1831 funcOp, entryPointOp.getExecutionModel());
1832 if (!entryPoints.try_emplace(key, entryPointOp).second)
1833 return entryPointOp.emitError(
"duplicate of a previous EntryPointOp");
1834 }
else if (
auto funcOp = dyn_cast<spirv::FuncOp>(op)) {
1838 auto linkageAttr = funcOp.getLinkageAttributes();
1839 auto hasImportLinkage =
1840 linkageAttr && (linkageAttr.value().getLinkageType().getValue() ==
1841 spirv::LinkageType::Import);
1842 if (funcOp.isExternal() && !hasImportLinkage)
1844 "'spirv.module' cannot contain external functions "
1845 "without 'Import' linkage_attributes (LinkageAttributes)");
1848 for (
auto &block : funcOp)
1849 for (
auto &op : block) {
1852 "functions in 'spirv.module' can only contain spirv.* ops");
1870 auto specConstOp = dyn_cast_or_null<spirv::SpecConstantOp>(specConstSym);
1872 constType = specConstOp.getDefaultValue().getType();
1874 auto specConstCompositeOp =
1875 dyn_cast_or_null<spirv::SpecConstantCompositeOp>(specConstSym);
1876 if (specConstCompositeOp)
1877 constType = specConstCompositeOp.getType();
1879 if (!specConstOp && !specConstCompositeOp)
1881 "expected spirv.SpecConstant or spirv.SpecConstantComposite symbol");
1883 if (getReference().
getType() != constType)
1884 return emitOpError(
"result type mismatch with the referenced "
1885 "specialization constant's type");
1894ParseResult spirv::SpecConstantOp::parse(
OpAsmParser &parser,
1898 StringAttr nameAttr;
1900 StringRef defaultValueAttrName =
1901 spirv::SpecConstantOp::getDefaultValueAttrName(
result.name);
1909 IntegerAttr specIdAttr;
1923void spirv::SpecConstantOp::print(
OpAsmPrinter &printer) {
1925 if (StringAttr visibility = getSymVisibilityAttr())
1926 printer << visibility.getValue() <<
' ';
1931 printer <<
" = " << getDefaultValue();
1934LogicalResult spirv::SpecConstantOp::verify() {
1937 if (specID.getValue().isNegative())
1938 return emitOpError(
"SpecId cannot be negative");
1940 auto value = getDefaultValue();
1941 if (isa<IntegerAttr, FloatAttr>(value)) {
1943 if (!isa<spirv::SPIRVType>(value.getType()))
1944 return emitOpError(
"default value bitwidth disallowed");
1948 "default value can only be a bool, integer, or float scalar");
1955LogicalResult spirv::VectorShuffleOp::verify() {
1956 VectorType resultType = cast<VectorType>(
getType());
1958 size_t numResultElements = resultType.getNumElements();
1959 if (numResultElements != getComponents().size())
1960 return emitOpError(
"result type element count (")
1961 << numResultElements
1962 <<
") mismatch with the number of component selectors ("
1963 << getComponents().size() <<
")";
1965 size_t totalSrcElements =
1966 cast<VectorType>(getVector1().
getType()).getNumElements() +
1967 cast<VectorType>(getVector2().
getType()).getNumElements();
1969 for (
const auto &selector : getComponents().getAsValueRange<IntegerAttr>()) {
1970 uint32_t
index = selector.getZExtValue();
1971 if (
index >= totalSrcElements &&
1972 index != std::numeric_limits<uint32_t>().
max())
1973 return emitOpError(
"component selector ")
1974 <<
index <<
" out of range: expected to be in [0, "
1975 << totalSrcElements <<
") or 0xffffffff";
1984ParseResult spirv::SpecConstantCompositeOp::parse(
OpAsmParser &parser,
1989 StringAttr compositeName;
2001 const char *attrName =
"spec_const";
2008 constituents.push_back(specConstRef);
2014 StringAttr compositeSpecConstituentsName =
2015 spirv::SpecConstantCompositeOp::getConstituentsAttrName(
result.name);
2016 result.addAttribute(compositeSpecConstituentsName,
2023 StringAttr typeAttrName =
2024 spirv::SpecConstantCompositeOp::getTypeAttrName(
result.name);
2025 result.addAttribute(typeAttrName, TypeAttr::get(type));
2030void spirv::SpecConstantCompositeOp::print(
OpAsmPrinter &printer) {
2032 if (StringAttr visibility = getSymVisibilityAttr())
2033 printer << visibility.getValue() <<
' ';
2035 printer <<
" (" << llvm::interleaved(this->getConstituents().getValue())
2039LogicalResult spirv::SpecConstantCompositeOp::verify() {
2040 auto cType = dyn_cast<spirv::CompositeType>(
getType());
2041 auto constituents = this->getConstituents().getValue();
2044 return emitError(
"result type must be a composite type, but provided ")
2047 if (isa<spirv::CooperativeMatrixType>(cType))
2048 return emitError(
"unsupported composite type ") << cType;
2049 if (constituents.size() != cType.getNumElements())
2050 return emitError(
"has incorrect number of operands: expected ")
2051 << cType.getNumElements() <<
", but provided "
2052 << constituents.size();
2057LogicalResult spirv::SpecConstantCompositeOp::verifySymbolUses(
2059 auto cType = cast<spirv::CompositeType>(
getType());
2062 for (
auto index : llvm::seq<uint32_t>(0, constituents.size())) {
2063 auto constituent = cast<FlatSymbolRefAttr>(constituents[
index]);
2069 return emitError(
"unknown constituent symbol ") << constituent.getAttr();
2071 Type constituentType;
2072 if (
auto specConstOp = dyn_cast<spirv::SpecConstantOp>(constituentOp)) {
2073 constituentType = specConstOp.getDefaultValue().getType();
2074 }
else if (
auto specConstCompositeOp =
2075 dyn_cast<spirv::SpecConstantCompositeOp>(constituentOp)) {
2076 constituentType = specConstCompositeOp.getType();
2078 return emitError(
"unsupported constituent ")
2079 << constituent.getAttr()
2080 <<
": must reference a spirv.SpecConstant or "
2081 "spirv.SpecConstantComposite";
2084 if (constituentType != cType.getElementType(
index))
2085 return emitError(
"has incorrect types of operands: expected ")
2086 << cType.getElementType(
index) <<
", but provided "
2098spirv::EXTSpecConstantCompositeReplicateOp::parse(
OpAsmParser &parser,
2102 StringAttr compositeName;
2104 const char *attrName =
"spec_const";
2115 StringAttr compositeSpecConstituentName =
2116 spirv::EXTSpecConstantCompositeReplicateOp::getConstituentAttrName(
2118 result.addAttribute(compositeSpecConstituentName, specConstRef);
2120 StringAttr typeAttrName =
2121 spirv::EXTSpecConstantCompositeReplicateOp::getTypeAttrName(
result.name);
2122 result.addAttribute(typeAttrName, TypeAttr::get(type));
2127void spirv::EXTSpecConstantCompositeReplicateOp::print(
OpAsmPrinter &printer) {
2129 if (StringAttr visibility = getSymVisibilityAttr())
2130 printer << visibility.getValue() <<
' ';
2132 printer <<
" (" << this->getConstituent() <<
") : " <<
getType();
2135LogicalResult spirv::EXTSpecConstantCompositeReplicateOp::verify() {
2136 if (!isa<spirv::CompositeType>(
getType()))
2137 return emitError(
"result type must be a composite type, but provided ")
2143LogicalResult spirv::EXTSpecConstantCompositeReplicateOp::verifySymbolUses(
2145 auto compositeType = cast<spirv::CompositeType>(
getType());
2150 "splat spec constant reference defining constituent not found");
2152 auto constituentSpecConstOp = dyn_cast<spirv::SpecConstantOp>(constituentOp);
2153 if (!constituentSpecConstOp)
2154 return emitError(
"constituent is not a spec constant");
2156 Type constituentType = constituentSpecConstOp.getDefaultValue().getType();
2157 Type compositeElementType = compositeType.getElementType(0);
2158 if (constituentType != compositeElementType)
2159 return emitError(
"constituent has incorrect type: expected ")
2160 << compositeElementType <<
", but provided " << constituentType;
2169ParseResult spirv::SpecConstantOperationOp::parse(
OpAsmParser &parser,
2185 spirv::YieldOp::create(builder, wrappedOp->
getLoc(), wrappedOp->
getResult(0));
2196void spirv::SpecConstantOperationOp::print(
OpAsmPrinter &printer) {
2197 printer <<
" wraps ";
2201LogicalResult spirv::SpecConstantOperationOp::verifyRegions() {
2202 Block &block = getRegion().getBlocks().
front();
2205 return emitOpError(
"expected exactly 2 nested ops");
2210 return emitOpError(
"invalid enclosed op");
2213 if (!isa_and_present<spirv::ConstantOp, spirv::ReferenceOfOp,
2214 spirv::SpecConstantOperationOp>(
2215 operand.getDefiningOp()))
2217 "invalid operand, must be defined by a constant operation");
2226LogicalResult spirv::GLFrexpStructOp::verify() {
2228 dyn_cast<spirv::StructType>(getResult().
getType());
2231 return emitError(
"result type must be a struct type with two memebers");
2235 VectorType exponentVecTy = dyn_cast<VectorType>(exponentTy);
2236 IntegerType exponentIntTy = dyn_cast<IntegerType>(exponentTy);
2238 Type operandTy = getOperand().getType();
2239 VectorType operandVecTy = dyn_cast<VectorType>(operandTy);
2240 FloatType operandFTy = dyn_cast<FloatType>(operandTy);
2242 if (significandTy != operandTy)
2243 return emitError(
"member zero of the resulting struct type must be the "
2244 "same type as the operand");
2246 if (exponentVecTy) {
2247 IntegerType componentIntTy =
2248 dyn_cast<IntegerType>(exponentVecTy.getElementType());
2249 if (!componentIntTy || componentIntTy.getWidth() != 32)
2250 return emitError(
"member one of the resulting struct type must"
2251 "be a scalar or vector of 32 bit integer type");
2252 }
else if (!exponentIntTy || exponentIntTy.getWidth() != 32) {
2253 return emitError(
"member one of the resulting struct type "
2254 "must be a scalar or vector of 32 bit integer type");
2258 if (operandVecTy && exponentVecTy &&
2259 (exponentVecTy.getNumElements() == operandVecTy.getNumElements()))
2262 if (operandFTy && exponentIntTy)
2265 return emitError(
"member one of the resulting struct type must have the same "
2266 "number of components as the operand type");
2275 if (isa<FloatType>(floatType) != isa<IntegerType>(integerType))
2276 return op->
emitOpError(
"operands must both be scalars or vectors");
2279 if (
auto vectorType = dyn_cast<VectorType>(type))
2280 return vectorType.getNumElements();
2285 return op->
emitOpError(
"operands must have the same number of elements");
2290LogicalResult spirv::GLLdexpOp::verify() {
2299LogicalResult spirv::CLLdexpOp::verify() {
2308LogicalResult spirv::CLPownOp::verify() {
2317LogicalResult spirv::CLRootnOp::verify() {
2326LogicalResult spirv::CLSincosOp::verify() {
2328 cast<spirv::PointerType>(getCosval().
getType()).getStorageClass();
2329 if (!llvm::is_contained(
2330 {spirv::StorageClass::CrossWorkgroup, spirv::StorageClass::Workgroup,
2331 spirv::StorageClass::Function, spirv::StorageClass::Generic},
2333 return emitOpError(
"cosval must point to CrossWorkgroup, Workgroup, "
2334 "Function, or Generic storage");
2342LogicalResult spirv::ShiftLeftLogicalOp::verify() {
2350LogicalResult spirv::ShiftRightArithmeticOp::verify() {
2358LogicalResult spirv::ShiftRightLogicalOp::verify() {
2366LogicalResult spirv::VectorTimesScalarOp::verify() {
2368 return emitOpError(
"vector operand and result type mismatch");
2369 auto scalarType = cast<VectorType>(
getType()).getElementType();
2370 if (getScalar().
getType() != scalarType)
2371 return emitOpError(
"scalar operand and result element type match");
static Value getPointer(Location loc, Value value, ConversionPatternRewriter &rewriter)
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static ParseResult parseArithmeticExtendedBinaryOp(OpAsmParser &parser, OperationState &result)
static Type getValueType(Attribute attr)
static LogicalResult verifyConstantType(spirv::ConstantOp op, Attribute value, Type opType)
static ParseResult parseOneResultSameOperandTypeOp(OpAsmParser &parser, OperationState &result)
static LogicalResult verifyArithmeticExtendedBinaryOp(ExtendedBinaryOp op)
static LogicalResult verifyFloatIntegerBuiltin(Operation *op, Type floatType, Type integerType)
static LogicalResult verifyShiftOp(Operation *op)
static LogicalResult verifyBlockReadWritePtrAndValTypes(BlockReadWriteOpTy op, Value ptr, Value val)
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
static void printOneResultOp(Operation *op, OpAsmPrinter &p)
static void printArithmeticExtendedBinaryOp(Operation *op, OpAsmPrinter &printer)
ParseResult parseSymbolName(StringAttr &result)
Parse an -identifier and store it (without the '@' symbol) in a string attribute.
virtual ParseResult parseOptionalSymbolName(StringAttr &result)=0
Parse an optional -identifier and store it (without the '@' symbol) in a string attribute.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseOptionalColon()=0
Parse a : token if present.
ParseResult addTypeToList(Type type, SmallVectorImpl< Type > &result)
Add the specified type to the end of the specified type list and return success.
virtual ParseResult parseEqual()=0
Parse a = token.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual ParseResult parseColonType(Type &result)=0
Parse a colon followed by a type.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
virtual ParseResult parseColon()=0
Parse a : token.
ParseResult addTypesToList(ArrayRef< Type > types, SmallVectorImpl< Type > &result)
Add the specified types to the end of the specified type list and return success.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
ParseResult parseKeywordType(const char *keyword, Type &result)
Parse a keyword followed by a type.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
Attributes are known-constant values of operations.
Block represents an ordered list of Operations.
ValueTypeRange< BlockArgListType > getArgumentTypes()
Return a range containing the types of the arguments for this block.
unsigned getNumArguments()
OpListType & getOperations()
IntegerAttr getI32IntegerAttr(int32_t value)
IntegerAttr getIntegerAttr(Type type, int64_t value)
ArrayAttr getI32ArrayAttr(ArrayRef< int32_t > values)
FloatAttr getFloatAttr(Type type, double value)
FunctionType getFunctionType(TypeRange inputs, TypeRange results)
IntegerType getIntegerType(unsigned width)
BoolAttr getBoolAttr(bool value)
StringAttr getStringAttr(const Twine &bytes)
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
MLIRContext * getContext() const
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
static DenseFPElementsAttr get(const ShapedType &type, Arg &&arg)
Get an instance of a DenseFPElementsAttr with the given arguments.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
A symbol reference with a reference path containing a single element.
This class represents a diagnostic that is inflight and set to be reported.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
Attribute get(StringAttr name) const
Return the specified attribute if present, null otherwise.
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
virtual OptionalParseResult parseOptionalRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region if present.
virtual Operation * parseGenericOperation(Block *insertBlock, Block::iterator insertPt)=0
Parse an operation in its generic form.
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printOptionalAttrDictWithKeyword(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary prefixed with 'attribute...
void printOperands(OperandRange operands)
Print a comma separated range of operation operands out of line to avoid instantiating the range iter...
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
virtual void printGenericOp(Operation *op, bool printOpName=true)=0
Print the entire operation with the default generic assembly form.
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
A trait to mark ops that can be enclosed/wrapped in a SpecConstantOperation op.
type_range getType() const
void populateInherentAttrs(Operation *op, NamedAttrList &attrs) const
Append the inherent attributes stored in the properties of op to attrs.
Operation is the basic unit of execution within MLIR.
Attribute getDiscardableAttr(StringRef name)
Access a discardable attribute by name, returns a null Attribute if the discardable attribute does no...
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
Value getOperand(unsigned idx)
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OperationName getName()
The name of an operation is the key identifier for it.
DictionaryAttr getDiscardableAttrDictionary()
Return all of the discardable attributes on this operation as a DictionaryAttr.
operand_type_range getOperandTypes()
result_type_range getResultTypes()
operand_range getOperands()
Returns an iterator on the underlying Value's.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
unsigned getNumResults()
Return the number of results held by this operation.
This class implements Optional functionality for ParseResult.
bool has_value() const
Returns true if we contain a valid ParseResult value.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
void push_back(Block *block)
This class represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
This class allows for representing and managing the symbol table used by operations with the 'SymbolT...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Dialect & getDialect() const
Get the dialect this type is registered to.
Type front()
Return first type in the range.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
static ArrayType get(Type elementType, unsigned elementCount)
Type getElementType() const
static PointerType get(Type pointeeType, StorageClass storageClass)
unsigned getNumElements() const
Type getElementType(unsigned) const
An attribute that specifies the SPIR-V (version, capabilities, extensions) triple.
void addArgAndResultAttrs(Builder &builder, OperationState &result, ArrayRef< DictionaryAttr > argAttrs, ArrayRef< DictionaryAttr > resultAttrs, StringAttr argAttrsName, StringAttr resAttrsName)
Adds argument and result attributes, provided as argAttrs and resultAttrs arguments,...
void walk(Operation *op, function_ref< void(Region *)> callback, WalkOrder order)
Walk all of the regions, blocks, or operations nested under (and including) the given operation.
ArrayRef< NamedAttribute > getArgAttrs(FunctionOpInterface op, unsigned index)
Return all of the attributes for the argument at 'index'.
ParseResult parseFunctionSignatureWithArguments(OpAsmParser &parser, bool allowVariadic, SmallVectorImpl< OpAsmParser::Argument > &arguments, bool &isVariadic, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses a function signature using parser.
void printFunctionAttributes(OpAsmPrinter &p, Operation *op, ArrayRef< StringRef > elided={})
Prints the list of function prefixed with the "attributes" keyword.
void printFunctionSignature(OpAsmPrinter &p, FunctionOpInterface op, ArrayRef< Type > argTypes, bool isVariadic, ArrayRef< Type > resultTypes)
Prints the signature of the function-like operation op.
ParseResult parseOptionalVisibilityKeyword(OpAsmParser &parser, NamedAttrList &attrs)
Parse an optional visibility attribute keyword (i.e., public, private, or nested) without quotes in a...
Operation::operand_range getIndices(Operation *op)
Get the indices that the given load/store operation is operating on.
uint64_t getN(LevelType lt)
constexpr char kFnNameAttrName[]
constexpr char kSpecIdAttrName[]
LogicalResult verifyMemorySemantics(Operation *op, spirv::MemorySemantics memorySemantics)
ParseResult parseEnumStrAttr(EnumClass &value, OpAsmParser &parser, StringRef attrName=spirv::attributeName< EnumClass >())
Parses the next string attribute in parser as an enumerant of the given EnumClass.
ParseResult parseEnumKeywordAttr(EnumClass &value, ParserType &parser, StringRef attrName=spirv::attributeName< EnumClass >())
Parses the next keyword in parser as an enumerant of the given EnumClass.
void printVariableDecorations(Operation *op, OpAsmPrinter &printer, SmallVectorImpl< StringRef > &elidedAttrs)
LogicalResult verifyPhysicalStorageBufferDecorations(Operation *op, Type pointeeType)
Verifies the SPV_KHR_physical_storage_buffer rule that a variable whose pointee is a pointer (or arra...
AddressingModel getAddressingModel(TargetEnvAttr targetAttr, bool use64bitAddress)
Returns addressing model selected based on target environment.
FailureOr< ExecutionModel > getExecutionModel(TargetEnvAttr targetAttr)
Returns execution model selected based on target environment.
FailureOr< MemoryModel > getMemoryModel(TargetEnvAttr targetAttr)
Returns memory model selected based on target environment.
LogicalResult extractValueFromConstOp(Operation *op, int32_t &value)
std::string getDecorationString(Decoration decoration)
Converts a SPIR-V Decoration enum value to its snake_case string representation for use in MLIR attri...
ParseResult parseVariableDecorations(OpAsmParser &parser, OperationState &state)
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
llvm::function_ref< Fn > function_ref
This is the representation of an operand reference.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
Region * addRegion()
Create a region that should be attached to the operation.