18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/TypeSwitch.h"
21 #include "llvm/Support/Casting.h"
26 #include "mlir/Dialect/EmitC/IR/EmitCDialect.cpp.inc"
32 void EmitCDialect::initialize() {
35 #include "mlir/Dialect/EmitC/IR/EmitC.cpp.inc"
38 #define GET_TYPEDEF_LIST
39 #include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc"
42 #define GET_ATTRDEF_LIST
43 #include "mlir/Dialect/EmitC/IR/EmitCAttributes.cpp.inc"
52 return builder.
create<emitc::ConstantOp>(loc, type, value);
58 builder.
create<emitc::YieldOp>(loc);
62 if (llvm::isa<emitc::OpaqueType>(type))
64 if (
auto ptrType = llvm::dyn_cast<emitc::PointerType>(type))
66 if (
auto arrayType = llvm::dyn_cast<emitc::ArrayType>(type)) {
67 auto elemType = arrayType.getElementType();
68 return !llvm::isa<emitc::ArrayType>(elemType) &&
73 if (llvm::isa<IntegerType>(type))
75 if (llvm::isa<FloatType>(type))
77 if (
auto tensorType = llvm::dyn_cast<TensorType>(type)) {
78 if (!tensorType.hasStaticShape()) {
81 auto elemType = tensorType.getElementType();
82 if (llvm::isa<emitc::ArrayType>(elemType)) {
87 if (
auto tupleType = llvm::dyn_cast<TupleType>(type)) {
88 return llvm::all_of(tupleType.getTypes(), [](
Type type) {
89 return !llvm::isa<emitc::ArrayType>(type) && isSupportedEmitCType(type);
96 if (
auto intType = llvm::dyn_cast<IntegerType>(type)) {
97 switch (intType.getWidth()) {
112 return llvm::isa<IndexType, emitc::OpaqueType>(type) ||
117 if (
auto floatType = llvm::dyn_cast<FloatType>(type)) {
118 switch (floatType.getWidth()) {
120 if (llvm::isa<Float16Type, BFloat16Type>(type))
135 return isa<emitc::SignedSizeTType, emitc::SizeTType, emitc::PtrDiffTType>(
143 assert(op->
getNumResults() == 1 &&
"operation must have 1 result");
145 if (llvm::isa<emitc::OpaqueAttr>(value))
148 if (llvm::isa<StringAttr>(value))
150 <<
"string attributes are not supported, use #emitc.opaque instead";
153 if (
auto lType = dyn_cast<LValueType>(resultType))
154 resultType = lType.getValueType();
155 Type attrType = cast<TypedAttr>(value).getType();
160 if (resultType != attrType)
162 <<
"requires attribute to either be an #emitc.opaque attribute or "
164 << attrType <<
") to match the op's result type (" << resultType
175 Type lhsType = getLhs().getType();
176 Type rhsType = getRhs().getType();
178 if (isa<emitc::PointerType>(lhsType) && isa<emitc::PointerType>(rhsType))
179 return emitOpError(
"requires that at most one operand is a pointer");
181 if ((isa<emitc::PointerType>(lhsType) &&
182 !isa<IntegerType, emitc::OpaqueType>(rhsType)) ||
183 (isa<emitc::PointerType>(rhsType) &&
184 !isa<IntegerType, emitc::OpaqueType>(lhsType)))
185 return emitOpError(
"requires that one operand is an integer or of opaque "
186 "type if the other is a pointer");
196 StringRef applicableOperatorStr = getApplicableOperator();
199 if (applicableOperatorStr.empty())
200 return emitOpError(
"applicable operator must not be empty");
203 if (applicableOperatorStr !=
"&" && applicableOperatorStr !=
"*")
204 return emitOpError(
"applicable operator is illegal");
206 Type operandType = getOperand().getType();
207 Type resultType = getResult().getType();
208 if (applicableOperatorStr ==
"&") {
209 if (!llvm::isa<emitc::LValueType>(operandType))
210 return emitOpError(
"operand type must be an lvalue when applying `&`");
211 if (!llvm::isa<emitc::PointerType>(resultType))
212 return emitOpError(
"result type must be a pointer when applying `&`");
214 if (!llvm::isa<emitc::PointerType>(operandType))
215 return emitOpError(
"operand type must be a pointer when applying `*`");
230 if (!variable.getDefiningOp())
231 return emitOpError() <<
"cannot assign to block argument";
233 Type valueType = getValue().getType();
234 Type variableType = variable.getType().getValueType();
235 if (variableType != valueType)
236 return emitOpError() <<
"requires value's type (" << valueType
237 <<
") to match variable's type (" << variableType
238 <<
")\n variable: " << variable
239 <<
"\n value: " << getValue() <<
"\n";
248 Type input = inputs.front(), output = outputs.front();
263 if (getCallee().empty())
264 return emitOpError(
"callee must not be empty");
266 if (std::optional<ArrayAttr> argsAttr = getArgs()) {
268 auto intAttr = llvm::dyn_cast<IntegerAttr>(arg);
269 if (intAttr && llvm::isa<IndexType>(intAttr.getType())) {
270 int64_t index = intAttr.getInt();
273 if ((index < 0) || (index >=
static_cast<int64_t
>(getNumOperands())))
274 return emitOpError(
"index argument is out of range");
277 }
else if (llvm::isa<ArrayAttr>(
280 return emitOpError(
"array argument has no type");
285 if (std::optional<ArrayAttr> templateArgsAttr = getTemplateArgs()) {
286 for (
Attribute tArg : *templateArgsAttr) {
287 if (!llvm::isa<TypeAttr, IntegerAttr, FloatAttr, emitc::OpaqueAttr>(tArg))
288 return emitOpError(
"template argument has invalid type");
292 if (llvm::any_of(getResultTypes(), llvm::IsaPred<ArrayType>)) {
293 return emitOpError() <<
"cannot return array type";
307 if (
auto opaqueValue = llvm::dyn_cast<emitc::OpaqueAttr>(value)) {
308 if (opaqueValue.getValue().empty())
309 return emitOpError() <<
"value must not be empty";
314 OpFoldResult emitc::ConstantOp::fold(FoldAdaptor adaptor) {
return getValue(); }
321 auto yieldOp = cast<YieldOp>(getBody()->getTerminator());
322 Value yieldedValue = yieldOp.getResult();
324 assert(rootOp &&
"Yielded value not defined within expression");
329 Type resultType = getResult().getType();
330 Region ®ion = getRegion();
335 return emitOpError(
"must yield a value at termination");
338 Value yieldResult = yield.getResult();
341 return emitOpError(
"must yield a value at termination");
345 if (resultType != yieldType)
346 return emitOpError(
"requires yielded type to match return type");
350 return emitOpError(
"contains an unsupported operation");
351 if (op.getNumResults() != 1)
352 return emitOpError(
"requires exactly one result for each operation");
353 if (!op.getResult(0).hasOneUse())
354 return emitOpError(
"requires exactly one use for each operation");
365 Value ub,
Value step, BodyBuilderFn bodyBuilder) {
375 ForOp::ensureTerminator(*bodyRegion, builder, result.
location);
403 regionArgs.push_back(inductionVariable);
412 regionArgs.front().type = type;
423 ForOp::ensureTerminator(*body, builder, result.
location);
433 p <<
" " << getInductionVar() <<
" = " <<
getLowerBound() <<
" to "
438 p <<
" : " << t <<
' ';
445 LogicalResult ForOp::verifyRegions() {
450 "expected induction variable to be same type as bounds and step");
463 return emitOpError(
"requires a 'callee' symbol reference attribute");
466 return emitOpError() <<
"'" << fnAttr.getValue()
467 <<
"' does not reference a valid function";
470 auto fnType = fn.getFunctionType();
471 if (fnType.getNumInputs() != getNumOperands())
472 return emitOpError(
"incorrect number of operands for callee");
474 for (
unsigned i = 0, e = fnType.getNumInputs(); i != e; ++i)
475 if (getOperand(i).
getType() != fnType.getInput(i))
476 return emitOpError(
"operand type mismatch: expected operand type ")
477 << fnType.getInput(i) <<
", but provided "
478 << getOperand(i).getType() <<
" for operand number " << i;
480 if (fnType.getNumResults() != getNumResults())
481 return emitOpError(
"incorrect number of results for callee");
483 for (
unsigned i = 0, e = fnType.getNumResults(); i != e; ++i)
484 if (getResult(i).
getType() != fnType.getResult(i)) {
485 auto diag = emitOpError(
"result type mismatch at index ") << i;
486 diag.attachNote() <<
" op result types: " << getResultTypes();
487 diag.attachNote() <<
"function result types: " << fnType.getResults();
494 FunctionType CallOp::getCalleeType() {
505 auto fnAttr = getSymNameAttr();
507 return emitOpError(
"requires a 'sym_name' symbol reference attribute");
510 return emitOpError() <<
"'" << fnAttr.getValue()
511 <<
"' does not reference a valid function";
525 state.addAttribute(getFunctionTypeAttrName(state.name),
TypeAttr::get(type));
526 state.attributes.append(attrs.begin(), attrs.end());
529 if (argAttrs.empty())
531 assert(type.getNumInputs() == argAttrs.size());
533 builder, state, argAttrs, std::nullopt,
534 getArgAttrsAttrName(state.name), getResAttrsAttrName(state.name));
544 parser, result,
false,
545 getFunctionTypeAttrName(result.
name), buildFuncType,
546 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
551 p, *
this,
false, getFunctionTypeAttrName(),
552 getArgAttrsAttrName(), getResAttrsAttrName());
556 if (llvm::any_of(getArgumentTypes(), llvm::IsaPred<LValueType>)) {
557 return emitOpError(
"cannot have lvalue type as argument");
560 if (getNumResults() > 1)
561 return emitOpError(
"requires zero or exactly one result, but has ")
564 if (getNumResults() == 1 && isa<ArrayType>(getResultTypes()[0]))
565 return emitOpError(
"cannot return array type");
575 auto function = cast<FuncOp>((*this)->getParentOp());
578 if (getNumOperands() !=
function.getNumResults())
579 return emitOpError(
"has ")
580 << getNumOperands() <<
" operands, but enclosing function (@"
581 <<
function.getName() <<
") returns " <<
function.getNumResults();
583 if (
function.getNumResults() == 1)
584 if (getOperand().
getType() !=
function.getResultTypes()[0])
585 return emitError() <<
"type of the return operand ("
586 << getOperand().getType()
587 <<
") doesn't match function result type ("
588 <<
function.getResultTypes()[0] <<
")"
589 <<
" in function @" <<
function.getName();
598 bool addThenBlock,
bool addElseBlock) {
599 assert((!addElseBlock || addThenBlock) &&
600 "must not create else block w/o then block");
614 bool withElseRegion) {
624 if (withElseRegion) {
632 assert(thenBuilder &&
"the builder callback for 'then' must be present");
639 thenBuilder(builder, result.
location);
645 elseBuilder(builder, result.
location);
680 bool printBlockTerminators =
false;
682 p <<
" " << getCondition();
686 printBlockTerminators);
689 Region &elseRegion = getElseRegion();
690 if (!elseRegion.
empty()) {
694 printBlockTerminators);
716 Region *elseRegion = &this->getElseRegion();
717 if (elseRegion->
empty())
725 FoldAdaptor adaptor(operands, *
this);
726 auto boolAttr = dyn_cast_or_null<BoolAttr>(adaptor.getCondition());
727 if (!boolAttr || boolAttr.getValue())
728 regions.emplace_back(&getThenRegion());
731 if (!boolAttr || !boolAttr.getValue()) {
732 if (!getElseRegion().empty())
733 regions.emplace_back(&getElseRegion());
735 regions.emplace_back();
739 void IfOp::getRegionInvocationBounds(
742 if (
auto cond = llvm::dyn_cast_or_null<BoolAttr>(operands[0])) {
745 invocationBounds.emplace_back(0, cond.getValue() ? 1 : 0);
746 invocationBounds.emplace_back(0, cond.getValue() ? 0 : 1);
749 invocationBounds.assign(2, {0, 1});
758 bool standardInclude = getIsStandardInclude();
763 p <<
"\"" << getInclude() <<
"\"";
779 <<
"expected trailing '>' for standard include";
794 if (getValue().empty())
795 return emitOpError() <<
"value must not be empty";
803 Type lhsType = getLhs().getType();
804 Type rhsType = getRhs().getType();
805 Type resultType = getResult().getType();
807 if (isa<emitc::PointerType>(rhsType) && !isa<emitc::PointerType>(lhsType))
808 return emitOpError(
"rhs can only be a pointer if lhs is a pointer");
810 if (isa<emitc::PointerType>(lhsType) &&
811 !isa<IntegerType, emitc::OpaqueType, emitc::PointerType>(rhsType))
812 return emitOpError(
"requires that rhs is an integer, pointer or of opaque "
813 "type if lhs is a pointer");
815 if (isa<emitc::PointerType>(lhsType) && isa<emitc::PointerType>(rhsType) &&
816 !isa<IntegerType, emitc::PtrDiffTType, emitc::OpaqueType>(resultType))
817 return emitOpError(
"requires that the result is an integer, ptrdiff_t or "
818 "of opaque type if lhs and rhs are pointers");
835 Value result = getResult();
839 return emitOpError() <<
"yields a value not returned by parent";
842 return emitOpError() <<
"does not yield a value to be returned by parent";
853 if (
auto arrayType = llvm::dyn_cast<emitc::ArrayType>(getValue().
getType())) {
855 if (
getIndices().size() != (
size_t)arrayType.getRank()) {
856 return emitOpError() <<
"on array operand requires number of indices ("
858 <<
") to match the rank of the array type ("
859 << arrayType.getRank() <<
")";
862 for (
unsigned i = 0, e =
getIndices().size(); i != e; ++i) {
865 return emitOpError() <<
"on array operand requires index operand " << i
866 <<
" to be integer-like, but got " << type;
870 Type elementType = arrayType.getElementType();
872 if (elementType != resultType) {
873 return emitOpError() <<
"on array operand requires element type ("
874 << elementType <<
") and result type (" << resultType
881 if (
auto pointerType =
882 llvm::dyn_cast<emitc::PointerType>(getValue().
getType())) {
886 <<
"on pointer operand requires one index operand, but got "
892 return emitOpError() <<
"on pointer operand requires index operand to be "
893 "integer-like, but got "
897 Type pointeeType = pointerType.getPointee();
899 if (pointeeType != resultType) {
900 return emitOpError() <<
"on pointer operand requires pointee type ("
901 << pointeeType <<
") and result type (" << resultType
916 #include "mlir/Dialect/EmitC/IR/EmitCEnums.cpp.inc"
922 #define GET_ATTRDEF_CLASSES
923 #include "mlir/Dialect/EmitC/IR/EmitCAttributes.cpp.inc"
929 #define GET_TYPEDEF_CLASSES
930 #include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc"
951 if (!isValidElementType(elementType))
952 return parser.
emitError(typeLoc,
"invalid array element type"),
Type();
955 return parser.
getChecked<ArrayType>(dimensions, elementType);
961 printer << dim <<
'x';
971 return emitError() <<
"shape must not be empty";
973 for (int64_t dim : shape) {
975 return emitError() <<
"dimensions must have positive size";
979 return emitError() <<
"element type must not be none";
981 if (!isValidElementType(elementType))
982 return emitError() <<
"invalid array element type";
989 Type elementType)
const {
1006 <<
"!emitc.lvalue must wrap supported emitc type, but got " << value;
1008 if (llvm::isa<emitc::ArrayType>(value))
1009 return emitError() <<
"!emitc.lvalue cannot wrap !emitc.array type";
1020 llvm::StringRef value) {
1021 if (value.empty()) {
1022 return emitError() <<
"expected non empty string in !emitc.opaque type";
1024 if (value.back() ==
'*') {
1025 return emitError() <<
"pointer not allowed as outer type with "
1026 "!emitc.opaque, use !emitc.ptr instead";
1037 if (llvm::isa<emitc::LValueType>(value))
1038 return emitError() <<
"pointers to lvalues are not allowed";
1057 if (
auto array = llvm::dyn_cast<ArrayType>(type))
1077 if (!llvm::isa<ElementsAttr, IntegerAttr, FloatAttr, emitc::OpaqueAttr>(
1080 <<
"initial value should be a integer, float, elements or opaque "
1087 return emitOpError(
"expected valid emitc type");
1089 if (getInitialValue().has_value()) {
1090 Attribute initValue = getInitialValue().value();
1093 if (
auto elementsAttr = llvm::dyn_cast<ElementsAttr>(initValue)) {
1094 auto arrayType = llvm::dyn_cast<ArrayType>(
getType());
1096 return emitOpError(
"expected array type, but got ") <<
getType();
1098 Type initType = elementsAttr.getType();
1100 if (initType != tensorType) {
1101 return emitOpError(
"initial value expected to be of type ")
1102 <<
getType() <<
", but was of type " << initType;
1104 }
else if (
auto intAttr = dyn_cast<IntegerAttr>(initValue)) {
1105 if (intAttr.getType() !=
getType()) {
1106 return emitOpError(
"initial value expected to be of type ")
1107 <<
getType() <<
", but was of type " << intAttr.getType();
1109 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(initValue)) {
1110 if (floatAttr.getType() !=
getType()) {
1111 return emitOpError(
"initial value expected to be of type ")
1112 <<
getType() <<
", but was of type " << floatAttr.getType();
1114 }
else if (!isa<emitc::OpaqueAttr>(initValue)) {
1115 return emitOpError(
"initial value should be a integer, float, elements "
1116 "or opaque attribute, but got ")
1120 if (getStaticSpecifier() && getExternSpecifier()) {
1121 return emitOpError(
"cannot have both static and extern specifiers");
1136 return emitOpError(
"'")
1137 << getName() <<
"' does not reference a valid emitc.global";
1139 Type resultType = getResult().getType();
1140 Type globalType = global.getType();
1143 if (llvm::isa<ArrayType>(globalType)) {
1144 if (globalType != resultType)
1145 return emitOpError(
"on array type expects result type ")
1146 << resultType <<
" to match type " << globalType
1147 <<
" of the global @" << getName();
1152 auto lvalueType = dyn_cast<LValueType>(resultType);
1153 if (!lvalueType || lvalueType.getValueType() != globalType)
1154 return emitOpError(
"on non-array type expects result inner type ")
1155 << lvalueType.getValueType() <<
" to match type " << globalType
1156 <<
" of the global @" << getName();
1171 Region ®ion = *caseRegions.emplace_back(std::make_unique<Region>());
1175 caseValues.push_back(value);
1184 for (
auto [value, region] : llvm::zip(cases.
asArrayRef(), caseRegions)) {
1186 p <<
"case " << value <<
' ';
1192 const Twine &name) {
1193 auto yield = dyn_cast<emitc::YieldOp>(region.
front().
back());
1195 return op.emitOpError(
"expected region to end with emitc.yield, but got ")
1198 if (yield.getNumOperands() != 0) {
1199 return (op.emitOpError(
"expected each region to return ")
1200 <<
"0 values, but " << name <<
" returns "
1201 << yield.getNumOperands())
1202 .attachNote(yield.getLoc())
1203 <<
"see yield operation here";
1211 return emitOpError(
"unsupported type ") << getArg().getType();
1213 if (getCases().size() != getCaseRegions().size()) {
1214 return emitOpError(
"has ")
1215 << getCaseRegions().size() <<
" case regions but "
1216 << getCases().size() <<
" case values";
1220 for (int64_t value : getCases())
1221 if (!valueSet.insert(value).second)
1222 return emitOpError(
"has duplicate case value: ") << value;
1224 if (failed(
verifyRegion(*
this, getDefaultRegion(),
"default region")))
1228 if (failed(
verifyRegion(*
this, caseRegion,
"case region #" + Twine(idx))))
1234 unsigned emitc::SwitchOp::getNumCases() {
return getCases().size(); }
1236 Block &emitc::SwitchOp::getDefaultBlock() {
return getDefaultRegion().
front(); }
1238 Block &emitc::SwitchOp::getCaseBlock(
unsigned idx) {
1239 assert(idx < getNumCases() &&
"case index out-of-bounds");
1240 return getCaseRegions()[idx].front();
1243 void SwitchOp::getSuccessorRegions(
1245 llvm::copy(getRegions(), std::back_inserter(successors));
1248 void SwitchOp::getEntrySuccessorRegions(
1251 FoldAdaptor adaptor(operands, *
this);
1254 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
1256 llvm::copy(getRegions(), std::back_inserter(successors));
1262 for (
auto [caseValue, caseRegion] : llvm::zip(getCases(), getCaseRegions())) {
1263 if (caseValue == arg.getInt()) {
1264 successors.emplace_back(&caseRegion);
1268 successors.emplace_back(&getDefaultRegion());
1271 void SwitchOp::getRegionInvocationBounds(
1273 auto operandValue = llvm::dyn_cast_or_null<IntegerAttr>(operands.front());
1274 if (!operandValue) {
1280 unsigned liveIndex = getNumRegions() - 1;
1281 const auto *iteratorToInt = llvm::find(getCases(), operandValue.getInt());
1283 liveIndex = iteratorToInt != getCases().end()
1284 ? std::distance(getCases().begin(), iteratorToInt)
1287 for (
unsigned regIndex = 0, regNum = getNumRegions(); regIndex < regNum;
1289 bounds.emplace_back(0, regIndex == liveIndex);
1296 #define GET_OP_CLASSES
1297 #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 void copy(Location loc, Value dst, Value src, Value size, OpBuilder &builder)
Copies the given number of bytes from src to dst pointers.
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 void printEmitCGlobalOpTypeAndInitialValue(OpAsmPrinter &p, GlobalOp 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 std::string diag(const llvm::Value &value)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
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 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)
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.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start 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.
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.
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.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
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 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 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.