17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/TypeSwitch.h"
19 #include "llvm/Support/Casting.h"
24 #include "mlir/Dialect/EmitC/IR/EmitCDialect.cpp.inc"
30 void EmitCDialect::initialize() {
33 #include "mlir/Dialect/EmitC/IR/EmitC.cpp.inc"
36 #define GET_TYPEDEF_LIST
37 #include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc"
40 #define GET_ATTRDEF_LIST
41 #include "mlir/Dialect/EmitC/IR/EmitCAttributes.cpp.inc"
50 return emitc::ConstantOp::create(builder, loc, type, value);
56 emitc::YieldOp::create(builder, loc);
60 if (llvm::isa<emitc::OpaqueType>(type))
62 if (
auto ptrType = llvm::dyn_cast<emitc::PointerType>(type))
64 if (
auto arrayType = llvm::dyn_cast<emitc::ArrayType>(type)) {
65 auto elemType = arrayType.getElementType();
66 return !llvm::isa<emitc::ArrayType>(elemType) &&
71 if (llvm::isa<IntegerType>(type))
73 if (llvm::isa<FloatType>(type))
75 if (
auto tensorType = llvm::dyn_cast<TensorType>(type)) {
76 if (!tensorType.hasStaticShape()) {
79 auto elemType = tensorType.getElementType();
80 if (llvm::isa<emitc::ArrayType>(elemType)) {
85 if (
auto tupleType = llvm::dyn_cast<TupleType>(type)) {
86 return llvm::all_of(tupleType.getTypes(), [](
Type type) {
87 return !llvm::isa<emitc::ArrayType>(type) && isSupportedEmitCType(type);
94 if (
auto intType = llvm::dyn_cast<IntegerType>(type)) {
95 switch (intType.getWidth()) {
110 return llvm::isa<IndexType, emitc::OpaqueType>(type) ||
115 if (
auto floatType = llvm::dyn_cast<FloatType>(type)) {
116 switch (floatType.getWidth()) {
118 if (llvm::isa<Float16Type, BFloat16Type>(type))
133 return isa<emitc::SignedSizeTType, emitc::SizeTType, emitc::PtrDiffTType>(
141 assert(op->
getNumResults() == 1 &&
"operation must have 1 result");
143 if (llvm::isa<emitc::OpaqueAttr>(value))
146 if (llvm::isa<StringAttr>(value))
148 <<
"string attributes are not supported, use #emitc.opaque instead";
151 if (
auto lType = dyn_cast<LValueType>(resultType))
152 resultType = lType.getValueType();
153 Type attrType = cast<TypedAttr>(value).getType();
158 if (resultType != attrType)
160 <<
"requires attribute to either be an #emitc.opaque attribute or "
162 << attrType <<
") to match the op's result type (" << resultType
173 template <
class ArgType>
175 StringRef toParse, ArgType fmtArgs,
180 if (fmtArgs.empty()) {
181 items.push_back(toParse);
185 while (!toParse.empty()) {
186 size_t idx = toParse.find(
'{');
187 if (idx == StringRef::npos) {
189 items.push_back(toParse);
194 items.push_back(toParse.take_front(idx));
195 toParse = toParse.drop_front(idx);
198 if (toParse.size() < 2) {
199 return emitError() <<
"expected '}' after unescaped '{' at end of string";
202 char nextChar = toParse[1];
203 if (nextChar ==
'{') {
205 items.push_back(toParse.take_front(1));
206 toParse = toParse.drop_front(2);
209 if (nextChar ==
'}') {
211 toParse = toParse.drop_front(2);
216 return emitError() <<
"expected '}' after unescaped '{'";
228 Type lhsType = getLhs().getType();
229 Type rhsType = getRhs().getType();
231 if (isa<emitc::PointerType>(lhsType) && isa<emitc::PointerType>(rhsType))
232 return emitOpError(
"requires that at most one operand is a pointer");
234 if ((isa<emitc::PointerType>(lhsType) &&
235 !isa<IntegerType, emitc::OpaqueType>(rhsType)) ||
236 (isa<emitc::PointerType>(rhsType) &&
237 !isa<IntegerType, emitc::OpaqueType>(lhsType)))
238 return emitOpError(
"requires that one operand is an integer or of opaque "
239 "type if the other is a pointer");
249 StringRef applicableOperatorStr = getApplicableOperator();
252 if (applicableOperatorStr.empty())
253 return emitOpError(
"applicable operator must not be empty");
256 if (applicableOperatorStr !=
"&" && applicableOperatorStr !=
"*")
257 return emitOpError(
"applicable operator is illegal");
259 Type operandType = getOperand().getType();
260 Type resultType = getResult().getType();
261 if (applicableOperatorStr ==
"&") {
262 if (!llvm::isa<emitc::LValueType>(operandType))
263 return emitOpError(
"operand type must be an lvalue when applying `&`");
264 if (!llvm::isa<emitc::PointerType>(resultType))
265 return emitOpError(
"result type must be a pointer when applying `&`");
267 if (!llvm::isa<emitc::PointerType>(operandType))
268 return emitOpError(
"operand type must be a pointer when applying `*`");
283 if (!variable.getDefiningOp())
284 return emitOpError() <<
"cannot assign to block argument";
286 Type valueType = getValue().getType();
287 Type variableType = variable.getType().getValueType();
288 if (variableType != valueType)
289 return emitOpError() <<
"requires value's type (" << valueType
290 <<
") to match variable's type (" << variableType
291 <<
")\n variable: " << variable
292 <<
"\n value: " << getValue() <<
"\n";
301 Type input = inputs.front(), output = outputs.front();
303 if (
auto arrayType = dyn_cast<emitc::ArrayType>(input)) {
304 if (
auto pointerType = dyn_cast<emitc::PointerType>(output)) {
305 return (arrayType.getElementType() == pointerType.getPointee()) &&
306 arrayType.getShape().size() == 1 && arrayType.getShape()[0] >= 1;
324 if (getCallee().empty())
325 return emitOpError(
"callee must not be empty");
327 if (std::optional<ArrayAttr> argsAttr = getArgs()) {
329 auto intAttr = llvm::dyn_cast<IntegerAttr>(arg);
330 if (intAttr && llvm::isa<IndexType>(intAttr.getType())) {
331 int64_t index = intAttr.getInt();
334 if ((index < 0) || (index >=
static_cast<int64_t
>(getNumOperands())))
335 return emitOpError(
"index argument is out of range");
338 }
else if (llvm::isa<ArrayAttr>(
341 return emitOpError(
"array argument has no type");
346 if (std::optional<ArrayAttr> templateArgsAttr = getTemplateArgs()) {
347 for (
Attribute tArg : *templateArgsAttr) {
348 if (!llvm::isa<TypeAttr, IntegerAttr, FloatAttr, emitc::OpaqueAttr>(tArg))
349 return emitOpError(
"template argument has invalid type");
353 if (llvm::any_of(getResultTypes(), llvm::IsaPred<ArrayType>)) {
354 return emitOpError() <<
"cannot return array type";
368 if (
auto opaqueValue = llvm::dyn_cast<emitc::OpaqueAttr>(value)) {
369 if (opaqueValue.getValue().empty())
370 return emitOpError() <<
"value must not be empty";
375 OpFoldResult emitc::ConstantOp::fold(FoldAdaptor adaptor) {
return getValue(); }
382 auto yieldOp = cast<YieldOp>(getBody()->getTerminator());
383 Value yieldedValue = yieldOp.getResult();
388 Type resultType = getResult().getType();
389 Region ®ion = getRegion();
394 return emitOpError(
"must yield a value at termination");
397 Value yieldResult = yield.getResult();
400 return emitOpError(
"must yield a value at termination");
405 return emitOpError(
"yielded value has no defining op");
408 return emitOpError(
"yielded value not defined within expression");
412 if (resultType != yieldType)
413 return emitOpError(
"requires yielded type to match return type");
416 if (!isa<emitc::CExpressionInterface>(op))
417 return emitOpError(
"contains an unsupported operation");
418 if (op.getNumResults() != 1)
419 return emitOpError(
"requires exactly one result for each operation");
420 if (!op.getResult(0).hasOneUse())
421 return emitOpError(
"requires exactly one use for each operation");
432 Value ub,
Value step, BodyBuilderFn bodyBuilder) {
442 ForOp::ensureTerminator(*bodyRegion, builder, result.
location);
469 regionArgs.push_back(inductionVariable);
478 regionArgs.front().type = type;
489 ForOp::ensureTerminator(*body, builder, result.
location);
499 p <<
" " << getInductionVar() <<
" = " <<
getLowerBound() <<
" to "
504 p <<
" : " << t <<
' ';
511 LogicalResult ForOp::verifyRegions() {
516 "expected induction variable to be same type as bounds and step");
529 return emitOpError(
"requires a 'callee' symbol reference attribute");
532 return emitOpError() <<
"'" << fnAttr.getValue()
533 <<
"' does not reference a valid function";
536 auto fnType = fn.getFunctionType();
537 if (fnType.getNumInputs() != getNumOperands())
538 return emitOpError(
"incorrect number of operands for callee");
540 for (
unsigned i = 0, e = fnType.getNumInputs(); i != e; ++i)
541 if (getOperand(i).
getType() != fnType.getInput(i))
542 return emitOpError(
"operand type mismatch: expected operand type ")
543 << fnType.getInput(i) <<
", but provided "
544 << getOperand(i).getType() <<
" for operand number " << i;
546 if (fnType.getNumResults() != getNumResults())
547 return emitOpError(
"incorrect number of results for callee");
549 for (
unsigned i = 0, e = fnType.getNumResults(); i != e; ++i)
550 if (getResult(i).
getType() != fnType.getResult(i)) {
551 auto diag = emitOpError(
"result type mismatch at index ") << i;
552 diag.attachNote() <<
" op result types: " << getResultTypes();
553 diag.attachNote() <<
"function result types: " << fnType.getResults();
560 FunctionType CallOp::getCalleeType() {
571 auto fnAttr = getSymNameAttr();
573 return emitOpError(
"requires a 'sym_name' symbol reference attribute");
576 return emitOpError() <<
"'" << fnAttr.getValue()
577 <<
"' does not reference a valid function";
591 state.addAttribute(getFunctionTypeAttrName(state.name),
TypeAttr::get(type));
592 state.attributes.append(attrs.begin(), attrs.end());
595 if (argAttrs.empty())
597 assert(type.getNumInputs() == argAttrs.size());
599 builder, state, argAttrs, {},
600 getArgAttrsAttrName(state.name), getResAttrsAttrName(state.name));
610 parser, result,
false,
611 getFunctionTypeAttrName(result.
name), buildFuncType,
612 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
617 p, *
this,
false, getFunctionTypeAttrName(),
618 getArgAttrsAttrName(), getResAttrsAttrName());
622 if (llvm::any_of(getArgumentTypes(), llvm::IsaPred<LValueType>)) {
623 return emitOpError(
"cannot have lvalue type as argument");
626 if (getNumResults() > 1)
627 return emitOpError(
"requires zero or exactly one result, but has ")
630 if (getNumResults() == 1 && isa<ArrayType>(getResultTypes()[0]))
631 return emitOpError(
"cannot return array type");
641 auto function = cast<FuncOp>((*this)->getParentOp());
644 if (getNumOperands() !=
function.getNumResults())
645 return emitOpError(
"has ")
646 << getNumOperands() <<
" operands, but enclosing function (@"
647 <<
function.getName() <<
") returns " <<
function.getNumResults();
649 if (
function.getNumResults() == 1)
650 if (getOperand().
getType() !=
function.getResultTypes()[0])
651 return emitError() <<
"type of the return operand ("
652 << getOperand().getType()
653 <<
") doesn't match function result type ("
654 <<
function.getResultTypes()[0] <<
")"
655 <<
" in function @" <<
function.getName();
664 bool addThenBlock,
bool addElseBlock) {
665 assert((!addElseBlock || addThenBlock) &&
666 "must not create else block w/o then block");
680 bool withElseRegion) {
690 if (withElseRegion) {
698 assert(thenBuilder &&
"the builder callback for 'then' must be present");
705 thenBuilder(builder, result.
location);
711 elseBuilder(builder, result.
location);
746 bool printBlockTerminators =
false;
748 p <<
" " << getCondition();
752 printBlockTerminators);
755 Region &elseRegion = getElseRegion();
756 if (!elseRegion.
empty()) {
760 printBlockTerminators);
782 Region *elseRegion = &this->getElseRegion();
783 if (elseRegion->
empty())
791 FoldAdaptor adaptor(operands, *
this);
792 auto boolAttr = dyn_cast_or_null<BoolAttr>(adaptor.getCondition());
793 if (!boolAttr || boolAttr.getValue())
794 regions.emplace_back(&getThenRegion());
797 if (!boolAttr || !boolAttr.getValue()) {
798 if (!getElseRegion().empty())
799 regions.emplace_back(&getElseRegion());
801 regions.emplace_back();
805 void IfOp::getRegionInvocationBounds(
808 if (
auto cond = llvm::dyn_cast_or_null<BoolAttr>(operands[0])) {
811 invocationBounds.emplace_back(0, cond.getValue() ? 1 : 0);
812 invocationBounds.emplace_back(0, cond.getValue() ? 0 : 1);
815 invocationBounds.assign(2, {0, 1});
824 bool standardInclude = getIsStandardInclude();
829 p <<
"\"" << getInclude() <<
"\"";
845 <<
"expected trailing '>' for standard include";
860 if (getValue().empty())
861 return emitOpError() <<
"value must not be empty";
869 Type lhsType = getLhs().getType();
870 Type rhsType = getRhs().getType();
871 Type resultType = getResult().getType();
873 if (isa<emitc::PointerType>(rhsType) && !isa<emitc::PointerType>(lhsType))
874 return emitOpError(
"rhs can only be a pointer if lhs is a pointer");
876 if (isa<emitc::PointerType>(lhsType) &&
877 !isa<IntegerType, emitc::OpaqueType, emitc::PointerType>(rhsType))
878 return emitOpError(
"requires that rhs is an integer, pointer or of opaque "
879 "type if lhs is a pointer");
881 if (isa<emitc::PointerType>(lhsType) && isa<emitc::PointerType>(rhsType) &&
882 !isa<IntegerType, emitc::PtrDiffTType, emitc::OpaqueType>(resultType))
883 return emitOpError(
"requires that the result is an integer, ptrdiff_t or "
884 "of opaque type if lhs and rhs are pointers");
901 Value result = getResult();
905 return emitOpError() <<
"yields a value not returned by parent";
908 return emitOpError() <<
"does not yield a value to be returned by parent";
919 if (
auto arrayType = llvm::dyn_cast<emitc::ArrayType>(getValue().
getType())) {
921 if (
getIndices().size() != (
size_t)arrayType.getRank()) {
922 return emitOpError() <<
"on array operand requires number of indices ("
924 <<
") to match the rank of the array type ("
925 << arrayType.getRank() <<
")";
928 for (
unsigned i = 0, e =
getIndices().size(); i != e; ++i) {
931 return emitOpError() <<
"on array operand requires index operand " << i
932 <<
" to be integer-like, but got " << type;
936 Type elementType = arrayType.getElementType();
938 if (elementType != resultType) {
939 return emitOpError() <<
"on array operand requires element type ("
940 << elementType <<
") and result type (" << resultType
947 if (
auto pointerType =
948 llvm::dyn_cast<emitc::PointerType>(getValue().
getType())) {
952 <<
"on pointer operand requires one index operand, but got "
958 return emitOpError() <<
"on pointer operand requires index operand to be "
959 "integer-like, but got "
963 Type pointeeType = pointerType.getPointee();
965 if (pointeeType != resultType) {
966 return emitOpError() <<
"on pointer operand requires pointee type ("
967 << pointeeType <<
") and result type (" << resultType
984 return this->emitOpError();
986 FailureOr<SmallVector<ReplacementItem>> fmt =
991 size_t numPlaceholders = llvm::count_if(*fmt, [](
ReplacementItem &item) {
992 return std::holds_alternative<Placeholder>(item);
995 if (numPlaceholders != getFmtArgs().size()) {
997 <<
"requires operands for each placeholder in the format string";
1011 #include "mlir/Dialect/EmitC/IR/EmitCEnums.cpp.inc"
1017 #define GET_ATTRDEF_CLASSES
1018 #include "mlir/Dialect/EmitC/IR/EmitCAttributes.cpp.inc"
1024 #define GET_TYPEDEF_CLASSES
1025 #include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc"
1046 if (!isValidElementType(elementType))
1047 return parser.
emitError(typeLoc,
"invalid array element type '")
1048 << elementType <<
"'",
1052 return parser.
getChecked<ArrayType>(dimensions, elementType);
1058 printer << dim <<
'x';
1068 return emitError() <<
"shape must not be empty";
1070 for (int64_t dim : shape) {
1072 return emitError() <<
"dimensions must have non-negative size";
1076 return emitError() <<
"element type must not be none";
1078 if (!isValidElementType(elementType))
1079 return emitError() <<
"invalid array element type";
1086 Type elementType)
const {
1103 <<
"!emitc.lvalue must wrap supported emitc type, but got " << value;
1105 if (llvm::isa<emitc::ArrayType>(value))
1106 return emitError() <<
"!emitc.lvalue cannot wrap !emitc.array type";
1117 llvm::StringRef value) {
1118 if (value.empty()) {
1119 return emitError() <<
"expected non empty string in !emitc.opaque type";
1121 if (value.back() ==
'*') {
1122 return emitError() <<
"pointer not allowed as outer type with "
1123 "!emitc.opaque, use !emitc.ptr instead";
1134 if (llvm::isa<emitc::LValueType>(value))
1135 return emitError() <<
"pointers to lvalues are not allowed";
1154 if (
auto array = llvm::dyn_cast<ArrayType>(type))
1174 if (!llvm::isa<ElementsAttr, IntegerAttr, FloatAttr, emitc::OpaqueAttr>(
1177 <<
"initial value should be a integer, float, elements or opaque "
1184 return emitOpError(
"expected valid emitc type");
1186 if (getInitialValue().has_value()) {
1187 Attribute initValue = getInitialValue().value();
1190 if (
auto elementsAttr = llvm::dyn_cast<ElementsAttr>(initValue)) {
1191 auto arrayType = llvm::dyn_cast<ArrayType>(
getType());
1193 return emitOpError(
"expected array type, but got ") <<
getType();
1195 Type initType = elementsAttr.getType();
1197 if (initType != tensorType) {
1198 return emitOpError(
"initial value expected to be of type ")
1199 <<
getType() <<
", but was of type " << initType;
1201 }
else if (
auto intAttr = dyn_cast<IntegerAttr>(initValue)) {
1202 if (intAttr.getType() !=
getType()) {
1203 return emitOpError(
"initial value expected to be of type ")
1204 <<
getType() <<
", but was of type " << intAttr.getType();
1206 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(initValue)) {
1207 if (floatAttr.getType() !=
getType()) {
1208 return emitOpError(
"initial value expected to be of type ")
1209 <<
getType() <<
", but was of type " << floatAttr.getType();
1211 }
else if (!isa<emitc::OpaqueAttr>(initValue)) {
1212 return emitOpError(
"initial value should be a integer, float, elements "
1213 "or opaque attribute, but got ")
1217 if (getStaticSpecifier() && getExternSpecifier()) {
1218 return emitOpError(
"cannot have both static and extern specifiers");
1233 return emitOpError(
"'")
1234 << getName() <<
"' does not reference a valid emitc.global";
1236 Type resultType = getResult().getType();
1237 Type globalType = global.getType();
1240 if (llvm::isa<ArrayType>(globalType)) {
1241 if (globalType != resultType)
1242 return emitOpError(
"on array type expects result type ")
1243 << resultType <<
" to match type " << globalType
1244 <<
" of the global @" << getName();
1249 auto lvalueType = dyn_cast<LValueType>(resultType);
1250 if (!lvalueType || lvalueType.getValueType() != globalType)
1251 return emitOpError(
"on non-array type expects result inner type ")
1252 << lvalueType.getValueType() <<
" to match type " << globalType
1253 <<
" of the global @" << getName();
1268 Region ®ion = *caseRegions.emplace_back(std::make_unique<Region>());
1272 caseValues.push_back(value);
1281 for (
auto [value, region] : llvm::zip(cases.
asArrayRef(), caseRegions)) {
1283 p <<
"case " << value <<
' ';
1289 const Twine &name) {
1290 auto yield = dyn_cast<emitc::YieldOp>(region.
front().
back());
1292 return op.emitOpError(
"expected region to end with emitc.yield, but got ")
1295 if (yield.getNumOperands() != 0) {
1296 return (op.emitOpError(
"expected each region to return ")
1297 <<
"0 values, but " << name <<
" returns "
1298 << yield.getNumOperands())
1299 .attachNote(yield.getLoc())
1300 <<
"see yield operation here";
1308 return emitOpError(
"unsupported type ") << getArg().getType();
1310 if (getCases().size() != getCaseRegions().size()) {
1311 return emitOpError(
"has ")
1312 << getCaseRegions().size() <<
" case regions but "
1313 << getCases().size() <<
" case values";
1317 for (int64_t value : getCases())
1318 if (!valueSet.insert(value).second)
1319 return emitOpError(
"has duplicate case value: ") << value;
1321 if (failed(
verifyRegion(*
this, getDefaultRegion(),
"default region")))
1325 if (failed(
verifyRegion(*
this, caseRegion,
"case region #" + Twine(idx))))
1331 unsigned emitc::SwitchOp::getNumCases() {
return getCases().size(); }
1333 Block &emitc::SwitchOp::getDefaultBlock() {
return getDefaultRegion().
front(); }
1335 Block &emitc::SwitchOp::getCaseBlock(
unsigned idx) {
1336 assert(idx < getNumCases() &&
"case index out-of-bounds");
1337 return getCaseRegions()[idx].front();
1340 void SwitchOp::getSuccessorRegions(
1342 llvm::append_range(successors, getRegions());
1345 void SwitchOp::getEntrySuccessorRegions(
1348 FoldAdaptor adaptor(operands, *
this);
1351 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
1353 llvm::append_range(successors, getRegions());
1359 for (
auto [caseValue, caseRegion] : llvm::zip(getCases(), getCaseRegions())) {
1360 if (caseValue == arg.getInt()) {
1361 successors.emplace_back(&caseRegion);
1365 successors.emplace_back(&getDefaultRegion());
1368 void SwitchOp::getRegionInvocationBounds(
1370 auto operandValue = llvm::dyn_cast_or_null<IntegerAttr>(operands.front());
1371 if (!operandValue) {
1377 unsigned liveIndex = getNumRegions() - 1;
1378 const auto *iteratorToInt = llvm::find(getCases(), operandValue.getInt());
1380 liveIndex = iteratorToInt != getCases().end()
1381 ? std::distance(getCases().begin(), iteratorToInt)
1384 for (
unsigned regIndex = 0, regNum = getNumRegions(); regIndex < regNum;
1386 bounds.emplace_back(0, regIndex == liveIndex);
1393 state.addRegion()->emplaceBlock();
1394 state.attributes.push_back(
1412 if (
auto array = llvm::dyn_cast<ArrayType>(type))
1432 if (!llvm::isa<ElementsAttr, IntegerAttr, FloatAttr, emitc::OpaqueAttr>(
1435 <<
"initial value should be a integer, float, elements or opaque "
1442 return emitOpError(
"expected valid emitc type");
1445 if (!parentOp || !isa<emitc::ClassOp>(parentOp))
1446 return emitOpError(
"field must be nested within an emitc.class operation");
1448 StringAttr symName = getSymNameAttr();
1449 if (!symName || symName.getValue().empty())
1450 return emitOpError(
"field must have a non-empty symbol name");
1463 return emitOpError(
"field '")
1464 << fieldNameAttr <<
"' not found in the class";
1466 Type getFieldResultType = getResult().getType();
1467 Type fieldType = fieldOp.getType();
1469 if (fieldType != getFieldResultType)
1470 return emitOpError(
"result type ")
1471 << getFieldResultType <<
" does not match field '" << fieldNameAttr
1472 <<
"' type " << fieldType;
1481 #include "mlir/Dialect/EmitC/IR/EmitCInterfaces.cpp.inc"
1483 #define GET_OP_CLASSES
1484 #include "mlir/Dialect/EmitC/IR/EmitC.cpp.inc"
static std::optional< int64_t > getUpperBound(Value iv)
Gets the constant upper bound on an affine.for iv.
static std::optional< int64_t > getLowerBound(Value iv)
Gets the constant lower bound on an iv.
static LogicalResult verifyInitializationAttribute(Operation *op, Attribute value)
Check that the type of the initial value is compatible with the operations result type.
static LogicalResult verifyRegion(emitc::SwitchOp op, Region ®ion, const Twine &name)
static ParseResult parseEmitCGlobalOpTypeAndInitialValue(OpAsmParser &parser, TypeAttr &typeAttr, Attribute &initialValue)
static ParseResult parseSwitchCases(OpAsmParser &parser, DenseI64ArrayAttr &cases, SmallVectorImpl< std::unique_ptr< Region >> &caseRegions)
Parse the case regions and values.
static Type getInitializerTypeForField(Type type)
FailureOr< SmallVector< ReplacementItem > > parseFormatString(StringRef toParse, ArgType fmtArgs, llvm::function_ref< mlir::InFlightDiagnostic()> emitError={})
Parse a format string and return a list of its parts.
static ParseResult parseEmitCFieldOpTypeAndInitialValue(OpAsmParser &parser, TypeAttr &typeAttr, Attribute &initialValue)
static void printEmitCGlobalOpTypeAndInitialValue(OpAsmPrinter &p, GlobalOp op, TypeAttr type, Attribute initialValue)
static void printEmitCFieldOpTypeAndInitialValue(OpAsmPrinter &p, FieldOp op, TypeAttr type, Attribute initialValue)
static void printSwitchCases(OpAsmPrinter &p, Operation *op, DenseI64ArrayAttr cases, RegionRange caseRegions)
Print the case regions and values.
static Type getInitializerTypeForGlobal(Type type)
static Operation * materializeConstant(Dialect *dialect, OpBuilder &builder, Attribute value, Type type, Location loc)
A utility function used to materialize a constant for a given attribute and type.
static MLIRContext * getContext(OpFoldResult val)
static Type getElementType(Type type)
Determine the element type of type.
static std::string diag(const llvm::Value &value)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
static ArrayRef< int64_t > getShape(Type type)
Returns the shape of the given type.
This base class exposes generic asm parser hooks, usable across the various derived parsers.
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 parseOptionalEqual()=0
Parse a = token if present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
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 parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseLess()=0
Parse a '<' token.
virtual ParseResult parseDimensionList(SmallVectorImpl< int64_t > &dimensions, bool allowDynamic=true, bool withTrailingX=true)=0
Parse a dimension list of a tensor or memref type.
virtual ParseResult parseOptionalGreater()=0
Parse a '>' token if present.
virtual ParseResult parseEqual()=0
Parse a = token.
virtual OptionalParseResult parseOptionalAttribute(Attribute &result, Type type={})=0
Parse an arbitrary optional attribute of a given type and return it in result.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
auto getChecked(SMLoc loc, ParamsT &&...params)
Invoke the getChecked method of the given Attribute or Type class, using the provided location to emi...
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalLess()=0
Parse a '<' token if present.
virtual ParseResult parseGreater()=0
Parse a '>' token.
virtual ParseResult parseType(Type &result)=0
Parse 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.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual void printType(Type type)
Attributes are known-constant values of operations.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
bool mightHaveTerminator()
Check whether this block might have a terminator.
iterator_range< iterator > without_terminator()
Return an iterator range over the operation within this block excluding the terminator operation at t...
This class is a general helper class for creating context-global objects like types,...
DenseI64ArrayAttr getDenseI64ArrayAttr(ArrayRef< int64_t > values)
FunctionType getFunctionType(TypeRange inputs, TypeRange results)
IntegerType getIntegerType(unsigned width)
StringAttr getStringAttr(const Twine &bytes)
NamedAttribute getNamedAttr(StringRef name, Attribute val)
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 represents upper and lower bounds on the number of times a region of a RegionBranchOpInter...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
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 ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printNewline()=0
Print a newline and indent the printer to the start of the current operation.
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 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 setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
This class represents a single result from folding an operation.
type_range getType() const
Operation is the basic unit of execution within MLIR.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
OperationName getName()
The name of an operation is the key identifier for it.
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 represents a point being branched from in the methods of the RegionBranchOpInterface.
bool isParent() const
Returns true if branching from the parent op.
This class provides an abstraction over the different types of ranges over Regions.
This class represents a successor of a region.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
This class represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Base class for DenseArrayAttr that is instantiated and specialized for each supported element type be...
ArrayRef< T > asArrayRef() const
A named class for passing around the variadic flag.
mlir::Value getVar(mlir::Operation *accDataClauseOp)
Used to obtain the var from a data clause operation.
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,...
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
std::variant< StringRef, Placeholder > ReplacementItem
void buildTerminatedBody(OpBuilder &builder, Location loc)
Default callback for builders of ops carrying a region.
bool isSupportedFloatType(mlir::Type type)
Determines whether type is a valid floating-point type in EmitC.
bool isSupportedEmitCType(mlir::Type type)
Determines whether type is valid in EmitC.
bool isPointerWideType(mlir::Type type)
Determines whether type is a emitc.size_t/ssize_t type.
bool isIntegerIndexOrOpaqueType(Type type)
Determines whether type is integer like, i.e.
bool isSupportedIntegerType(mlir::Type type)
Determines whether type is a valid integer type in EmitC.
void printFunctionOp(OpAsmPrinter &p, FunctionOpInterface op, bool isVariadic, StringRef typeAttrName, StringAttr argAttrsName, StringAttr resAttrsName)
Printer implementation for function-like operations.
ParseResult parseFunctionOp(OpAsmParser &parser, OperationState &result, bool allowVariadic, StringAttr typeAttrName, FuncTypeBuilder funcTypeBuilder, StringAttr argAttrsName, StringAttr resAttrsName)
Parser implementation for function-like operations.
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)
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
std::conditional_t< std::is_same_v< Ty, mlir::Type >, mlir::Value, detail::TypedValue< Ty > > TypedValue
If Ty is mlir::Type this will select Value instead of having a wrapper around it.
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,...
UnresolvedOperand ssaName
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 addOperands(ValueRange newOperands)
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
SmallVector< std::unique_ptr< Region >, 1 > regions
Regions that the op will hold.
Region * addRegion()
Create a region that should be attached to the operation.