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));
361LogicalResult spirv::AddressOfOp::verify() {
362 auto varOp = dyn_cast_or_null<spirv::GlobalVariableOp>(
366 return emitOpError(
"expected spirv.GlobalVariable symbol");
368 if (getPointer().
getType() != varOp.getType()) {
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");
427 for (
Value component : constituents) {
428 if (!isa<VectorType>(component.getType()) &&
429 !component.getType().isIntOrFloat())
430 return emitOpError(
"operand type mismatch: expected operand to have "
431 "a scalar or vector type, but provided ")
432 << component.getType();
434 Type elementType = component.getType();
435 if (
auto vectorType = dyn_cast<VectorType>(component.getType())) {
436 sizes.push_back(vectorType.getNumElements());
437 elementType = vectorType.getElementType();
442 if (elementType != resultType.getElementType())
443 return emitOpError(
"operand element type mismatch: expected to be ")
444 << resultType.getElementType() <<
", but provided " << elementType;
446 unsigned totalCount = llvm::sum_of(sizes);
447 if (totalCount != cType.getNumElements())
448 return emitOpError(
"has incorrect number of operands: expected ")
449 << cType.getNumElements() <<
", but provided " << totalCount;
466 build(builder, state, elementType, composite, indexAttr);
469ParseResult spirv::CompositeExtractOp::parse(
OpAsmParser &parser,
473 StringRef indicesAttrName =
474 spirv::CompositeExtractOp::getIndicesAttrName(
result.name);
491 result.addTypes(resultType);
495void spirv::CompositeExtractOp::print(
OpAsmPrinter &printer) {
496 printer <<
' ' << getComposite() <<
getIndices() <<
" : "
500LogicalResult spirv::CompositeExtractOp::verify() {
501 auto indicesArrayAttr = dyn_cast<ArrayAttr>(
getIndices());
508 return emitOpError(
"invalid result type: expected ")
509 << resultType <<
" but provided " <<
getType();
523 build(builder, state, composite.
getType(),
object, composite, indexAttr);
526ParseResult spirv::CompositeInsertOp::parse(
OpAsmParser &parser,
529 Type objectType, compositeType;
531 StringRef indicesAttrName =
532 spirv::CompositeInsertOp::getIndicesAttrName(
result.name);
545LogicalResult spirv::CompositeInsertOp::verify() {
546 auto indicesArrayAttr = dyn_cast<ArrayAttr>(
getIndices());
552 if (objectType != getObject().
getType()) {
553 return emitOpError(
"object operand type should be ")
554 << objectType <<
", but found " << getObject().getType();
558 return emitOpError(
"result type should be the same as "
559 "the composite type, but found ")
560 << getComposite().getType() <<
" vs " <<
getType();
566void spirv::CompositeInsertOp::print(
OpAsmPrinter &printer) {
567 printer <<
" " << getObject() <<
", " << getComposite() <<
getIndices()
568 <<
" : " << getObject().
getType() <<
" into "
569 << getComposite().getType();
576ParseResult spirv::ConstantOp::parse(
OpAsmParser &parser,
579 StringRef valueAttrName = spirv::ConstantOp::getValueAttrName(
result.name);
584 if (
auto typedAttr = dyn_cast<TypedAttr>(value))
585 type = typedAttr.getType();
586 if (isa<NoneType, TensorType>(type)) {
591 if (isa<TensorArmType>(type)) {
601 printer <<
' ' << getValue();
602 if (isa<spirv::ArrayType, spirv::StructType>(
getType()))
608 if (isa<spirv::CooperativeMatrixType>(opType)) {
609 auto denseAttr = dyn_cast<DenseElementsAttr>(value);
610 if (!denseAttr || !denseAttr.isSplat())
611 return op.emitOpError(
"expected a splat dense attribute for cooperative "
612 "matrix constant, but found ")
615 if (isa<IntegerAttr, FloatAttr>(value)) {
616 auto valueType = cast<TypedAttr>(value).getType();
617 if (valueType != opType)
618 return op.emitOpError(
"result type (")
619 << opType <<
") does not match value type (" << valueType <<
")";
622 if (isa<DenseTypedElementsAttr, SparseElementsAttr>(value)) {
623 auto valueType = cast<TypedAttr>(value).getType();
624 if (valueType == opType)
626 auto arrayType = dyn_cast<spirv::ArrayType>(opType);
627 auto shapedType = dyn_cast<ShapedType>(valueType);
629 return op.emitOpError(
"result or element type (")
630 << opType <<
") does not match value type (" << valueType
631 <<
"), must be the same or spirv.array";
633 int numElements = arrayType.getNumElements();
634 auto opElemType = arrayType.getElementType();
635 while (
auto t = dyn_cast<spirv::ArrayType>(opElemType)) {
636 numElements *= t.getNumElements();
637 opElemType = t.getElementType();
639 if (!opElemType.isIntOrFloat())
640 return op.emitOpError(
"only support nested array result type");
642 auto valueElemType = shapedType.getElementType();
643 if (valueElemType != opElemType) {
644 return op.emitOpError(
"result element type (")
645 << opElemType <<
") does not match value element type ("
646 << valueElemType <<
")";
649 if (numElements != shapedType.getNumElements()) {
650 return op.emitOpError(
"result number of elements (")
651 << numElements <<
") does not match value number of elements ("
652 << shapedType.getNumElements() <<
")";
656 if (
auto arrayAttr = dyn_cast<ArrayAttr>(value)) {
657 if (
auto structType = dyn_cast<spirv::StructType>(opType)) {
659 if (structType.isIdentified())
660 return op.emitOpError(
661 "cannot have an identified struct as a constant type");
662 if (arrayAttr.size() != structType.getNumElements())
663 return op.emitOpError(
"number of constituents (")
665 <<
") does not match number of struct members ("
666 << structType.getNumElements() <<
")";
667 for (
auto [idx, element] : llvm::enumerate(arrayAttr.getValue())) {
669 structType.getElementType(idx))))
674 auto arrayType = dyn_cast<spirv::ArrayType>(opType);
676 return op.emitOpError(
677 "must have spirv.array or spirv.struct result type for array value");
678 Type elemType = arrayType.getElementType();
679 for (
Attribute element : arrayAttr.getValue()) {
686 return op.emitOpError(
"cannot have attribute: ") << value;
689LogicalResult spirv::ConstantOp::verify() {
696bool spirv::ConstantOp::isBuildableWith(
Type type) {
698 if (!isa<spirv::SPIRVType>(type))
702 if (
auto structType = dyn_cast<spirv::StructType>(type))
703 return !structType.isIdentified();
704 return isa<spirv::ArrayType>(type);
710spirv::ConstantOp spirv::ConstantOp::getZero(
Type type,
Location loc,
712 if (
auto intType = dyn_cast<IntegerType>(type)) {
713 unsigned width = intType.getWidth();
715 return spirv::ConstantOp::create(builder, loc, type,
717 return spirv::ConstantOp::create(
718 builder, loc, type, builder.
getIntegerAttr(type, APInt(width, 0)));
720 if (
auto floatType = dyn_cast<FloatType>(type)) {
721 return spirv::ConstantOp::create(builder, loc, type,
724 if (
auto vectorType = dyn_cast<VectorType>(type)) {
725 Type elemType = vectorType.getElementType();
726 if (isa<IntegerType>(elemType)) {
727 return spirv::ConstantOp::create(
730 IntegerAttr::get(elemType, 0).getValue()));
732 if (isa<FloatType>(elemType)) {
733 return spirv::ConstantOp::create(
736 FloatAttr::get(elemType, 0.0).getValue()));
740 llvm_unreachable(
"unimplemented types for ConstantOp::getZero()");
743spirv::ConstantOp spirv::ConstantOp::getOne(
Type type,
Location loc,
745 if (
auto intType = dyn_cast<IntegerType>(type)) {
746 unsigned width = intType.getWidth();
748 return spirv::ConstantOp::create(builder, loc, type,
750 return spirv::ConstantOp::create(
751 builder, loc, type, builder.
getIntegerAttr(type, APInt(width, 1)));
753 if (
auto floatType = dyn_cast<FloatType>(type)) {
754 return spirv::ConstantOp::create(builder, loc, type,
757 if (
auto vectorType = dyn_cast<VectorType>(type)) {
758 Type elemType = vectorType.getElementType();
759 if (isa<IntegerType>(elemType)) {
760 return spirv::ConstantOp::create(
763 IntegerAttr::get(elemType, 1).getValue()));
765 if (isa<FloatType>(elemType)) {
766 return spirv::ConstantOp::create(
769 FloatAttr::get(elemType, 1.0).getValue()));
773 llvm_unreachable(
"unimplemented types for ConstantOp::getOne()");
776void mlir::spirv::ConstantOp::getAsmResultNames(
781 llvm::raw_svector_ostream specialName(specialNameBuffer);
782 specialName <<
"cst";
784 IntegerType intTy = dyn_cast<IntegerType>(type);
786 if (IntegerAttr intCst = dyn_cast<IntegerAttr>(getValue())) {
789 if (intTy.getWidth() == 1) {
790 return setNameFn(getResult(), (intCst.getInt() ?
"true" :
"false"));
793 if (intTy.isSignless()) {
794 specialName << intCst.getInt();
795 }
else if (intTy.isUnsigned()) {
796 specialName << intCst.getUInt();
798 specialName << intCst.getSInt();
802 if (intTy || isa<FloatType>(type)) {
803 specialName <<
'_' << type;
806 if (
auto vecType = dyn_cast<VectorType>(type)) {
807 specialName <<
"_vec_";
808 specialName << vecType.getDimSize(0);
810 Type elementType = vecType.getElementType();
812 if (isa<IntegerType>(elementType) || isa<FloatType>(elementType)) {
813 specialName <<
"x" << elementType;
817 setNameFn(getResult(), specialName.str());
820void mlir::spirv::AddressOfOp::getAsmResultNames(
823 llvm::raw_svector_ostream specialName(specialNameBuffer);
824 specialName << getVariable() <<
"_addr";
825 setNameFn(getResult(), specialName.str());
836 if (
auto typedAttr = dyn_cast<TypedAttr>(attr)) {
837 return typedAttr.getType();
840 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
847LogicalResult spirv::EXTConstantCompositeReplicateOp::verify() {
850 return emitError(
"unknown value attribute type");
852 auto compositeType = dyn_cast<spirv::CompositeType>(
getType());
854 return emitError(
"result type is not a composite type");
856 Type compositeElementType = compositeType.getElementType(0);
859 while (
auto type = dyn_cast<spirv::CompositeType>(compositeElementType)) {
860 compositeElementType = type.getElementType(0);
861 possibleTypes.push_back(compositeElementType);
864 if (!is_contained(possibleTypes, valueType)) {
865 return emitError(
"expected value attribute type ")
866 << interleaved(possibleTypes,
" or ") <<
", but got: " << valueType;
876LogicalResult spirv::ControlBarrierOp::verify() {
885 spirv::ExecutionModel executionModel,
886 spirv::FuncOp function,
888 build(builder, state,
889 spirv::ExecutionModelAttr::get(builder.
getContext(), executionModel),
890 SymbolRefAttr::get(function), builder.
getArrayAttr(interfaceVars));
893ParseResult spirv::EntryPointOp::parse(
OpAsmParser &parser,
895 spirv::ExecutionModel execModel;
908 FlatSymbolRefAttr var;
910 if (parser.parseAttribute(var, Type(),
"var_symbol", attrs))
912 interfaceVars.push_back(var);
917 result.addAttribute(spirv::EntryPointOp::getInterfaceAttrName(
result.name),
925 auto interfaceVars = getInterface().getValue();
926 if (!interfaceVars.empty())
927 printer <<
", " << llvm::interleaved(interfaceVars);
930LogicalResult spirv::EntryPointOp::verify() {
944struct ExecutionModeOperandSchema {
946 unsigned numOperands;
949ExecutionModeOperandSchema
950getExecutionModeOperandSchema(spirv::ExecutionMode mode) {
952 case spirv::ExecutionMode::Invocations:
953 case spirv::ExecutionMode::OutputVertices:
954 case spirv::ExecutionMode::VecTypeHint:
955 case spirv::ExecutionMode::SubgroupSize:
956 case spirv::ExecutionMode::SubgroupsPerWorkgroup:
957 case spirv::ExecutionMode::DenormPreserve:
958 case spirv::ExecutionMode::DenormFlushToZero:
959 case spirv::ExecutionMode::SignedZeroInfNanPreserve:
960 case spirv::ExecutionMode::RoundingModeRTE:
961 case spirv::ExecutionMode::RoundingModeRTZ:
962 case spirv::ExecutionMode::OutputPrimitivesEXT:
963 case spirv::ExecutionMode::SharedLocalMemorySizeINTEL:
964 case spirv::ExecutionMode::RoundingModeRTPINTEL:
965 case spirv::ExecutionMode::RoundingModeRTNINTEL:
966 case spirv::ExecutionMode::FloatingPointModeALTINTEL:
967 case spirv::ExecutionMode::FloatingPointModeIEEEINTEL:
968 case spirv::ExecutionMode::MaxWorkDimINTEL:
969 case spirv::ExecutionMode::NumSIMDWorkitemsINTEL:
970 case spirv::ExecutionMode::SchedulerTargetFmaxMhzINTEL:
971 case spirv::ExecutionMode::StreamingInterfaceINTEL:
972 case spirv::ExecutionMode::NamedBarrierCountINTEL:
974 case spirv::ExecutionMode::LocalSize:
975 case spirv::ExecutionMode::LocalSizeHint:
976 case spirv::ExecutionMode::MaxWorkgroupSizeINTEL:
978 case spirv::ExecutionMode::SubgroupsPerWorkgroupId:
980 case spirv::ExecutionMode::LocalSizeId:
981 case spirv::ExecutionMode::LocalSizeHintId:
994 spirv::FuncOp function,
995 spirv::ExecutionMode executionMode,
997 build(builder, state, SymbolRefAttr::get(function),
998 spirv::ExecutionModeAttr::get(builder.
getContext(), executionMode),
1002ParseResult spirv::ExecutionModeOp::parse(
OpAsmParser &parser,
1004 spirv::ExecutionMode execMode;
1019 values.push_back(cast<IntegerAttr>(value).getInt());
1021 StringRef valuesAttrName =
1022 spirv::ExecutionModeOp::getValuesAttrName(
result.name);
1023 result.addAttribute(valuesAttrName,
1028void spirv::ExecutionModeOp::print(
OpAsmPrinter &printer) {
1031 printer <<
" \"" << stringifyExecutionMode(getExecutionMode()) <<
"\"";
1033 if (!values.empty())
1034 printer <<
", " << llvm::interleaved(values.getAsValueRange<IntegerAttr>());
1037LogicalResult spirv::ExecutionModeOp::verify() {
1038 ExecutionModeOperandSchema schema =
1039 getExecutionModeOperandSchema(getExecutionMode());
1041 if (schema.isIdOperand)
1042 return emitOpError(
"expected ExecutionMode that takes extra operands "
1043 "that are not <id> operands, got: ")
1044 << stringifyExecutionMode(getExecutionMode());
1046 if (getValues().size() != schema.numOperands)
1048 << schema.numOperands <<
" value operand(s), got "
1049 << getValues().size();
1058ParseResult spirv::ExecutionModeIdOp::parse(
OpAsmParser &parser,
1060 ExecutionMode execMode;
1069 FlatSymbolRefAttr attr;
1070 if (parser.parseAttribute(attr))
1072 values.push_back(attr);
1078 StringRef valuesAttrName = getValuesAttrName(
result.name);
1080 result.addAttribute(valuesAttrName, valuesAttr);
1084void spirv::ExecutionModeIdOp::print(
OpAsmPrinter &printer) {
1087 printer <<
" \"" << stringifyExecutionMode(getExecutionMode()) <<
"\" ";
1089 llvm::interleaveComma(
1090 getValues().getAsValueRange<FlatSymbolRefAttr>(), printer,
1094LogicalResult spirv::ExecutionModeIdOp::verify() {
1095 ExecutionModeOperandSchema schema =
1096 getExecutionModeOperandSchema(getExecutionMode());
1098 if (!schema.isIdOperand)
1099 return emitOpError(
"expected ExecutionMode that takes extra operands that "
1100 "are <id> operands, got: ")
1101 << stringifyExecutionMode(getExecutionMode());
1103 if (getValues().size() != schema.numOperands)
1105 << schema.numOperands <<
" value operand(s), got "
1106 << getValues().size();
1109 auto valueSymbol = dyn_cast<FlatSymbolRefAttr>(value);
1111 return emitOpError(
"expected value operands to be symbol reference");
1113 (*this)->getParentOp(), valueSymbol);
1115 return emitOpError(
"cannot find symbol referenced by value operand: ")
1116 << valueSymbol.getValue();
1133 StringAttr nameAttr;
1139 bool isVariadic =
false;
1141 parser,
false, entryArgs, isVariadic, resultTypes,
1146 for (
auto &arg : entryArgs)
1147 argTypes.push_back(arg.type);
1149 result.addAttribute(getFunctionTypeAttrName(
result.name),
1150 TypeAttr::get(fnType));
1153 spirv::FunctionControl fnControl;
1162 assert(resultAttrs.size() == resultTypes.size());
1164 builder,
result, entryArgs, resultAttrs, getArgAttrsAttrName(
result.name),
1165 getResAttrsAttrName(
result.name));
1168 auto *body =
result.addRegion();
1178 auto fnType = getFunctionType();
1180 printer, *
this, fnType.getInputs(),
1181 false, fnType.getResults());
1182 printer <<
" \"" << spirv::stringifyFunctionControl(getFunctionControl())
1186 {spirv::attributeName<spirv::FunctionControl>(),
1187 getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
1188 getFunctionControlAttrName()});
1191 Region &body = this->getBody();
1192 if (!body.empty()) {
1199LogicalResult spirv::FuncOp::verifyType() {
1200 FunctionType fnType = getFunctionType();
1201 if (fnType.getNumResults() > 1)
1202 return emitOpError(
"cannot have more than one result");
1204 auto hasDecorationAttr = [&](spirv::Decoration decoration,
1205 unsigned argIndex) {
1206 auto func = cast<FunctionOpInterface>(getOperation());
1207 for (
auto argAttr : cast<FunctionOpInterface>(
func).
getArgAttrs(argIndex)) {
1208 if (argAttr.getName() != spirv::DecorationAttr::name)
1210 if (
auto decAttr = dyn_cast<spirv::DecorationAttr>(argAttr.getValue()))
1211 return decAttr.getValue() == decoration;
1216 for (
unsigned i = 0, e = this->getNumArguments(); i != e; ++i) {
1217 Type param = fnType.getInputs()[i];
1218 auto inputPtrType = dyn_cast<spirv::PointerType>(param);
1222 auto pointeePtrType =
1223 dyn_cast<spirv::PointerType>(inputPtrType.getPointeeType());
1224 if (pointeePtrType) {
1230 if (pointeePtrType.getStorageClass() !=
1231 spirv::StorageClass::PhysicalStorageBuffer)
1234 bool hasAliasedPtr =
1235 hasDecorationAttr(spirv::Decoration::AliasedPointer, i);
1236 bool hasRestrictPtr =
1237 hasDecorationAttr(spirv::Decoration::RestrictPointer, i);
1238 if (!hasAliasedPtr && !hasRestrictPtr)
1240 <<
"with a pointer points to a physical buffer pointer must "
1241 "be decorated either 'AliasedPointer' or 'RestrictPointer'";
1248 if (
auto pointeeArrayType =
1249 dyn_cast<spirv::ArrayType>(inputPtrType.getPointeeType())) {
1251 dyn_cast<spirv::PointerType>(pointeeArrayType.getElementType());
1253 pointeePtrType = inputPtrType;
1256 if (!pointeePtrType || pointeePtrType.getStorageClass() !=
1257 spirv::StorageClass::PhysicalStorageBuffer)
1260 bool hasAliased = hasDecorationAttr(spirv::Decoration::Aliased, i);
1261 bool hasRestrict = hasDecorationAttr(spirv::Decoration::Restrict, i);
1262 if (!hasAliased && !hasRestrict)
1263 return emitOpError() <<
"with physical buffer pointer must be decorated "
1264 "either 'Aliased' or 'Restrict'";
1270LogicalResult spirv::FuncOp::verifyBody() {
1271 FunctionType fnType = getFunctionType();
1272 if (!isExternal()) {
1273 Block &entryBlock = front();
1275 unsigned numArguments = this->getNumArguments();
1278 << numArguments <<
" arguments to match function signature";
1280 for (
auto [
index, fnArgType, blockArgType] :
1282 if (blockArgType != fnArgType) {
1283 return emitOpError(
"type of entry block argument #")
1284 <<
index <<
'(' << blockArgType
1285 <<
") must match the type of the corresponding argument in "
1286 <<
"function signature(" << fnArgType <<
')';
1292 if (
auto retOp = dyn_cast<spirv::ReturnOp>(op)) {
1293 if (fnType.getNumResults() != 0)
1294 return retOp.emitOpError(
"cannot be used in functions returning value");
1295 }
else if (
auto retOp = dyn_cast<spirv::ReturnValueOp>(op)) {
1296 if (fnType.getNumResults() != 1)
1297 return retOp.emitOpError(
1298 "returns 1 value but enclosing function requires ")
1299 << fnType.getNumResults() <<
" results";
1301 auto retOperandType = retOp.getValue().getType();
1302 auto fnResultType = fnType.getResult(0);
1303 if (retOperandType != fnResultType)
1304 return retOp.emitOpError(
" return value's type (")
1305 << retOperandType <<
") mismatch with function's result type ("
1306 << fnResultType <<
")";
1313 return failure(walkResult.wasInterrupted());
1317 StringRef name, FunctionType type,
1318 spirv::FunctionControl control,
1322 state.
addAttribute(getFunctionTypeAttrName(state.
name), TypeAttr::get(type));
1323 state.
addAttribute(spirv::attributeName<spirv::FunctionControl>(),
1324 builder.
getAttr<spirv::FunctionControlAttr>(control));
1333ParseResult spirv::GLFClampOp::parse(
OpAsmParser &parser,
1343ParseResult spirv::GLUClampOp::parse(
OpAsmParser &parser,
1353ParseResult spirv::GLSClampOp::parse(
OpAsmParser &parser,
1363ParseResult spirv::GLNClampOp::parse(
OpAsmParser &parser,
1373ParseResult spirv::GLSmoothStepOp::parse(
OpAsmParser &parser,
1395 Type type, StringRef name,
1396 unsigned descriptorSet,
unsigned binding) {
1397 build(builder, state, TypeAttr::get(type), builder.
getStringAttr(name));
1399 spirv::SPIRVDialect::getAttributeName(spirv::Decoration::DescriptorSet),
1402 spirv::SPIRVDialect::getAttributeName(spirv::Decoration::Binding),
1407 Type type, StringRef name,
1409 build(builder, state, TypeAttr::get(type), builder.
getStringAttr(name));
1411 spirv::SPIRVDialect::getAttributeName(spirv::Decoration::BuiltIn),
1415ParseResult spirv::GlobalVariableOp::parse(
OpAsmParser &parser,
1418 StringAttr nameAttr;
1419 StringRef initializerAttrName =
1420 spirv::GlobalVariableOp::getInitializerAttrName(
result.name);
1441 StringRef typeAttrName =
1442 spirv::GlobalVariableOp::getTypeAttrName(
result.name);
1447 if (!isa<spirv::PointerType>(type)) {
1448 return parser.
emitError(loc,
"expected spirv.ptr type");
1450 result.addAttribute(typeAttrName, TypeAttr::get(type));
1455void spirv::GlobalVariableOp::print(
OpAsmPrinter &printer) {
1457 spirv::attributeName<spirv::StorageClass>()};
1464 StringRef initializerAttrName = this->getInitializerAttrName();
1466 if (
auto initializer = this->getInitializer()) {
1467 printer <<
" " << initializerAttrName <<
'(';
1470 elidedAttrs.push_back(initializerAttrName);
1473 StringRef typeAttrName = this->getTypeAttrName();
1474 elidedAttrs.push_back(typeAttrName);
1476 printer <<
" : " <<
getType();
1479LogicalResult spirv::GlobalVariableOp::verify() {
1480 if (!isa<spirv::PointerType>(
getType()))
1481 return emitOpError(
"result must be of a !spv.ptr type");
1487 auto storageClass = this->storageClass();
1488 if (storageClass == spirv::StorageClass::Generic ||
1489 storageClass == spirv::StorageClass::Function) {
1491 << stringifyStorageClass(storageClass) <<
"'";
1496 if (std::optional<spirv::LinkageAttributesAttr> linkage =
1497 getLinkageAttributes()) {
1498 if (linkage->getLinkageType().getValue() == spirv::LinkageType::Import &&
1501 "with Import linkage type must not have an initializer");
1507 (*this)->getParentOp(), init.getAttr());
1519 !isa<spirv::SpecConstantOp, spirv::SpecConstantCompositeOp>(initOp)) {
1520 return emitOpError(
"initializer must be result of a "
1521 "spirv.SpecConstant or "
1522 "spirv.SpecConstantCompositeOp op");
1526 Type pointeeType = cast<spirv::PointerType>(
getType()).getPointeeType();
1538LogicalResult spirv::INTELSubgroupBlockReadOp::verify() {
1549ParseResult spirv::INTELSubgroupBlockWriteOp::parse(
OpAsmParser &parser,
1552 spirv::StorageClass storageClass;
1563 if (
auto valVecTy = dyn_cast<VectorType>(elementType))
1573void spirv::INTELSubgroupBlockWriteOp::print(
OpAsmPrinter &printer) {
1574 printer <<
" " << getPtr() <<
", " << getValue() <<
" : "
1575 << getValue().getType();
1578LogicalResult spirv::INTELSubgroupBlockWriteOp::verify() {
1589LogicalResult spirv::IAddCarryOp::verify() {
1590 return ::verifyArithmeticExtendedBinaryOp(*
this);
1593ParseResult spirv::IAddCarryOp::parse(
OpAsmParser &parser,
1595 return ::parseArithmeticExtendedBinaryOp(parser,
result);
1606LogicalResult spirv::ISubBorrowOp::verify() {
1607 return ::verifyArithmeticExtendedBinaryOp(*
this);
1610ParseResult spirv::ISubBorrowOp::parse(
OpAsmParser &parser,
1612 return ::parseArithmeticExtendedBinaryOp(parser,
result);
1615void spirv::ISubBorrowOp::print(
OpAsmPrinter &printer) {
1623LogicalResult spirv::SMulExtendedOp::verify() {
1624 return ::verifyArithmeticExtendedBinaryOp(*
this);
1627ParseResult spirv::SMulExtendedOp::parse(
OpAsmParser &parser,
1629 return ::parseArithmeticExtendedBinaryOp(parser,
result);
1632void spirv::SMulExtendedOp::print(
OpAsmPrinter &printer) {
1640LogicalResult spirv::UMulExtendedOp::verify() {
1641 return ::verifyArithmeticExtendedBinaryOp(*
this);
1644ParseResult spirv::UMulExtendedOp::parse(
OpAsmParser &parser,
1646 return ::parseArithmeticExtendedBinaryOp(parser,
result);
1649void spirv::UMulExtendedOp::print(
OpAsmPrinter &printer) {
1657LogicalResult spirv::MemoryBarrierOp::verify() {
1665LogicalResult spirv::MemoryNamedBarrierOp::verify() {
1674 std::optional<StringRef> name) {
1684 spirv::AddressingModel addressingModel,
1685 spirv::MemoryModel memoryModel,
1686 std::optional<VerCapExtAttr> vceTriple,
1687 std::optional<StringRef> name) {
1690 builder.
getAttr<spirv::AddressingModelAttr>(addressingModel));
1692 builder.
getAttr<spirv::MemoryModelAttr>(memoryModel));
1696 state.
addAttribute(getVCETripleAttrName(), *vceTriple);
1702ParseResult spirv::ModuleOp::parse(
OpAsmParser &parser,
1707 StringAttr nameAttr;
1712 spirv::AddressingModel addrModel;
1713 spirv::MemoryModel memoryModel;
1723 spirv::ModuleOp::getVCETripleAttrName(),
1740 if (std::optional<StringRef> name = getName()) {
1749 auto addressingModelAttrName = spirv::attributeName<spirv::AddressingModel>();
1750 auto memoryModelAttrName = spirv::attributeName<spirv::MemoryModel>();
1751 elidedAttrs.assign({addressingModelAttrName, memoryModelAttrName,
1754 if (std::optional<spirv::VerCapExtAttr> triple = getVceTriple()) {
1755 printer <<
" requires " << *triple;
1756 elidedAttrs.push_back(spirv::ModuleOp::getVCETripleAttrName());
1760 (*this)->getDiscardableAttrDictionary().getValue(), elidedAttrs);
1765LogicalResult spirv::ModuleOp::verifyRegions() {
1766 Dialect *dialect = (*this)->getDialect();
1771 for (
auto &op : *getBody()) {
1773 return op.
emitError(
"'spirv.module' can only contain spirv.* ops");
1778 if (
auto entryPointOp = dyn_cast<spirv::EntryPointOp>(op)) {
1779 auto funcOp = table.lookup<spirv::FuncOp>(entryPointOp.getFn());
1781 return entryPointOp.emitError(
"function '")
1782 << entryPointOp.getFn() <<
"' not found in 'spirv.module'";
1784 if (
auto interface = entryPointOp.getInterface()) {
1786 auto varSymRef = dyn_cast<FlatSymbolRefAttr>(varRef);
1788 return entryPointOp.emitError(
1789 "expected symbol reference for interface "
1790 "specification instead of '")
1794 table.lookup<spirv::GlobalVariableOp>(varSymRef.getValue());
1796 return entryPointOp.emitError(
"expected spirv.GlobalVariable "
1797 "symbol reference instead of'")
1798 << varSymRef <<
"'";
1803 auto key = std::pair<spirv::FuncOp, spirv::ExecutionModel>(
1804 funcOp, entryPointOp.getExecutionModel());
1805 if (!entryPoints.try_emplace(key, entryPointOp).second)
1806 return entryPointOp.emitError(
"duplicate of a previous EntryPointOp");
1807 }
else if (
auto funcOp = dyn_cast<spirv::FuncOp>(op)) {
1811 auto linkageAttr = funcOp.getLinkageAttributes();
1812 auto hasImportLinkage =
1813 linkageAttr && (linkageAttr.value().getLinkageType().getValue() ==
1814 spirv::LinkageType::Import);
1815 if (funcOp.isExternal() && !hasImportLinkage)
1817 "'spirv.module' cannot contain external functions "
1818 "without 'Import' linkage_attributes (LinkageAttributes)");
1821 for (
auto &block : funcOp)
1822 for (
auto &op : block) {
1825 "functions in 'spirv.module' can only contain spirv.* ops");
1837LogicalResult spirv::ReferenceOfOp::verify() {
1839 (*this)->getParentOp(), getSpecConstAttr());
1842 auto specConstOp = dyn_cast_or_null<spirv::SpecConstantOp>(specConstSym);
1844 constType = specConstOp.getDefaultValue().getType();
1846 auto specConstCompositeOp =
1847 dyn_cast_or_null<spirv::SpecConstantCompositeOp>(specConstSym);
1848 if (specConstCompositeOp)
1849 constType = specConstCompositeOp.getType();
1851 if (!specConstOp && !specConstCompositeOp)
1853 "expected spirv.SpecConstant or spirv.SpecConstantComposite symbol");
1855 if (getReference().
getType() != constType)
1856 return emitOpError(
"result type mismatch with the referenced "
1857 "specialization constant's type");
1866ParseResult spirv::SpecConstantOp::parse(
OpAsmParser &parser,
1868 StringAttr nameAttr;
1870 StringRef defaultValueAttrName =
1871 spirv::SpecConstantOp::getDefaultValueAttrName(
result.name);
1879 IntegerAttr specIdAttr;
1893void spirv::SpecConstantOp::print(
OpAsmPrinter &printer) {
1899 printer <<
" = " << getDefaultValue();
1902LogicalResult spirv::SpecConstantOp::verify() {
1905 if (specID.getValue().isNegative())
1908 auto value = getDefaultValue();
1909 if (isa<IntegerAttr, FloatAttr>(value)) {
1911 if (!isa<spirv::SPIRVType>(value.getType()))
1912 return emitOpError(
"default value bitwidth disallowed");
1916 "default value can only be a bool, integer, or float scalar");
1923LogicalResult spirv::VectorShuffleOp::verify() {
1924 VectorType resultType = cast<VectorType>(
getType());
1926 size_t numResultElements = resultType.getNumElements();
1927 if (numResultElements != getComponents().size())
1929 << numResultElements
1930 <<
") mismatch with the number of component selectors ("
1931 << getComponents().size() <<
")";
1933 size_t totalSrcElements =
1934 cast<VectorType>(getVector1().
getType()).getNumElements() +
1935 cast<VectorType>(getVector2().
getType()).getNumElements();
1937 for (
const auto &selector : getComponents().getAsValueRange<IntegerAttr>()) {
1938 uint32_t
index = selector.getZExtValue();
1939 if (
index >= totalSrcElements &&
1940 index != std::numeric_limits<uint32_t>().
max())
1942 <<
index <<
" out of range: expected to be in [0, "
1943 << totalSrcElements <<
") or 0xffffffff";
1952ParseResult spirv::SpecConstantCompositeOp::parse(
OpAsmParser &parser,
1955 StringAttr compositeName;
1967 const char *attrName =
"spec_const";
1974 constituents.push_back(specConstRef);
1980 StringAttr compositeSpecConstituentsName =
1981 spirv::SpecConstantCompositeOp::getConstituentsAttrName(
result.name);
1982 result.addAttribute(compositeSpecConstituentsName,
1989 StringAttr typeAttrName =
1990 spirv::SpecConstantCompositeOp::getTypeAttrName(
result.name);
1991 result.addAttribute(typeAttrName, TypeAttr::get(type));
1996void spirv::SpecConstantCompositeOp::print(
OpAsmPrinter &printer) {
1999 printer <<
" (" << llvm::interleaved(this->getConstituents().getValue())
2003LogicalResult spirv::SpecConstantCompositeOp::verify() {
2004 auto cType = dyn_cast<spirv::CompositeType>(
getType());
2005 auto constituents = this->getConstituents().getValue();
2008 return emitError(
"result type must be a composite type, but provided ")
2011 if (isa<spirv::CooperativeMatrixType>(cType))
2012 return emitError(
"unsupported composite type ") << cType;
2013 if (constituents.size() != cType.getNumElements())
2014 return emitError(
"has incorrect number of operands: expected ")
2015 << cType.getNumElements() <<
", but provided "
2016 << constituents.size();
2018 for (
auto index : llvm::seq<uint32_t>(0, constituents.size())) {
2019 auto constituent = cast<FlatSymbolRefAttr>(constituents[
index]);
2022 (*this)->getParentOp(), constituent.getAttr());
2025 return emitError(
"unknown constituent symbol ") << constituent.getAttr();
2027 Type constituentType;
2028 if (
auto specConstOp = dyn_cast<spirv::SpecConstantOp>(constituentOp)) {
2029 constituentType = specConstOp.getDefaultValue().getType();
2030 }
else if (
auto specConstCompositeOp =
2031 dyn_cast<spirv::SpecConstantCompositeOp>(constituentOp)) {
2032 constituentType = specConstCompositeOp.getType();
2034 return emitError(
"unsupported constituent ")
2035 << constituent.getAttr()
2036 <<
": must reference a spirv.SpecConstant or "
2037 "spirv.SpecConstantComposite";
2040 if (constituentType != cType.getElementType(
index))
2041 return emitError(
"has incorrect types of operands: expected ")
2042 << cType.getElementType(
index) <<
", but provided "
2054spirv::EXTSpecConstantCompositeReplicateOp::parse(
OpAsmParser &parser,
2056 StringAttr compositeName;
2058 const char *attrName =
"spec_const";
2069 StringAttr compositeSpecConstituentName =
2070 spirv::EXTSpecConstantCompositeReplicateOp::getConstituentAttrName(
2072 result.addAttribute(compositeSpecConstituentName, specConstRef);
2074 StringAttr typeAttrName =
2075 spirv::EXTSpecConstantCompositeReplicateOp::getTypeAttrName(
result.name);
2076 result.addAttribute(typeAttrName, TypeAttr::get(type));
2081void spirv::EXTSpecConstantCompositeReplicateOp::print(
OpAsmPrinter &printer) {
2084 printer <<
" (" << this->getConstituent() <<
") : " <<
getType();
2087LogicalResult spirv::EXTSpecConstantCompositeReplicateOp::verify() {
2088 auto compositeType = dyn_cast<spirv::CompositeType>(
getType());
2090 return emitError(
"result type must be a composite type, but provided ")
2094 (*this)->getParentOp(), this->getConstituent());
2097 "splat spec constant reference defining constituent not found");
2099 auto constituentSpecConstOp = dyn_cast<spirv::SpecConstantOp>(constituentOp);
2100 if (!constituentSpecConstOp)
2101 return emitError(
"constituent is not a spec constant");
2103 Type constituentType = constituentSpecConstOp.getDefaultValue().getType();
2104 Type compositeElementType = compositeType.getElementType(0);
2105 if (constituentType != compositeElementType)
2106 return emitError(
"constituent has incorrect type: expected ")
2107 << compositeElementType <<
", but provided " << constituentType;
2116ParseResult spirv::SpecConstantOperationOp::parse(
OpAsmParser &parser,
2132 spirv::YieldOp::create(builder, wrappedOp->
getLoc(), wrappedOp->
getResult(0));
2143void spirv::SpecConstantOperationOp::print(
OpAsmPrinter &printer) {
2144 printer <<
" wraps ";
2148LogicalResult spirv::SpecConstantOperationOp::verifyRegions() {
2149 Block &block = getRegion().getBlocks().
front();
2152 return emitOpError(
"expected exactly 2 nested ops");
2160 if (!isa_and_present<spirv::ConstantOp, spirv::ReferenceOfOp,
2161 spirv::SpecConstantOperationOp>(
2162 operand.getDefiningOp()))
2164 "invalid operand, must be defined by a constant operation");
2173LogicalResult spirv::GLFrexpStructOp::verify() {
2175 dyn_cast<spirv::StructType>(getResult().
getType());
2178 return emitError(
"result type must be a struct type with two memebers");
2182 VectorType exponentVecTy = dyn_cast<VectorType>(exponentTy);
2183 IntegerType exponentIntTy = dyn_cast<IntegerType>(exponentTy);
2185 Type operandTy = getOperand().getType();
2186 VectorType operandVecTy = dyn_cast<VectorType>(operandTy);
2187 FloatType operandFTy = dyn_cast<FloatType>(operandTy);
2189 if (significandTy != operandTy)
2190 return emitError(
"member zero of the resulting struct type must be the "
2191 "same type as the operand");
2193 if (exponentVecTy) {
2194 IntegerType componentIntTy =
2195 dyn_cast<IntegerType>(exponentVecTy.getElementType());
2196 if (!componentIntTy || componentIntTy.getWidth() != 32)
2197 return emitError(
"member one of the resulting struct type must"
2198 "be a scalar or vector of 32 bit integer type");
2199 }
else if (!exponentIntTy || exponentIntTy.getWidth() != 32) {
2200 return emitError(
"member one of the resulting struct type "
2201 "must be a scalar or vector of 32 bit integer type");
2205 if (operandVecTy && exponentVecTy &&
2206 (exponentVecTy.getNumElements() == operandVecTy.getNumElements()))
2209 if (operandFTy && exponentIntTy)
2212 return emitError(
"member one of the resulting struct type must have the same "
2213 "number of components as the operand type");
2222 if (isa<FloatType>(floatType) != isa<IntegerType>(integerType))
2223 return op->
emitOpError(
"operands must both be scalars or vectors");
2226 if (
auto vectorType = dyn_cast<VectorType>(type))
2227 return vectorType.getNumElements();
2232 return op->
emitOpError(
"operands must have the same number of elements");
2237LogicalResult spirv::GLLdexpOp::verify() {
2246LogicalResult spirv::CLLdexpOp::verify() {
2255LogicalResult spirv::CLPownOp::verify() {
2264LogicalResult spirv::CLRootnOp::verify() {
2273LogicalResult spirv::ShiftLeftLogicalOp::verify() {
2281LogicalResult spirv::ShiftRightArithmeticOp::verify() {
2289LogicalResult spirv::ShiftRightLogicalOp::verify() {
2297LogicalResult spirv::VectorTimesScalarOp::verify() {
2299 return emitOpError(
"vector operand and result type mismatch");
2300 auto scalarType = cast<VectorType>(
getType()).getElementType();
2301 if (getScalar().
getType() != scalarType)
2302 return emitOpError(
"scalar operand and result element type match");
p<< " : "<< getMemRefType()<< ", "<< getType();}static LogicalResult verifyVectorMemoryOp(Operation *op, MemRefType memrefType, VectorType vectorType) { if(memrefType.getElementType() !=vectorType.getElementType()) return op-> emitOpError("requires memref and vector types of the same elemental type")
Given a list of lists of parsed operands, populates uniqueOperands with unique operands.
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...
void printOperands(const ContainerType &container)
Print a comma separated list of operands.
virtual void printOptionalAttrDictWithKeyword(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary prefixed with 'attribute...
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
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 allows for representing and managing the symbol table used by operations with the 'SymbolT...
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...
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.
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.