32 #include "llvm/ADT/APFloat.h"
33 #include "llvm/ADT/APInt.h"
34 #include "llvm/ADT/ArrayRef.h"
35 #include "llvm/ADT/STLExtras.h"
36 #include "llvm/ADT/StringExtras.h"
37 #include "llvm/ADT/TypeSwitch.h"
38 #include "llvm/Support/InterleavedRange.h"
42 #include <type_traits>
52 auto constOp = dyn_cast_or_null<spirv::ConstantOp>(op);
56 auto valueAttr = constOp.getValue();
57 auto integerValueAttr = llvm::dyn_cast<IntegerAttr>(valueAttr);
58 if (!integerValueAttr) {
62 if (integerValueAttr.getType().isSignlessInteger())
63 value = integerValueAttr.getInt();
65 value = integerValueAttr.getSInt();
72 spirv::MemorySemantics memorySemantics) {
79 auto atMostOneInSet = spirv::MemorySemantics::Acquire |
80 spirv::MemorySemantics::Release |
81 spirv::MemorySemantics::AcquireRelease |
82 spirv::MemorySemantics::SequentiallyConsistent;
85 llvm::popcount(
static_cast<uint32_t
>(memorySemantics & atMostOneInSet));
88 "expected at most one of these four memory constraints "
89 "to be set: `Acquire`, `Release`,"
90 "`AcquireRelease` or `SequentiallyConsistent`");
99 stringifyDecoration(spirv::Decoration::DescriptorSet));
100 auto bindingName = llvm::convertToSnakeFromCamelCase(
101 stringifyDecoration(spirv::Decoration::Binding));
104 if (descriptorSet && binding) {
107 printer <<
" bind(" << descriptorSet.getInt() <<
", " << binding.getInt()
112 auto builtInName = llvm::convertToSnakeFromCamelCase(
113 stringifyDecoration(spirv::Decoration::BuiltIn));
114 if (
auto builtin = op->
getAttrOfType<StringAttr>(builtInName)) {
115 printer <<
" " << builtInName <<
"(\"" << builtin.getValue() <<
"\")";
116 elidedAttrs.push_back(builtInName);
134 auto fnType = llvm::dyn_cast<FunctionType>(type);
136 parser.
emitError(loc,
"expected function type");
141 result.
addTypes(fnType.getResults());
152 assert(op->
getNumResults() == 1 &&
"op should have one result");
158 [&](
Type type) { return type != resultType; })) {
167 p <<
" : " << resultType;
170 template <
typename BlockReadWriteOpTy>
174 if (
auto valVecTy = llvm::dyn_cast<VectorType>(valType))
175 valType = valVecTy.getElementType();
178 llvm::cast<spirv::PointerType>(ptr.
getType()).getPointeeType()) {
179 return op.emitOpError(
"mismatch in result type and pointer type");
190 if (indices.empty()) {
191 emitErrorFn(
"expected at least one index for spirv.CompositeExtract");
195 for (
auto index : indices) {
196 if (
auto cType = llvm::dyn_cast<spirv::CompositeType>(type)) {
197 if (cType.hasCompileTimeKnownNumElements() &&
199 static_cast<uint64_t
>(index) >= cType.getNumElements())) {
200 emitErrorFn(
"index ") << index <<
" out of bounds for " << type;
203 type = cType.getElementType(index);
205 emitErrorFn(
"cannot extract from non-composite type ")
206 << type <<
" with index " << index;
216 auto indicesArrayAttr = llvm::dyn_cast<ArrayAttr>(indices);
217 if (!indicesArrayAttr) {
218 emitErrorFn(
"expected a 32-bit integer array attribute for 'indices'");
221 if (indicesArrayAttr.empty()) {
222 emitErrorFn(
"expected at least one index for spirv.CompositeExtract");
227 for (
auto indexAttr : indicesArrayAttr) {
228 auto indexIntAttr = llvm::dyn_cast<IntegerAttr>(indexAttr);
230 emitErrorFn(
"expected an 32-bit integer for index, but found '")
234 indexVals.push_back(indexIntAttr.getInt());
254 template <
typename ExtendedBinaryOp>
256 auto resultType = llvm::cast<spirv::StructType>(op.getType());
257 if (resultType.getNumElements() != 2)
258 return op.emitOpError(
"expected result struct type containing two members");
260 if (!llvm::all_equal({op.getOperand1().
getType(), op.getOperand2().getType(),
261 resultType.getElementType(0),
262 resultType.getElementType(1)}))
263 return op.emitOpError(
264 "expected all operand types and struct member types are the same");
281 auto structType = llvm::dyn_cast<spirv::StructType>(resultType);
282 if (!structType || structType.getNumElements() != 2)
283 return parser.
emitError(loc,
"expected spirv.struct type with two members");
303 return op->
emitError(
"expected the same type for the first operand and "
304 "result, but provided ")
316 spirv::GlobalVariableOp var) {
321 auto varOp = dyn_cast_or_null<spirv::GlobalVariableOp>(
325 return emitOpError(
"expected spirv.GlobalVariable symbol");
327 if (getPointer().
getType() != varOp.getType()) {
329 "result type mismatch with the referenced global variable's type");
339 operand_range constituents = this->getConstituents();
347 auto coopElementType =
350 [](
auto coopType) {
return coopType.getElementType(); })
351 .Default([](
Type) {
return nullptr; });
354 if (coopElementType) {
355 if (constituents.size() != 1)
356 return emitOpError(
"has incorrect number of operands: expected ")
357 <<
"1, but provided " << constituents.size();
358 if (coopElementType != constituents.front().getType())
359 return emitOpError(
"operand type mismatch: expected operand type ")
360 << coopElementType <<
", but provided "
361 << constituents.front().getType();
366 auto cType = llvm::cast<spirv::CompositeType>(
getType());
367 if (constituents.size() == cType.getNumElements()) {
368 for (
auto index : llvm::seq<uint32_t>(0, constituents.size())) {
369 if (constituents[index].
getType() != cType.getElementType(index)) {
370 return emitOpError(
"operand type mismatch: expected operand type ")
371 << cType.getElementType(index) <<
", but provided "
372 << constituents[index].getType();
379 auto resultType = llvm::dyn_cast<VectorType>(cType);
382 "expected to return a vector or cooperative matrix when the number of "
383 "constituents is less than what the result needs");
386 for (
Value component : constituents) {
387 if (!llvm::isa<VectorType>(component.getType()) &&
388 !component.getType().isIntOrFloat())
389 return emitOpError(
"operand type mismatch: expected operand to have "
390 "a scalar or vector type, but provided ")
391 << component.getType();
393 Type elementType = component.getType();
394 if (
auto vectorType = llvm::dyn_cast<VectorType>(component.getType())) {
395 sizes.push_back(vectorType.getNumElements());
396 elementType = vectorType.getElementType();
401 if (elementType != resultType.getElementType())
402 return emitOpError(
"operand element type mismatch: expected to be ")
403 << resultType.getElementType() <<
", but provided " << elementType;
405 unsigned totalCount = std::accumulate(sizes.begin(), sizes.end(), 0);
406 if (totalCount != cType.getNumElements())
407 return emitOpError(
"has incorrect number of operands: expected ")
408 << cType.getNumElements() <<
", but provided " << totalCount;
425 build(builder, state, elementType, composite, indexAttr);
432 StringRef indicesAttrName =
433 spirv::CompositeExtractOp::getIndicesAttrName(result.
name);
455 printer <<
' ' << getComposite() <<
getIndices() <<
" : "
460 auto indicesArrayAttr = llvm::dyn_cast<ArrayAttr>(
getIndices());
467 return emitOpError(
"invalid result type: expected ")
468 << resultType <<
" but provided " <<
getType();
482 build(builder, state, composite.
getType(),
object, composite, indexAttr);
488 Type objectType, compositeType;
490 StringRef indicesAttrName =
491 spirv::CompositeInsertOp::getIndicesAttrName(result.
name);
505 auto indicesArrayAttr = llvm::dyn_cast<ArrayAttr>(
getIndices());
511 if (objectType != getObject().
getType()) {
512 return emitOpError(
"object operand type should be ")
513 << objectType <<
", but found " << getObject().getType();
517 return emitOpError(
"result type should be the same as "
518 "the composite type, but found ")
519 << getComposite().getType() <<
" vs " <<
getType();
526 printer <<
" " << getObject() <<
", " << getComposite() <<
getIndices()
527 <<
" : " << getObject().
getType() <<
" into "
528 << getComposite().getType();
538 StringRef valueAttrName = spirv::ConstantOp::getValueAttrName(result.
name);
543 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(value))
544 type = typedAttr.getType();
545 if (llvm::isa<NoneType, TensorType>(type)) {
554 printer <<
' ' << getValue();
555 if (llvm::isa<spirv::ArrayType>(
getType()))
561 if (llvm::isa<IntegerAttr, FloatAttr>(value)) {
562 auto valueType = llvm::cast<TypedAttr>(value).getType();
563 if (valueType != opType)
564 return op.emitOpError(
"result type (")
565 << opType <<
") does not match value type (" << valueType <<
")";
568 if (llvm::isa<DenseIntOrFPElementsAttr, SparseElementsAttr>(value)) {
569 auto valueType = llvm::cast<TypedAttr>(value).getType();
570 if (valueType == opType)
572 auto arrayType = llvm::dyn_cast<spirv::ArrayType>(opType);
573 auto shapedType = llvm::dyn_cast<ShapedType>(valueType);
575 return op.emitOpError(
"result or element type (")
576 << opType <<
") does not match value type (" << valueType
577 <<
"), must be the same or spirv.array";
579 int numElements = arrayType.getNumElements();
580 auto opElemType = arrayType.getElementType();
581 while (
auto t = llvm::dyn_cast<spirv::ArrayType>(opElemType)) {
582 numElements *= t.getNumElements();
583 opElemType = t.getElementType();
585 if (!opElemType.isIntOrFloat())
586 return op.emitOpError(
"only support nested array result type");
588 auto valueElemType = shapedType.getElementType();
589 if (valueElemType != opElemType) {
590 return op.emitOpError(
"result element type (")
591 << opElemType <<
") does not match value element type ("
592 << valueElemType <<
")";
595 if (numElements != shapedType.getNumElements()) {
596 return op.emitOpError(
"result number of elements (")
597 << numElements <<
") does not match value number of elements ("
598 << shapedType.getNumElements() <<
")";
602 if (
auto arrayAttr = llvm::dyn_cast<ArrayAttr>(value)) {
603 auto arrayType = llvm::dyn_cast<spirv::ArrayType>(opType);
605 return op.emitOpError(
606 "must have spirv.array result type for array value");
607 Type elemType = arrayType.getElementType();
608 for (
Attribute element : arrayAttr.getValue()) {
615 return op.emitOpError(
"cannot have attribute: ") << value;
625 bool spirv::ConstantOp::isBuildableWith(
Type type) {
627 if (!llvm::isa<spirv::SPIRVType>(type))
632 return llvm::isa<spirv::ArrayType>(type);
640 if (
auto intType = llvm::dyn_cast<IntegerType>(type)) {
641 unsigned width = intType.getWidth();
643 return builder.
create<spirv::ConstantOp>(loc, type,
645 return builder.
create<spirv::ConstantOp>(
648 if (
auto floatType = llvm::dyn_cast<FloatType>(type)) {
649 return builder.
create<spirv::ConstantOp>(
652 if (
auto vectorType = llvm::dyn_cast<VectorType>(type)) {
653 Type elemType = vectorType.getElementType();
654 if (llvm::isa<IntegerType>(elemType)) {
655 return builder.
create<spirv::ConstantOp>(
660 if (llvm::isa<FloatType>(elemType)) {
661 return builder.
create<spirv::ConstantOp>(
668 llvm_unreachable(
"unimplemented types for ConstantOp::getZero()");
671 spirv::ConstantOp spirv::ConstantOp::getOne(
Type type,
Location loc,
673 if (
auto intType = llvm::dyn_cast<IntegerType>(type)) {
674 unsigned width = intType.getWidth();
676 return builder.
create<spirv::ConstantOp>(loc, type,
678 return builder.
create<spirv::ConstantOp>(
681 if (
auto floatType = llvm::dyn_cast<FloatType>(type)) {
682 return builder.
create<spirv::ConstantOp>(
685 if (
auto vectorType = llvm::dyn_cast<VectorType>(type)) {
686 Type elemType = vectorType.getElementType();
687 if (llvm::isa<IntegerType>(elemType)) {
688 return builder.
create<spirv::ConstantOp>(
693 if (llvm::isa<FloatType>(elemType)) {
694 return builder.
create<spirv::ConstantOp>(
701 llvm_unreachable(
"unimplemented types for ConstantOp::getOne()");
704 void mlir::spirv::ConstantOp::getAsmResultNames(
709 llvm::raw_svector_ostream specialName(specialNameBuffer);
710 specialName <<
"cst";
712 IntegerType intTy = llvm::dyn_cast<IntegerType>(type);
714 if (IntegerAttr intCst = llvm::dyn_cast<IntegerAttr>(getValue())) {
715 if (intTy && intTy.getWidth() == 1) {
716 return setNameFn(getResult(), (intCst.getInt() ?
"true" :
"false"));
719 if (intTy.isSignless()) {
720 specialName << intCst.getInt();
721 }
else if (intTy.isUnsigned()) {
722 specialName << intCst.getUInt();
724 specialName << intCst.getSInt();
728 if (intTy || llvm::isa<FloatType>(type)) {
729 specialName <<
'_' << type;
732 if (
auto vecType = llvm::dyn_cast<VectorType>(type)) {
733 specialName <<
"_vec_";
734 specialName << vecType.getDimSize(0);
736 Type elementType = vecType.getElementType();
738 if (llvm::isa<IntegerType>(elementType) ||
739 llvm::isa<FloatType>(elementType)) {
740 specialName <<
"x" << elementType;
744 setNameFn(getResult(), specialName.str());
747 void mlir::spirv::AddressOfOp::getAsmResultNames(
750 llvm::raw_svector_ostream specialName(specialNameBuffer);
751 specialName << getVariable() <<
"_addr";
752 setNameFn(getResult(), specialName.str());
768 spirv::ExecutionModel executionModel,
769 spirv::FuncOp
function,
771 build(builder, state,
778 spirv::ExecutionModel execModel;
782 if (parseEnumStrAttr<spirv::ExecutionModelAttr>(execModel, parser, result) ||
791 FlatSymbolRefAttr var;
793 if (parser.parseAttribute(var, Type(),
"var_symbol", attrs))
795 interfaceVars.push_back(var);
808 auto interfaceVars = getInterface().getValue();
809 if (!interfaceVars.empty())
810 printer <<
", " << llvm::interleaved(interfaceVars);
824 spirv::FuncOp
function,
825 spirv::ExecutionMode executionMode,
834 spirv::ExecutionMode execMode;
837 parseEnumStrAttr<spirv::ExecutionModeAttr>(execMode, parser, result)) {
849 values.push_back(llvm::cast<IntegerAttr>(value).getInt());
851 StringRef valuesAttrName =
852 spirv::ExecutionModeOp::getValuesAttrName(result.
name);
861 printer <<
" \"" << stringifyExecutionMode(getExecutionMode()) <<
"\"";
862 ArrayAttr values = this->getValues();
864 printer <<
", " << llvm::interleaved(values.getAsValueRange<IntegerAttr>());
884 bool isVariadic =
false;
886 parser,
false, entryArgs, isVariadic, resultTypes,
891 for (
auto &arg : entryArgs)
892 argTypes.push_back(arg.type);
898 spirv::FunctionControl fnControl;
899 if (parseEnumStrAttr<spirv::FunctionControlAttr>(fnControl, parser, result))
907 assert(resultAttrs.size() == resultTypes.size());
909 builder, result, entryArgs, resultAttrs, getArgAttrsAttrName(result.
name),
910 getResAttrsAttrName(result.
name));
916 return failure(parseResult.
has_value() && failed(*parseResult));
923 auto fnType = getFunctionType();
925 printer, *
this, fnType.getInputs(),
926 false, fnType.getResults());
927 printer <<
" \"" << spirv::stringifyFunctionControl(getFunctionControl())
931 {spirv::attributeName<spirv::FunctionControl>(),
932 getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
933 getFunctionControlAttrName()});
936 Region &body = this->getBody();
944 LogicalResult spirv::FuncOp::verifyType() {
945 FunctionType fnType = getFunctionType();
946 if (fnType.getNumResults() > 1)
947 return emitOpError(
"cannot have more than one result");
949 auto hasDecorationAttr = [&](spirv::Decoration decoration,
951 auto func = llvm::cast<FunctionOpInterface>(getOperation());
952 for (
auto argAttr : cast<FunctionOpInterface>(func).
getArgAttrs(argIndex)) {
953 if (argAttr.getName() != spirv::DecorationAttr::name)
955 if (
auto decAttr = dyn_cast<spirv::DecorationAttr>(argAttr.getValue()))
956 return decAttr.getValue() == decoration;
961 for (
unsigned i = 0, e = this->getNumArguments(); i != e; ++i) {
962 Type param = fnType.getInputs()[i];
963 auto inputPtrType = dyn_cast<spirv::PointerType>(param);
967 auto pointeePtrType =
968 dyn_cast<spirv::PointerType>(inputPtrType.getPointeeType());
969 if (pointeePtrType) {
975 if (pointeePtrType.getStorageClass() !=
976 spirv::StorageClass::PhysicalStorageBuffer)
980 hasDecorationAttr(spirv::Decoration::AliasedPointer, i);
981 bool hasRestrictPtr =
982 hasDecorationAttr(spirv::Decoration::RestrictPointer, i);
983 if (!hasAliasedPtr && !hasRestrictPtr)
985 <<
"with a pointer points to a physical buffer pointer must "
986 "be decorated either 'AliasedPointer' or 'RestrictPointer'";
993 if (
auto pointeeArrayType =
994 dyn_cast<spirv::ArrayType>(inputPtrType.getPointeeType())) {
996 dyn_cast<spirv::PointerType>(pointeeArrayType.getElementType());
998 pointeePtrType = inputPtrType;
1001 if (!pointeePtrType || pointeePtrType.getStorageClass() !=
1002 spirv::StorageClass::PhysicalStorageBuffer)
1005 bool hasAliased = hasDecorationAttr(spirv::Decoration::Aliased, i);
1006 bool hasRestrict = hasDecorationAttr(spirv::Decoration::Restrict, i);
1007 if (!hasAliased && !hasRestrict)
1008 return emitOpError() <<
"with physical buffer pointer must be decorated "
1009 "either 'Aliased' or 'Restrict'";
1015 LogicalResult spirv::FuncOp::verifyBody() {
1016 FunctionType fnType = getFunctionType();
1017 if (!isExternal()) {
1018 Block &entryBlock = front();
1020 unsigned numArguments = this->getNumArguments();
1022 return emitOpError(
"entry block must have ")
1023 << numArguments <<
" arguments to match function signature";
1025 for (
auto [index, fnArgType, blockArgType] :
1027 if (blockArgType != fnArgType) {
1028 return emitOpError(
"type of entry block argument #")
1029 << index <<
'(' << blockArgType
1030 <<
") must match the type of the corresponding argument in "
1031 <<
"function signature(" << fnArgType <<
')';
1037 if (
auto retOp = dyn_cast<spirv::ReturnOp>(op)) {
1038 if (fnType.getNumResults() != 0)
1039 return retOp.emitOpError(
"cannot be used in functions returning value");
1040 }
else if (
auto retOp = dyn_cast<spirv::ReturnValueOp>(op)) {
1041 if (fnType.getNumResults() != 1)
1042 return retOp.emitOpError(
1043 "returns 1 value but enclosing function requires ")
1044 << fnType.getNumResults() <<
" results";
1046 auto retOperandType = retOp.getValue().getType();
1047 auto fnResultType = fnType.getResult(0);
1048 if (retOperandType != fnResultType)
1049 return retOp.emitOpError(
" return value's type (")
1050 << retOperandType <<
") mismatch with function's result type ("
1051 << fnResultType <<
")";
1058 return failure(walkResult.wasInterrupted());
1062 StringRef name, FunctionType type,
1063 spirv::FunctionControl control,
1067 state.addAttribute(getFunctionTypeAttrName(state.name),
TypeAttr::get(type));
1068 state.addAttribute(spirv::attributeName<spirv::FunctionControl>(),
1069 builder.
getAttr<spirv::FunctionControlAttr>(control));
1070 state.attributes.append(attrs.begin(), attrs.end());
1118 Type type, StringRef name,
1119 unsigned descriptorSet,
unsigned binding) {
1122 spirv::SPIRVDialect::getAttributeName(spirv::Decoration::DescriptorSet),
1125 spirv::SPIRVDialect::getAttributeName(spirv::Decoration::Binding),
1130 Type type, StringRef name,
1131 spirv::BuiltIn builtin) {
1134 spirv::SPIRVDialect::getAttributeName(spirv::Decoration::BuiltIn),
1141 StringAttr nameAttr;
1142 StringRef initializerAttrName =
1143 spirv::GlobalVariableOp::getInitializerAttrName(result.
name);
1164 StringRef typeAttrName =
1165 spirv::GlobalVariableOp::getTypeAttrName(result.
name);
1170 if (!llvm::isa<spirv::PointerType>(type)) {
1171 return parser.
emitError(loc,
"expected spirv.ptr type");
1180 spirv::attributeName<spirv::StorageClass>()};
1187 StringRef initializerAttrName = this->getInitializerAttrName();
1189 if (
auto initializer = this->getInitializer()) {
1190 printer <<
" " << initializerAttrName <<
'(';
1193 elidedAttrs.push_back(initializerAttrName);
1196 StringRef typeAttrName = this->getTypeAttrName();
1197 elidedAttrs.push_back(typeAttrName);
1199 printer <<
" : " <<
getType();
1203 if (!llvm::isa<spirv::PointerType>(
getType()))
1204 return emitOpError(
"result must be of a !spv.ptr type");
1210 auto storageClass = this->storageClass();
1211 if (storageClass == spirv::StorageClass::Generic ||
1212 storageClass == spirv::StorageClass::Function) {
1213 return emitOpError(
"storage class cannot be '")
1214 << stringifyStorageClass(storageClass) <<
"'";
1218 this->getInitializerAttrName())) {
1220 (*this)->getParentOp(), init.getAttr());
1224 if (!initOp || !isa<spirv::GlobalVariableOp, spirv::SpecConstantOp,
1225 spirv::SpecConstantCompositeOp>(initOp)) {
1226 return emitOpError(
"initializer must be result of a "
1227 "spirv.SpecConstant or spirv.GlobalVariable or "
1228 "spirv.SpecConstantCompositeOp op");
1253 spirv::StorageClass storageClass;
1264 if (
auto valVecTy = llvm::dyn_cast<VectorType>(elementType))
1275 printer <<
" " << getPtr() <<
", " << getValue() <<
" : "
1276 << getValue().getType();
1367 std::optional<StringRef> name) {
1377 spirv::AddressingModel addressingModel,
1378 spirv::MemoryModel memoryModel,
1379 std::optional<VerCapExtAttr> vceTriple,
1380 std::optional<StringRef> name) {
1383 builder.
getAttr<spirv::AddressingModelAttr>(addressingModel));
1384 state.addAttribute(
"memory_model",
1385 builder.
getAttr<spirv::MemoryModelAttr>(memoryModel));
1389 state.addAttribute(getVCETripleAttrName(), *vceTriple);
1400 StringAttr nameAttr;
1405 spirv::AddressingModel addrModel;
1406 spirv::MemoryModel memoryModel;
1407 if (spirv::parseEnumKeywordAttr<spirv::AddressingModelAttr>(addrModel, parser,
1409 spirv::parseEnumKeywordAttr<spirv::MemoryModelAttr>(memoryModel, parser,
1416 spirv::ModuleOp::getVCETripleAttrName(),
1433 if (std::optional<StringRef> name = getName()) {
1442 auto addressingModelAttrName = spirv::attributeName<spirv::AddressingModel>();
1443 auto memoryModelAttrName = spirv::attributeName<spirv::MemoryModel>();
1444 elidedAttrs.assign({addressingModelAttrName, memoryModelAttrName,
1447 if (std::optional<spirv::VerCapExtAttr> triple = getVceTriple()) {
1448 printer <<
" requires " << *triple;
1449 elidedAttrs.push_back(spirv::ModuleOp::getVCETripleAttrName());
1457 LogicalResult spirv::ModuleOp::verifyRegions() {
1458 Dialect *dialect = (*this)->getDialect();
1463 for (
auto &op : *getBody()) {
1465 return op.
emitError(
"'spirv.module' can only contain spirv.* ops");
1470 if (
auto entryPointOp = dyn_cast<spirv::EntryPointOp>(op)) {
1471 auto funcOp =
table.lookup<spirv::FuncOp>(entryPointOp.getFn());
1473 return entryPointOp.emitError(
"function '")
1474 << entryPointOp.getFn() <<
"' not found in 'spirv.module'";
1476 if (
auto interface = entryPointOp.getInterface()) {
1478 auto varSymRef = llvm::dyn_cast<FlatSymbolRefAttr>(varRef);
1480 return entryPointOp.emitError(
1481 "expected symbol reference for interface "
1482 "specification instead of '")
1486 table.lookup<spirv::GlobalVariableOp>(varSymRef.getValue());
1488 return entryPointOp.emitError(
"expected spirv.GlobalVariable "
1489 "symbol reference instead of'")
1490 << varSymRef <<
"'";
1495 auto key = std::pair<spirv::FuncOp, spirv::ExecutionModel>(
1496 funcOp, entryPointOp.getExecutionModel());
1497 if (!entryPoints.try_emplace(key, entryPointOp).second)
1498 return entryPointOp.emitError(
"duplicate of a previous EntryPointOp");
1499 }
else if (
auto funcOp = dyn_cast<spirv::FuncOp>(op)) {
1503 auto linkageAttr = funcOp.getLinkageAttributes();
1504 auto hasImportLinkage =
1505 linkageAttr && (linkageAttr.value().getLinkageType().getValue() ==
1506 spirv::LinkageType::Import);
1507 if (funcOp.isExternal() && !hasImportLinkage)
1509 "'spirv.module' cannot contain external functions "
1510 "without 'Import' linkage_attributes (LinkageAttributes)");
1513 for (
auto &block : funcOp)
1514 for (
auto &op : block) {
1517 "functions in 'spirv.module' can only contain spirv.* ops");
1531 (*this)->getParentOp(), getSpecConstAttr());
1534 auto specConstOp = dyn_cast_or_null<spirv::SpecConstantOp>(specConstSym);
1536 constType = specConstOp.getDefaultValue().getType();
1538 auto specConstCompositeOp =
1539 dyn_cast_or_null<spirv::SpecConstantCompositeOp>(specConstSym);
1540 if (specConstCompositeOp)
1541 constType = specConstCompositeOp.getType();
1543 if (!specConstOp && !specConstCompositeOp)
1545 "expected spirv.SpecConstant or spirv.SpecConstantComposite symbol");
1547 if (getReference().
getType() != constType)
1548 return emitOpError(
"result type mismatch with the referenced "
1549 "specialization constant's type");
1560 StringAttr nameAttr;
1562 StringRef defaultValueAttrName =
1563 spirv::SpecConstantOp::getDefaultValueAttrName(result.
name);
1571 IntegerAttr specIdAttr;
1588 if (
auto specID = (*this)->getAttrOfType<IntegerAttr>(
kSpecIdAttrName))
1590 printer <<
" = " << getDefaultValue();
1594 if (
auto specID = (*this)->getAttrOfType<IntegerAttr>(
kSpecIdAttrName))
1595 if (specID.getValue().isNegative())
1596 return emitOpError(
"SpecId cannot be negative");
1598 auto value = getDefaultValue();
1599 if (llvm::isa<IntegerAttr, FloatAttr>(value)) {
1601 if (!llvm::isa<spirv::SPIRVType>(value.getType()))
1602 return emitOpError(
"default value bitwidth disallowed");
1606 "default value can only be a bool, integer, or float scalar");
1614 VectorType resultType = llvm::cast<VectorType>(
getType());
1616 size_t numResultElements = resultType.getNumElements();
1617 if (numResultElements != getComponents().size())
1618 return emitOpError(
"result type element count (")
1619 << numResultElements
1620 <<
") mismatch with the number of component selectors ("
1621 << getComponents().size() <<
")";
1623 size_t totalSrcElements =
1624 llvm::cast<VectorType>(getVector1().
getType()).getNumElements() +
1625 llvm::cast<VectorType>(getVector2().
getType()).getNumElements();
1627 for (
const auto &selector : getComponents().getAsValueRange<IntegerAttr>()) {
1628 uint32_t index = selector.getZExtValue();
1629 if (index >= totalSrcElements &&
1630 index != std::numeric_limits<uint32_t>().
max())
1631 return emitOpError(
"component selector ")
1632 << index <<
" out of range: expected to be in [0, "
1633 << totalSrcElements <<
") or 0xffffffff";
1646 [](
auto matrixType) {
return matrixType.getElementType(); })
1647 .Default([](
Type) {
return nullptr; });
1649 assert(elementType &&
"Unhandled type");
1652 if (getScalar().
getType() != elementType)
1653 return emitOpError(
"input matrix components' type and scaling value must "
1654 "have the same type");
1664 auto inputMatrix = llvm::cast<spirv::MatrixType>(getMatrix().
getType());
1665 auto resultMatrix = llvm::cast<spirv::MatrixType>(getResult().
getType());
1668 if (inputMatrix.getNumRows() != resultMatrix.getNumColumns())
1669 return emitError(
"input matrix rows count must be equal to "
1670 "output matrix columns count");
1672 if (inputMatrix.getNumColumns() != resultMatrix.getNumRows())
1673 return emitError(
"input matrix columns count must be equal to "
1674 "output matrix rows count");
1677 if (inputMatrix.getElementType() != resultMatrix.getElementType())
1678 return emitError(
"input and output matrices must have the same "
1689 auto matrixType = llvm::cast<spirv::MatrixType>(getMatrix().
getType());
1690 auto vectorType = llvm::cast<VectorType>(getVector().
getType());
1691 auto resultType = llvm::cast<VectorType>(
getType());
1693 if (matrixType.getNumColumns() != vectorType.getNumElements())
1694 return emitOpError(
"matrix columns (")
1695 << matrixType.getNumColumns() <<
") must match vector operand size ("
1696 << vectorType.getNumElements() <<
")";
1698 if (resultType.getNumElements() != matrixType.getNumRows())
1699 return emitOpError(
"result size (")
1700 << resultType.getNumElements() <<
") must match the matrix rows ("
1701 << matrixType.getNumRows() <<
")";
1703 if (matrixType.getElementType() != resultType.getElementType())
1704 return emitOpError(
"matrix and result element types must match");
1714 auto vectorType = llvm::cast<VectorType>(getVector().
getType());
1715 auto matrixType = llvm::cast<spirv::MatrixType>(getMatrix().
getType());
1716 auto resultType = llvm::cast<VectorType>(
getType());
1718 if (matrixType.getNumRows() != vectorType.getNumElements())
1719 return emitOpError(
"number of components in vector must equal the number "
1720 "of components in each column in matrix");
1722 if (resultType.getNumElements() != matrixType.getNumColumns())
1723 return emitOpError(
"number of columns in matrix must equal the number of "
1724 "components in result");
1726 if (matrixType.getElementType() != resultType.getElementType())
1727 return emitOpError(
"matrix must be a matrix with the same component type "
1728 "as the component type in result");
1738 auto leftMatrix = llvm::cast<spirv::MatrixType>(getLeftmatrix().
getType());
1739 auto rightMatrix = llvm::cast<spirv::MatrixType>(getRightmatrix().
getType());
1740 auto resultMatrix = llvm::cast<spirv::MatrixType>(getResult().
getType());
1743 if (leftMatrix.getNumColumns() != rightMatrix.getNumRows())
1744 return emitError(
"left matrix columns' count must be equal to "
1745 "the right matrix rows' count");
1748 if (rightMatrix.getNumColumns() != resultMatrix.getNumColumns())
1750 "right and result matrices must have equal columns' count");
1753 if (rightMatrix.getElementType() != resultMatrix.getElementType())
1754 return emitError(
"right and result matrices' component type must"
1758 if (leftMatrix.getElementType() != resultMatrix.getElementType())
1759 return emitError(
"left and result matrices' component type"
1760 " must be the same");
1763 if (leftMatrix.getNumRows() != resultMatrix.getNumRows())
1764 return emitError(
"left and result matrices must have equal rows' count");
1776 StringAttr compositeName;
1788 const char *attrName =
"spec_const";
1795 constituents.push_back(specConstRef);
1801 StringAttr compositeSpecConstituentsName =
1802 spirv::SpecConstantCompositeOp::getConstituentsAttrName(result.
name);
1810 StringAttr typeAttrName =
1811 spirv::SpecConstantCompositeOp::getTypeAttrName(result.
name);
1820 printer <<
" (" << llvm::interleaved(this->getConstituents().getValue())
1825 auto cType = llvm::dyn_cast<spirv::CompositeType>(
getType());
1826 auto constituents = this->getConstituents().getValue();
1829 return emitError(
"result type must be a composite type, but provided ")
1832 if (llvm::isa<spirv::CooperativeMatrixType>(cType))
1833 return emitError(
"unsupported composite type ") << cType;
1834 if (constituents.size() != cType.getNumElements())
1835 return emitError(
"has incorrect number of operands: expected ")
1836 << cType.getNumElements() <<
", but provided "
1837 << constituents.size();
1839 for (
auto index : llvm::seq<uint32_t>(0, constituents.size())) {
1840 auto constituent = llvm::cast<FlatSymbolRefAttr>(constituents[index]);
1842 auto constituentSpecConstOp =
1844 (*this)->getParentOp(), constituent.getAttr()));
1846 if (constituentSpecConstOp.getDefaultValue().getType() !=
1847 cType.getElementType(index))
1848 return emitError(
"has incorrect types of operands: expected ")
1849 << cType.getElementType(index) <<
", but provided "
1850 << constituentSpecConstOp.getDefaultValue().getType();
1888 printer <<
" wraps ";
1892 LogicalResult spirv::SpecConstantOperationOp::verifyRegions() {
1893 Block &block = getRegion().getBlocks().
front();
1896 return emitOpError(
"expected exactly 2 nested ops");
1901 return emitOpError(
"invalid enclosed op");
1904 if (!isa<spirv::ConstantOp, spirv::ReferenceOfOp,
1905 spirv::SpecConstantOperationOp>(operand.getDefiningOp()))
1907 "invalid operand, must be defined by a constant operation");
1918 llvm::dyn_cast<spirv::StructType>(getResult().
getType());
1921 return emitError(
"result type must be a struct type with two memebers");
1925 VectorType exponentVecTy = llvm::dyn_cast<VectorType>(exponentTy);
1926 IntegerType exponentIntTy = llvm::dyn_cast<IntegerType>(exponentTy);
1928 Type operandTy = getOperand().getType();
1929 VectorType operandVecTy = llvm::dyn_cast<VectorType>(operandTy);
1930 FloatType operandFTy = llvm::dyn_cast<FloatType>(operandTy);
1932 if (significandTy != operandTy)
1933 return emitError(
"member zero of the resulting struct type must be the "
1934 "same type as the operand");
1936 if (exponentVecTy) {
1937 IntegerType componentIntTy =
1938 llvm::dyn_cast<IntegerType>(exponentVecTy.getElementType());
1939 if (!componentIntTy || componentIntTy.getWidth() != 32)
1940 return emitError(
"member one of the resulting struct type must"
1941 "be a scalar or vector of 32 bit integer type");
1942 }
else if (!exponentIntTy || exponentIntTy.getWidth() != 32) {
1943 return emitError(
"member one of the resulting struct type "
1944 "must be a scalar or vector of 32 bit integer type");
1948 if (operandVecTy && exponentVecTy &&
1949 (exponentVecTy.getNumElements() == operandVecTy.getNumElements()))
1952 if (operandFTy && exponentIntTy)
1955 return emitError(
"member one of the resulting struct type must have the same "
1956 "number of components as the operand type");
1964 Type significandType = getX().getType();
1965 Type exponentType = getExp().getType();
1967 if (llvm::isa<FloatType>(significandType) !=
1968 llvm::isa<IntegerType>(exponentType))
1969 return emitOpError(
"operands must both be scalars or vectors");
1972 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
1973 return vectorType.getNumElements();
1978 return emitOpError(
"operands must have the same number of elements");
2013 return emitOpError(
"vector operand and result type mismatch");
2014 auto scalarType = llvm::cast<VectorType>(
getType()).getElementType();
2015 if (getScalar().
getType() != scalarType)
2016 return emitOpError(
"scalar operand and result element type match");
static std::string bindingName()
Returns the string name of the Binding decoration.
static std::string descriptorSetName()
Returns the string name of the DescriptorSet decoration.
static Value getZero(OpBuilder &b, Location loc, Type elementType)
Get zero value for an element type.
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 void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
static ParseResult parseArithmeticExtendedBinaryOp(OpAsmParser &parser, OperationState &result)
static LogicalResult verifyConstantType(spirv::ConstantOp op, Attribute value, Type opType)
static ParseResult parseOneResultSameOperandTypeOp(OpAsmParser &parser, OperationState &result)
static LogicalResult verifyArithmeticExtendedBinaryOp(ExtendedBinaryOp op)
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 ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
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.
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)
MLIRContext * getContext() const
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
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...
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.
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 Operation * parseGenericOperation(Block *insertBlock, Block::iterator insertPt)=0
Parse an operation in its generic form.
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.
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes=std::nullopt, ArrayRef< Location > locs=std::nullopt)
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
A trait to mark ops that can be enclosed/wrapped in a SpecConstantOperation op.
type_range getType() const
Operation is the basic unit of execution within MLIR.
Value getOperand(unsigned idx)
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
AttrClass getAttrOfType(StringAttr name)
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this operation.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
operand_type_range getOperandTypes()
result_type_range getResultTypes()
operand_range getOperands()
Returns an iterator on the underlying Value's.
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 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.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
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.
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
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.
void printVariableDecorations(Operation *op, OpAsmPrinter &printer, SmallVectorImpl< StringRef > &elidedAttrs)
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)
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.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
This is the representation of an operand reference.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
SmallVector< Value, 4 > operands
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addTypes(ArrayRef< Type > newTypes)
SmallVector< Type, 4 > types
Types of the results of this operation.
Region * addRegion()
Create a region that should be attached to the operation.