27 #include "llvm/ADT/APFloat.h"
28 #include "llvm/ADT/TypeSwitch.h"
29 #include "llvm/IR/DataLayout.h"
30 #include "llvm/Support/Error.h"
39 using mlir::LLVM::cconv::getMaxEnumValForCConv;
40 using mlir::LLVM::linkage::getMaxEnumValForLinkage;
41 using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
43 #include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
54 if (attr.
getName() ==
"fastmathFlags") {
56 FastmathFlagsAttr::get(attr.getValue().getContext(), {});
74 << name <<
"' does not reference a valid LLVM function";
75 if (func.isExternal())
76 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
102 template <
typename Ty>
103 struct EnumTraits {};
105 #define REGISTER_ENUM_TYPE(Ty) \
107 struct EnumTraits<Ty> { \
108 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
109 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
122 template <
typename EnumTy,
typename RetTy = EnumTy>
124 EnumTy defaultValue) {
126 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
131 return static_cast<RetTy
>(defaultValue);
132 return static_cast<RetTy
>(index);
136 p << stringifyLinkage(val.getLinkage());
142 parseOptionalLLVMKeyword<LLVM::Linkage>(p, LLVM::Linkage::External));
148 uint64_t alignment = 1) {
154 if (alignment == 1) {
161 builder.
getNamedAttr(LLVMDialect::getAlignAttrName(), alignmentAttr);
171 int pos = isExpandLoad ? 0 : 1;
173 {alignDictAttr, emptyDictAttr, emptyDictAttr})
175 {emptyDictAttr, alignDictAttr, emptyDictAttr});
187 if (!operands.empty()) {
190 llvm::interleaveComma(operandTypes, p);
199 std::optional<ArrayAttr> opBundleTags) {
200 if (opBundleOperands.empty())
202 assert(opBundleTags &&
"expect operand bundle tags");
205 llvm::interleaveComma(
206 llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
208 auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
226 return p.
emitError(currentParserLoc,
"expect operand bundle tag");
237 opBundleOperands.push_back(std::move(operands));
238 opBundleOperandTypes.push_back(std::move(types));
248 ArrayAttr &opBundleTags) {
256 auto bundleParser = [&] {
276 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
277 <<
", " << getOperand(1);
279 p <<
" : " << getLhs().getType();
283 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
284 <<
", " << getOperand(1);
286 p <<
" : " << getLhs().getType();
293 template <
typename CmpPredicateType>
295 StringAttr predicateAttr;
298 SMLoc predicateLoc, trailingTypeLoc;
310 int64_t predicateValue = 0;
311 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
312 std::optional<ICmpPredicate> predicate =
313 symbolizeICmpPredicate(predicateAttr.getValue());
316 <<
"'" << predicateAttr.getValue()
317 <<
"' is an incorrect value of the 'predicate' attribute";
318 predicateValue =
static_cast<int64_t
>(*predicate);
320 std::optional<FCmpPredicate> predicate =
321 symbolizeFCmpPredicate(predicateAttr.getValue());
324 <<
"'" << predicateAttr.getValue()
325 <<
"' is an incorrect value of the 'predicate' attribute";
326 predicateValue =
static_cast<int64_t
>(*predicate);
336 "expected LLVM dialect-compatible type");
342 return parseCmpOp<ICmpPredicate>(parser, result);
346 return parseCmpOp<FCmpPredicate>(parser, result);
352 ShapedType shapedType = dyn_cast<ShapedType>(type);
359 if (getPredicate() != ICmpPredicate::eq &&
360 getPredicate() != ICmpPredicate::ne)
364 if (getLhs() == getRhs())
366 getPredicate() == ICmpPredicate::eq);
369 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
371 getPredicate() == ICmpPredicate::ne);
374 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
375 Value lhs = getLhs();
376 Value rhs = getRhs();
377 getLhsMutable().assign(rhs);
378 getRhsMutable().assign(lhs);
396 p <<
' ' << getArraySize() <<
" x " << getElemType();
397 if (getAlignment() && *getAlignment() != 0)
399 {kElemTypeAttrName, getInallocaAttrName()});
403 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
404 p <<
" : " << funcTy;
412 SMLoc trailingTypeLoc;
424 std::optional<NamedAttribute> alignmentAttr =
426 if (alignmentAttr.has_value()) {
427 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
430 "expected integer alignment");
431 if (alignmentInt.getValue().isZero())
436 auto funcType = llvm::dyn_cast<FunctionType>(type);
437 if (!funcType || funcType.getNumInputs() != 1 ||
438 funcType.getNumResults() != 1)
441 "expected trailing function type with one argument and one result");
446 Type resultType = funcType.getResult(0);
447 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
450 result.
addTypes({funcType.getResult(0)});
456 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
457 targetExtType && !targetExtType.supportsMemOps())
459 <<
"this target extension type cannot be used in alloca";
469 assert(index == 0 &&
"invalid successor index");
478 assert(index < getNumSuccessors() &&
"invalid successor index");
480 : getFalseDestOperandsMutable());
486 std::optional<std::pair<uint32_t, uint32_t>> weights) {
491 static_cast<int32_t
>(weights->second)});
493 build(builder, result, condition, trueOperands, falseOperands, weightsAttr,
494 {}, trueDest, falseDest);
508 if (!branchWeights.empty())
511 build(builder, result, value, defaultOperands, caseOperands, caseValues,
512 weightsAttr, defaultDestination, caseDestinations);
521 if (!caseValues.empty()) {
523 static_cast<int64_t
>(caseValues.size()), value.
getType());
527 build(builder, result, value, defaultDestination, defaultOperands,
528 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
537 if (!caseValues.empty()) {
539 static_cast<int64_t
>(caseValues.size()), value.
getType());
543 build(builder, result, value, defaultDestination, defaultOperands,
544 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
560 auto parseCase = [&]() {
564 values.push_back(APInt(bitWidth, value,
true));
577 caseDestinations.push_back(destination);
578 caseOperands.emplace_back(operands);
579 caseOperandTypes.emplace_back(operandTypes);
585 ShapedType caseValueType =
605 llvm::zip(caseValues, caseDestinations),
621 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
623 getCaseValues()->size() !=
624 static_cast<int64_t
>(getCaseDestinations().size())))
625 return emitOpError(
"expects number of case values to match number of "
626 "case destinations");
627 if (getCaseValues() &&
629 return emitError(
"expects case value type to match condition value type");
634 assert(index < getNumSuccessors() &&
"invalid successor index");
636 : getCaseOperandsMutable(index - 1));
643 constexpr int32_t GEPOp::kDynamicIndex;
647 getDynamicIndices());
652 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
653 return vectorType.getElementType();
665 for (
const GEPArg &iter : indices) {
670 bool requiresConst = !rawConstantIndices.empty() &&
671 isa_and_nonnull<LLVMStructType>(currType);
672 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
676 rawConstantIndices.push_back(intC.getSExtValue());
678 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
679 dynamicIndices.push_back(val);
682 rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
687 if (rawConstantIndices.size() == 1 || !currType)
691 .Case<VectorType, LLVMArrayType>([](
auto containerType) {
692 return containerType.getElementType();
694 .Case([&](LLVMStructType structType) ->
Type {
695 int64_t memberIndex = rawConstantIndices.back();
696 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
697 structType.getBody().size())
698 return structType.getBody()[memberIndex];
707 GEPNoWrapFlags noWrapFlags,
726 GEPNoWrapFlags noWrapFlags,
728 build(builder, result, resultType, elementType, basePtr,
738 auto idxParser = [&]() -> ParseResult {
749 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
763 llvm::interleaveComma(
766 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
769 printer << cast<IntegerAttr>(cst).getInt();
779 if (indexPos >= indices.
size())
784 .Case<LLVMStructType>([&](LLVMStructType structType) -> LogicalResult {
785 auto attr = dyn_cast<IntegerAttr>(indices[indexPos]);
787 return emitOpError() <<
"expected index " << indexPos
788 <<
" indexing a struct to be constant";
790 int32_t gepIndex = attr.getInt();
793 static_cast<size_t>(gepIndex) >= elementTypes.size())
794 return emitOpError() <<
"index " << indexPos
795 <<
" indexing a struct is out of bounds";
800 indices, emitOpError);
802 .Case<VectorType, LLVMArrayType>(
803 [&](
auto containerType) -> LogicalResult {
805 indexPos + 1, indices, emitOpError);
807 .Default([&](
auto otherType) -> LogicalResult {
809 <<
"type " << otherType <<
" cannot be indexed (index #"
822 if (
static_cast<size_t>(
823 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
824 getDynamicIndices().size())
825 return emitOpError(
"expected as many dynamic indices as specified in '")
826 << getRawConstantIndicesAttrName().getValue() <<
"'";
828 if (getNoWrapFlags() == GEPNoWrapFlags::inboundsFlag)
829 return emitOpError(
"'inbounds_flag' cannot be used directly.");
832 [&] {
return emitOpError(); });
839 void LoadOp::getEffects(
848 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
849 getOrdering() != AtomicOrdering::unordered)) {
860 if (!isa<IntegerType, LLVMPointerType>(type))
865 if (bitWidth.isScalable())
868 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
872 template <
typename OpTy>
876 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
879 return memOp.emitOpError(
"unsupported type ")
880 << valueType <<
" for atomic access";
881 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
882 return memOp.emitOpError(
"unsupported ordering '")
883 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
884 if (!memOp.getAlignment())
885 return memOp.emitOpError(
"expected alignment for atomic access");
888 if (memOp.getSyncscope())
889 return memOp.emitOpError(
890 "expected syncscope to be null for non-atomic access");
895 Type valueType = getResult().getType();
897 {AtomicOrdering::release, AtomicOrdering::acq_rel});
901 Value addr,
unsigned alignment,
bool isVolatile,
902 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
903 AtomicOrdering ordering, StringRef syncscope) {
904 build(builder, state, type, addr,
906 isNonTemporal, isInvariant, isInvariantGroup, ordering,
907 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
918 void StoreOp::getEffects(
927 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
928 getOrdering() != AtomicOrdering::unordered)) {
935 Type valueType = getValue().getType();
937 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
941 Value addr,
unsigned alignment,
bool isVolatile,
942 bool isNonTemporal,
bool isInvariantGroup,
943 AtomicOrdering ordering, StringRef syncscope) {
944 build(builder, state, value, addr,
946 isNonTemporal, isInvariantGroup, ordering,
947 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
949 nullptr,
nullptr,
nullptr);
959 Type resultType = calleeType.getReturnType();
960 if (!isa<LLVM::LLVMVoidType>(resultType))
961 results.push_back(resultType);
967 return calleeType.isVarArg() ?
TypeAttr::get(calleeType) :
nullptr;
977 resultType = results.front();
984 build(builder, state, results, builder.
getStringAttr(callee), args);
994 assert(callee &&
"expected non-null callee in direct call builder");
995 build(builder, state, results,
996 nullptr, callee, args,
nullptr,
999 nullptr,
nullptr,
nullptr,
1009 LLVMFunctionType calleeType, StringRef callee,
1011 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1015 LLVMFunctionType calleeType, StringAttr callee,
1033 nullptr,
nullptr,
nullptr,
1039 LLVMFunctionType calleeType,
ValueRange args) {
1044 nullptr,
nullptr,
nullptr,
1045 nullptr,
nullptr,
nullptr,
1056 auto calleeType = func.getFunctionType();
1060 nullptr,
nullptr,
nullptr,
1061 nullptr,
nullptr,
nullptr,
1075 return getOperand(0);
1081 auto symRef = cast<SymbolRefAttr>(callee);
1082 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1085 return setOperand(0, cast<Value>(callee));
1089 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1094 getCalleeOperands().size());
1101 if (callee.isExternal())
1103 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1107 auto hasSubprogram = [](
Operation *op) {
1112 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1114 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1116 return callOp.emitError()
1117 <<
"inlinable function call in a function with a DISubprogram "
1118 "location must have a debug location";
1124 template <
typename OpTy>
1126 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1131 if (!varCalleeType->isVarArg())
1132 return callOp.emitOpError(
1133 "expected var_callee_type to be a variadic function type");
1137 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1138 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1139 << callOp.getArgOperands().size() <<
" parameters";
1142 for (
auto [paramType, operand] :
1143 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1144 if (paramType != operand.getType())
1145 return callOp.emitOpError()
1146 <<
"var_callee_type parameter type mismatch: " << paramType
1147 <<
" != " << operand.getType();
1150 if (!callOp.getNumResults()) {
1151 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1152 return callOp.emitOpError(
"expected var_callee_type to return void");
1154 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1155 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1156 << varCalleeType->getReturnType()
1157 <<
" != " << callOp.getResult().getType();
1162 template <
typename OpType>
1165 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1167 auto isStringAttr = [](
Attribute tagAttr) {
1168 return isa<StringAttr>(tagAttr);
1170 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1171 return op.emitError(
"operand bundle tag must be a StringAttr");
1173 size_t numOpBundles = opBundleOperands.size();
1174 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1175 if (numOpBundles != numOpBundleTags)
1176 return op.emitError(
"expected ")
1177 << numOpBundles <<
" operand bundle tags, but actually got "
1193 bool isIndirect =
false;
1199 if (!getNumOperands())
1201 "must have either a `callee` attribute or at least an operand");
1202 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1204 return emitOpError(
"indirect call expects a pointer as callee: ")
1205 << getOperand(0).getType();
1212 return emitOpError()
1214 <<
"' does not reference a symbol in the current scope";
1215 if (
auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1218 fnType = fn.getFunctionType();
1219 }
else if (
auto ifunc = dyn_cast<IFuncOp>(callee)) {
1220 fnType = ifunc.getIFuncType();
1222 return emitOpError()
1224 <<
"' does not reference a valid LLVM function or IFunc";
1228 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1230 return emitOpError(
"callee does not have a functional type: ") << fnType;
1232 if (funcType.isVarArg() && !getVarCalleeType())
1233 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1237 if (!funcType.isVarArg() &&
1238 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1239 return emitOpError() <<
"incorrect number of operands ("
1240 << (getCalleeOperands().size() - isIndirect)
1241 <<
") for callee (expecting: "
1242 << funcType.getNumParams() <<
")";
1244 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1245 return emitOpError() <<
"incorrect number of operands ("
1246 << (getCalleeOperands().size() - isIndirect)
1247 <<
") for varargs callee (expecting at least: "
1248 << funcType.getNumParams() <<
")";
1250 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1251 if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1252 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1253 << getOperand(i + isIndirect).getType()
1254 <<
" != " << funcType.getParamType(i);
1256 if (getNumResults() == 0 &&
1257 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1258 return emitOpError() <<
"expected function call to produce a value";
1260 if (getNumResults() != 0 &&
1261 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1262 return emitOpError()
1263 <<
"calling function with void result must not produce values";
1265 if (getNumResults() > 1)
1266 return emitOpError()
1267 <<
"expected LLVM function call to produce 0 or 1 result";
1269 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1270 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1271 <<
" != " << funcType.getReturnType();
1277 auto callee = getCallee();
1278 bool isDirect = callee.has_value();
1283 if (getCConv() != LLVM::CConv::C)
1284 p << stringifyCConv(getCConv()) <<
' ';
1287 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1296 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1297 p <<
'(' << args <<
')';
1300 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1301 p <<
" vararg(" << *varCalleeType <<
")";
1303 if (!getOpBundleOperands().empty()) {
1306 getOpBundleOperands().getTypes(), getOpBundleTags());
1310 {getCalleeAttrName(), getTailCallKindAttrName(),
1311 getVarCalleeTypeAttrName(), getCConvAttrName(),
1312 getOperandSegmentSizesAttrName(),
1313 getOpBundleSizesAttrName(),
1314 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1315 getResAttrsAttrName()});
1319 p << getOperand(0).getType() <<
", ";
1323 p, args.getTypes(), getArgAttrsAttr(),
1324 false, getResultTypes(), getResAttrsAttr());
1339 types.emplace_back();
1344 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1349 resTypes, resultAttrs)) {
1351 return parser.
emitError(trailingTypesLoc,
1352 "expected direct call to have 1 trailing types");
1353 return parser.
emitError(trailingTypesLoc,
1354 "expected trailing function type");
1357 if (resTypes.size() > 1)
1358 return parser.
emitError(trailingTypesLoc,
1359 "expected function with 0 or 1 result");
1360 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1361 return parser.
emitError(trailingTypesLoc,
1362 "expected a non-void result type");
1368 llvm::append_range(types, argTypes);
1372 if (!resTypes.empty())
1386 if (
failed(*parseResult))
1387 return *parseResult;
1388 operands.push_back(funcPtrOperand);
1397 StringAttr opBundleSizesAttrName) {
1398 unsigned opBundleIndex = 0;
1399 for (
const auto &[operands, types] :
1400 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1401 if (operands.size() != types.size())
1402 return parser.
emitError(loc,
"expected ")
1404 <<
" types for operand bundle operands for operand bundle #"
1405 << opBundleIndex <<
", but actually got " << types.size();
1411 opBundleSizes.reserve(opBundleOperands.size());
1412 for (
const auto &operands : opBundleOperands)
1413 opBundleSizes.push_back(operands.size());
1416 opBundleSizesAttrName,
1428 SymbolRefAttr funcAttr;
1429 TypeAttr varCalleeType;
1433 ArrayAttr opBundleTags;
1437 getCConvAttrName(result.
name),
1439 parseOptionalLLVMKeyword<CConv>(parser, LLVM::CConv::C)));
1442 getTailCallKindAttrName(result.
name),
1444 parseOptionalLLVMKeyword<TailCallKind>(
1450 bool isDirect = operands.empty();
1463 StringAttr varCalleeTypeAttrName =
1464 CallOp::getVarCalleeTypeAttrName(result.
name);
1476 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1477 result &&
failed(*result))
1479 if (opBundleTags && !opBundleTags.empty())
1480 result.
addAttribute(CallOp::getOpBundleTagsAttrName(result.
name).getValue(),
1490 argAttrs, resultAttrs))
1493 parser.
getBuilder(), result, argAttrs, resultAttrs,
1494 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
1496 opBundleOperandTypes,
1497 getOpBundleSizesAttrName(result.
name)))
1500 int32_t numOpBundleOperands = 0;
1501 for (
const auto &operands : opBundleOperands)
1502 numOpBundleOperands += operands.size();
1505 CallOp::getOperandSegmentSizeAttr(),
1507 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1511 LLVMFunctionType CallOp::getCalleeFunctionType() {
1512 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1513 return *varCalleeType;
1524 auto calleeType = func.getFunctionType();
1527 nullptr,
nullptr, normalOps, unwindOps,
1528 nullptr,
nullptr, {}, {}, normal, unwind);
1535 build(builder, state, tys,
1536 nullptr, callee, ops,
nullptr,
1537 nullptr, normalOps, unwindOps,
nullptr,
nullptr, {}, {},
1547 nullptr,
nullptr, normalOps, unwindOps,
1548 nullptr,
nullptr, {}, {}, normal, unwind);
1552 assert(index < getNumSuccessors() &&
"invalid successor index");
1554 : getUnwindDestOperandsMutable());
1562 return getOperand(0);
1568 auto symRef = cast<SymbolRefAttr>(callee);
1569 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1572 return setOperand(0, cast<Value>(callee));
1576 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1581 getCalleeOperands().size());
1588 Block *unwindDest = getUnwindDest();
1589 if (unwindDest->
empty())
1590 return emitError(
"must have at least one operation in unwind destination");
1593 if (!isa<LandingpadOp>(unwindDest->
front()))
1594 return emitError(
"first operation in unwind destination should be a "
1595 "llvm.landingpad operation");
1604 auto callee = getCallee();
1605 bool isDirect = callee.has_value();
1610 if (getCConv() != LLVM::CConv::C)
1611 p << stringifyCConv(getCConv()) <<
' ';
1619 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1626 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1627 p <<
" vararg(" << *varCalleeType <<
")";
1629 if (!getOpBundleOperands().empty()) {
1632 getOpBundleOperands().getTypes(), getOpBundleTags());
1636 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1637 getCConvAttrName(), getVarCalleeTypeAttrName(),
1638 getOpBundleSizesAttrName(),
1639 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1640 getResAttrsAttrName()});
1644 p << getOperand(0).getType() <<
", ";
1646 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1648 false, getResultTypes(), getResAttrsAttr());
1661 SymbolRefAttr funcAttr;
1662 TypeAttr varCalleeType;
1665 ArrayAttr opBundleTags;
1666 Block *normalDest, *unwindDest;
1672 getCConvAttrName(result.
name),
1674 parseOptionalLLVMKeyword<CConv>(parser, LLVM::CConv::C)));
1679 bool isDirect = operands.empty();
1695 StringAttr varCalleeTypeAttrName =
1696 InvokeOp::getVarCalleeTypeAttrName(result.
name);
1708 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1709 result &&
failed(*result))
1711 if (opBundleTags && !opBundleTags.empty())
1713 InvokeOp::getOpBundleTagsAttrName(result.
name).getValue(),
1723 argAttrs, resultAttrs))
1726 parser.
getBuilder(), result, argAttrs, resultAttrs,
1727 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
1730 opBundleOperandTypes,
1731 getOpBundleSizesAttrName(result.
name)))
1738 int32_t numOpBundleOperands = 0;
1739 for (
const auto &operands : opBundleOperands)
1740 numOpBundleOperands += operands.size();
1743 InvokeOp::getOperandSegmentSizeAttr(),
1745 static_cast<int32_t>(normalOperands.size()),
1746 static_cast<int32_t>(unwindOperands.size()),
1747 numOpBundleOperands}));
1751 LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1752 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1753 return *varCalleeType;
1763 if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1764 if (!func.getPersonality())
1766 "llvm.landingpad needs to be in a function with a personality");
1772 if (!getCleanup() && getOperands().empty())
1773 return emitError(
"landingpad instruction expects at least one clause or "
1774 "cleanup attribute");
1776 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1777 value = getOperand(idx);
1778 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1785 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1788 <<
"global addresses expected as operand to "
1789 "bitcast used in clauses for landingpad";
1797 << idx <<
" is not a known constant - null, addressof, bitcast";
1804 p << (getCleanup() ?
" cleanup " :
" ");
1807 for (
auto value : getOperands()) {
1810 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1811 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1858 Type llvmType = containerType;
1860 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1868 for (int64_t idx : position) {
1869 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1870 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1871 emitError(
"position out of bounds: ") << idx;
1874 llvmType = arrayType.getElementType();
1875 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1877 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1878 emitError(
"position out of bounds: ") << idx;
1881 llvmType = structType.getBody()[idx];
1883 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1894 for (int64_t idx : position) {
1895 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1896 llvmType = structType.getBody()[idx];
1898 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1903 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1904 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
1906 newPos.append(getPosition().begin(), getPosition().end());
1907 setPosition(newPos);
1908 getContainerMutable().set(extractValueOp.getContainer());
1916 if (isa<SplatElementsAttr>(constval))
1918 if (getPosition().size() == 1)
1923 auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1926 bool switchedToInsertedValue =
false;
1927 while (insertValueOp) {
1929 auto extractPosSize = extractPos.size();
1930 auto insertPosSize = insertPos.size();
1933 if (extractPos == insertPos)
1934 return insertValueOp.getValue();
1948 if (extractPosSize > insertPosSize &&
1949 extractPos.take_front(insertPosSize) == insertPos) {
1950 insertValueOp = insertValueOp.getValue().getDefiningOp<InsertValueOp>();
1951 extractPos = extractPos.drop_front(insertPosSize);
1952 switchedToInsertedValue =
true;
1957 unsigned min =
std::min(extractPosSize, insertPosSize);
1969 if (extractPos.take_front(
min) == insertPos.take_front(
min))
1974 if (!switchedToInsertedValue) {
1977 getContainerMutable().assign(insertValueOp.getContainer());
1978 result = getResult();
1980 insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1986 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1992 if (getRes().
getType() != valueType)
1993 return emitOpError() <<
"Type mismatch: extracting from "
1994 << getContainer().getType() <<
" should produce "
1995 << valueType <<
" but this op returns "
1996 << getRes().getType();
2002 build(builder, state,
2017 [&](StringRef msg) {
2021 return success(!!valueType);
2031 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
2037 if (getValue().
getType() != valueType)
2038 return emitOpError() <<
"Type mismatch: cannot insert "
2039 << getValue().getType() <<
" into "
2040 << getContainer().getType();
2050 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2054 Type expectedType = parent.getFunctionType().getReturnType();
2055 if (llvm::isa<LLVMVoidType>(expectedType)) {
2059 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2063 if (llvm::isa<LLVMVoidType>(expectedType))
2066 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2069 if (expectedType != getArg().
getType()) {
2071 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2082 return dyn_cast_or_null<GlobalOp>(
2087 return dyn_cast_or_null<LLVMFuncOp>(
2092 return dyn_cast_or_null<AliasOp>(
2097 return dyn_cast_or_null<IFuncOp>(
2106 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2107 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2108 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2109 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2111 if (!global && !
function && !alias && !ifunc)
2112 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2113 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2115 LLVMPointerType type =
getType();
2116 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2117 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2118 return emitOpError(
"pointer address space must match address space of the "
2119 "referenced global or alias");
2126 return getGlobalNameAttr();
2147 getFunctionNameAttr());
2148 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2149 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2151 if (!
function && !alias)
2153 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2156 if (alias.getInitializer()
2157 .walk([&](AddressOfOp addrOp) {
2158 if (addrOp.getGlobal(symbolTable))
2159 return WalkResult::interrupt();
2160 return WalkResult::advance();
2163 return emitOpError(
"must reference an alias to a function");
2166 if ((
function &&
function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2167 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2169 "target function with 'extern_weak' linkage not allowed");
2185 StringRef symName) {
2192 LogicalResult ComdatOp::verifyRegions() {
2193 Region &body = getBody();
2195 if (!isa<ComdatSelectorOp>(op))
2196 return op.emitError(
2197 "only comdat selector symbols can appear in a comdat region");
2207 bool isConstant, Linkage linkage, StringRef name,
2208 Attribute value, uint64_t alignment,
unsigned addrSpace,
2209 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2243 if (!dbgExprs.empty())
2250 template <
typename OpType>
2252 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2253 StringRef visibility = stringifyVisibility(op.getVisibility_());
2254 if (!visibility.empty())
2255 p << visibility <<
' ';
2256 if (op.getThreadLocal_())
2257 p <<
"thread_local ";
2258 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2259 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2266 printCommonGlobalAndAlias<GlobalOp>(p, *
this);
2271 if (
auto value = getValueOrNull())
2274 if (
auto comdat = getComdat())
2275 p <<
" comdat(" << *comdat <<
')';
2281 {SymbolTable::getSymbolAttrName(),
2282 getGlobalTypeAttrName(), getConstantAttrName(),
2283 getValueAttrName(), getLinkageAttrName(),
2284 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2285 getVisibility_AttrName(), getComdatAttrName()});
2288 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2292 Region &initializer = getInitializerRegion();
2293 if (!initializer.
empty()) {
2300 std::optional<SymbolRefAttr> attr) {
2305 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2306 return op->
emitError() <<
"expected comdat symbol";
2316 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2317 if (blockTags.contains(blockTagOp.getTag())) {
2318 blockTagOp.emitError()
2319 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2320 <<
"' in the same function: ";
2321 return WalkResult::interrupt();
2323 blockTags.insert(blockTagOp.getTag());
2332 template <
typename OpType>
2338 OpType::getLinkageAttrName(result.
name),
2340 parser, LLVM::Linkage::External)));
2345 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2346 parser, LLVM::Visibility::Default)));
2355 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2371 if (parseCommonGlobalAndAlias<GlobalOp>(parser, result).
failed())
2393 SymbolRefAttr comdat;
2406 if (types.size() > 1)
2410 if (types.empty()) {
2411 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2414 strAttr.getValue().size());
2415 types.push_back(arrayType);
2418 "type can only be omitted for string globals");
2434 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2435 return intValue.getValue().isZero();
2436 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2437 return fpValue.getValue().isZero();
2438 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2440 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2442 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2449 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2450 LLVMMetadataType, LLVMLabelType>(
getType())
2451 : llvm::isa<PointerElementTypeInterface>(
getType());
2454 "expects type to be a valid element type for an LLVM global");
2456 return emitOpError(
"must appear at the module level");
2458 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2459 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2460 IntegerType elementType =
2461 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2462 if (!elementType || elementType.getWidth() != 8 ||
2463 type.getNumElements() != strAttr.getValue().size())
2465 "requires an i8 array type of the length equal to that of the string "
2469 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2470 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2471 return emitOpError()
2472 <<
"this target extension type cannot be used in a global";
2475 return emitOpError() <<
"global with target extension type can only be "
2476 "initialized with zero-initializer";
2479 if (getLinkage() == Linkage::Common) {
2480 if (
Attribute value = getValueOrNull()) {
2482 return emitOpError()
2483 <<
"expected zero value for '"
2484 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2489 if (getLinkage() == Linkage::Appending) {
2490 if (!llvm::isa<LLVMArrayType>(
getType())) {
2491 return emitOpError() <<
"expected array type for '"
2492 << stringifyLinkage(Linkage::Appending)
2500 std::optional<uint64_t> alignAttr = getAlignment();
2501 if (alignAttr.has_value()) {
2502 uint64_t value = alignAttr.value();
2503 if (!llvm::isPowerOf2_64(value))
2504 return emitError() <<
"alignment attribute is not a power of 2";
2510 LogicalResult GlobalOp::verifyRegions() {
2511 if (
Block *b = getInitializerBlock()) {
2512 ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2513 if (ret.operand_type_begin() == ret.operand_type_end())
2514 return emitOpError(
"initializer region cannot return void");
2515 if (*ret.operand_type_begin() !=
getType())
2516 return emitOpError(
"initializer region type ")
2517 << *ret.operand_type_begin() <<
" does not match global type "
2521 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2522 if (!iface || !iface.hasNoEffect())
2523 return op.emitError()
2524 <<
"ops with side effects not allowed in global initializers";
2527 if (getValueOrNull())
2528 return emitOpError(
"cannot have both initializer value and region");
2543 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2546 return op->
emitError(
"data element must be symbol or #llvm.zero");
2563 if (getCtors().size() == getPriorities().size() &&
2564 getCtors().size() == getData().size())
2567 "ctors, priorities, and data must have the same number of elements");
2588 if (getDtors().size() == getPriorities().size() &&
2589 getDtors().size() == getData().size())
2592 "dtors, priorities, and data must have the same number of elements");
2600 Linkage linkage, StringRef name,
bool dsoLocal,
2620 printCommonGlobalAndAlias<AliasOp>(p, *
this);
2624 {SymbolTable::getSymbolAttrName(),
2625 getAliasTypeAttrName(), getLinkageAttrName(),
2626 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2627 getVisibility_AttrName()});
2630 p <<
" : " <<
getType() <<
' ';
2643 if (parseCommonGlobalAndAlias<AliasOp>(parser, result).
failed())
2656 if (types.size() > 1)
2670 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2671 LLVMMetadataType, LLVMLabelType>(
getType())
2672 : llvm::isa<PointerElementTypeInterface>(
getType());
2675 "expects type to be a valid element type for an LLVM global alias");
2678 switch (getLinkage()) {
2679 case Linkage::External:
2680 case Linkage::Internal:
2681 case Linkage::Private:
2683 case Linkage::WeakODR:
2684 case Linkage::Linkonce:
2685 case Linkage::LinkonceODR:
2686 case Linkage::AvailableExternally:
2689 return emitOpError()
2690 <<
"'" << stringifyLinkage(getLinkage())
2691 <<
"' linkage not supported in aliases, available options: private, "
2692 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2693 "available_externally";
2699 LogicalResult AliasOp::verifyRegions() {
2700 Block &b = getInitializerBlock();
2702 if (ret.getNumOperands() == 0 ||
2703 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2704 return emitOpError(
"initializer region must always return a pointer");
2707 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2708 if (!iface || !iface.hasNoEffect())
2709 return op.emitError()
2710 <<
"ops with side effects are not allowed in alias initializers";
2716 unsigned AliasOp::getAddrSpace() {
2717 Block &initializer = getInitializerBlock();
2719 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2720 return ptrTy.getAddressSpace();
2728 Type iFuncType, StringRef resolverName,
Type resolverType,
2730 return build(builder, result, name, iFuncType, resolverName, resolverType,
2739 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2740 auto alias = dyn_cast<AliasOp>(symbol);
2742 Block &initBlock = alias.getInitializerBlock();
2744 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
2751 resolver = addrOp.getFunction(symbolTable);
2752 alias = addrOp.getAlias(symbolTable);
2755 return emitOpError(
"must have a function resolver");
2756 Linkage linkage = resolver.getLinkage();
2757 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
2758 return emitOpError(
"resolver must be a definition");
2759 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
2760 return emitOpError(
"resolver must return a pointer");
2761 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
2762 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
2763 return emitOpError(
"resolver has incorrect type");
2768 switch (getLinkage()) {
2769 case Linkage::External:
2770 case Linkage::Internal:
2771 case Linkage::Private:
2773 case Linkage::WeakODR:
2774 case Linkage::Linkonce:
2775 case Linkage::LinkonceODR:
2778 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
2779 <<
"' linkage not supported in ifuncs, available "
2780 "options: private, internal, linkonce, weak, "
2781 "linkonce_odr, weak_odr, or external linkage";
2793 auto containerType = v1.
getType();
2797 build(builder, state, vType, v1, v2, mask);
2798 state.addAttributes(attrs);
2811 "expected an LLVM compatible vector type");
2824 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2825 return emitOpError(
"expected a splat operation for scalable vectors");
2831 OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
2833 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
2834 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
2838 if (getMask().size() != 1 || getMask()[0] != 0)
2849 assert(empty() &&
"function already has an entry block");
2854 LLVMFunctionType type = getFunctionType();
2855 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2856 entry->
addArgument(type.getParamType(i), getLoc());
2861 StringRef name,
Type type, LLVM::Linkage linkage,
2862 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2865 std::optional<uint64_t> functionEntryCount) {
2881 if (functionEntryCount)
2884 if (argAttrs.empty())
2887 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2888 "expected as many argument attribute lists as arguments");
2890 builder, result, argAttrs, {},
2891 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2902 if (outputs.size() > 1) {
2903 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2904 "one function result");
2910 for (
auto t : inputs) {
2912 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2913 "type for function arguments");
2916 llvmInputs.push_back(t);
2923 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2924 "type for function results")
2943 parseOptionalLLVMKeyword<Linkage>(
2944 parser, LLVM::Linkage::External)));
2949 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2950 parser, LLVM::Visibility::Default)));
2955 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2960 getCConvAttrName(result.
name),
2962 parseOptionalLLVMKeyword<CConv>(parser, LLVM::CConv::C)));
2964 StringAttr nameAttr;
2974 parser,
true, entryArgs, isVariadic, resultTypes,
2979 for (
auto &arg : entryArgs)
2980 argTypes.push_back(arg.type);
2990 int64_t minRange, maxRange;
2997 getVscaleRangeAttrName(result.
name),
3004 SymbolRefAttr comdat;
3015 parser.
getBuilder(), result, entryArgs, resultAttrs,
3016 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
3029 if (getLinkage() != LLVM::Linkage::External)
3030 p << stringifyLinkage(getLinkage()) <<
' ';
3031 StringRef visibility = stringifyVisibility(getVisibility_());
3032 if (!visibility.empty())
3033 p << visibility <<
' ';
3034 if (
auto unnamedAddr = getUnnamedAddr()) {
3035 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3039 if (getCConv() != LLVM::CConv::C)
3040 p << stringifyCConv(getCConv()) <<
' ';
3044 LLVMFunctionType fnType = getFunctionType();
3047 argTypes.reserve(fnType.getNumParams());
3048 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3049 argTypes.push_back(fnType.getParamType(i));
3051 Type returnType = fnType.getReturnType();
3052 if (!llvm::isa<LLVMVoidType>(returnType))
3053 resTypes.push_back(returnType);
3056 isVarArg(), resTypes);
3059 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3060 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3061 << vscale->getMaxRange().getInt() <<
')';
3064 if (
auto comdat = getComdat())
3065 p <<
" comdat(" << *comdat <<
')';
3069 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3070 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3071 getComdatAttrName(), getUnnamedAddrAttrName(),
3072 getVscaleRangeAttrName()});
3075 Region &body = getBody();
3076 if (!body.empty()) {
3088 if (getLinkage() == LLVM::Linkage::Common)
3089 return emitOpError() <<
"functions cannot have '"
3090 << stringifyLinkage(LLVM::Linkage::Common)
3097 if (getLinkage() != LLVM::Linkage::External &&
3098 getLinkage() != LLVM::Linkage::ExternWeak)
3099 return emitOpError() <<
"external functions must have '"
3100 << stringifyLinkage(LLVM::Linkage::External)
3102 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3108 if (isNoInline() && isAlwaysInline())
3109 return emitError(
"no_inline and always_inline attributes are incompatible");
3111 if (isOptimizeNone() && !isNoInline())
3112 return emitOpError(
"with optimize_none must also be no_inline");
3114 Type landingpadResultTy;
3115 StringRef diagnosticMessage;
3116 bool isLandingpadTypeConsistent =
3118 const auto checkType = [&](
Type type, StringRef errorMessage) {
3119 if (!landingpadResultTy) {
3120 landingpadResultTy = type;
3123 if (landingpadResultTy != type) {
3124 diagnosticMessage = errorMessage;
3130 .Case<LandingpadOp>([&](
auto landingpad) {
3131 constexpr StringLiteral errorMessage =
3132 "'llvm.landingpad' should have a consistent result type "
3133 "inside a function";
3134 return checkType(landingpad.getType(), errorMessage);
3136 .Case<ResumeOp>([&](
auto resume) {
3137 constexpr StringLiteral errorMessage =
3138 "'llvm.resume' should have a consistent input type inside a "
3140 return checkType(resume.getValue().getType(), errorMessage);
3143 }).wasInterrupted();
3144 if (!isLandingpadTypeConsistent) {
3145 assert(!diagnosticMessage.empty() &&
3146 "Expecting a non-empty diagnostic message");
3158 LogicalResult LLVMFuncOp::verifyRegions() {
3162 unsigned numArguments = getFunctionType().getNumParams();
3163 Block &entryBlock = front();
3164 for (
unsigned i = 0; i < numArguments; ++i) {
3167 return emitOpError(
"entry block argument #")
3168 << i <<
" is not of LLVM type";
3174 Region *LLVMFuncOp::getCallableRegion() {
3203 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3204 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3205 return emitOpError()
3206 <<
"target extension type does not support zero-initializer";
3228 if (
auto vecType = dyn_cast<VectorType>(t)) {
3229 assert(!vecType.isScalable() &&
3230 "number of elements of a scalable vector type is unknown");
3231 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3233 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3234 return arrayType.getNumElements() *
3242 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3243 type = arrayType.getElementType();
3244 if (
auto vecType = dyn_cast<VectorType>(type))
3245 return vecType.getElementType();
3246 if (
auto tenType = dyn_cast<TensorType>(type))
3247 return tenType.getElementType();
3254 if (
auto vecType = dyn_cast<VectorType>(t)) {
3255 if (vecType.isScalable())
3259 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3267 LLVM::LLVMArrayType arrayType,
3268 ArrayAttr arrayAttr,
int dim) {
3269 if (arrayType.getNumElements() != arrayAttr.size())
3270 return op.emitOpError()
3271 <<
"array attribute size does not match array type size in "
3273 << dim <<
": " << arrayAttr.size() <<
" vs. "
3274 << arrayType.getNumElements();
3279 if (
auto subArrayType =
3280 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3282 if (elementsVerified.insert(elementAttr).second) {
3283 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3285 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3287 return op.emitOpError()
3288 <<
"nested attribute for sub-array in dimension " << dim
3289 <<
" at index " << idx
3290 <<
" must be a zero, or undef, or array attribute";
3304 auto structType = dyn_cast<LLVM::LLVMStructType>(arrayType.getElementType());
3306 return op.emitOpError() <<
"for array with an array attribute must have a "
3307 "struct element type";
3311 size_t numStructElements = structType.getBody().size();
3313 if (elementsVerified.insert(elementAttr).second) {
3314 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3316 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3318 return op.emitOpError()
3319 <<
"nested attribute for struct element at index " << idx
3320 <<
" must be a zero, or undef, or array attribute";
3321 if (subArrayAttr.size() != numStructElements)
3322 return op.emitOpError()
3323 <<
"nested array attribute size for struct element at index "
3324 << idx <<
" must match struct size: " << subArrayAttr.size()
3325 <<
" vs. " << numStructElements;
3333 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3334 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3335 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3336 !arrayType.getElementType().isInteger(8)) {
3337 return emitOpError() <<
"expected array type of "
3338 << sAttr.getValue().size()
3339 <<
" i8 elements for the string constant";
3343 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3344 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3346 return emitOpError() <<
"expected array attribute for struct type";
3349 if (arrayAttr.size() != elementTypes.size()) {
3350 return emitOpError() <<
"expected array attribute of size "
3351 << elementTypes.size();
3353 for (
auto [i, attr, type] :
llvm::enumerate(arrayAttr, elementTypes)) {
3355 return emitOpError() <<
"expected struct element types to be floating "
3356 "point type or integer type";
3358 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3359 return emitOpError() <<
"expected element of array attribute to be "
3360 "floating point or integer";
3362 if (cast<TypedAttr>(attr).
getType() != type)
3363 return emitOpError()
3364 <<
"struct element at index " << i <<
" is of wrong type";
3369 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3370 return emitOpError() <<
"does not support target extension type.";
3381 auto verifyFloatSemantics =
3382 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3383 Type constantElementType) -> LogicalResult {
3384 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3385 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3386 return emitOpError()
3387 <<
"attribute and type have different float semantics";
3391 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3392 if (isa<IntegerType>(constantElementType)) {
3393 if (!constantElementType.isInteger(floatWidth))
3394 return emitOpError() <<
"expected integer type of width " << floatWidth;
3402 if (isa<IntegerAttr>(getValue())) {
3403 if (!llvm::isa<IntegerType>(
getType()))
3404 return emitOpError() <<
"expected integer type";
3405 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3406 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3407 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3411 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3412 if (!splatElementsAttr)
3413 return emitOpError()
3414 <<
"scalable vector type requires a splat attribute";
3417 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3418 return emitOpError() <<
"expected vector or array type";
3421 int64_t attrNumElements = elementsAttr.getNumElements();
3423 return emitOpError()
3424 <<
"type and attribute have a different number of elements: "
3430 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3431 return verifyFloatSemantics(floatType.getFloatSemantics(), resultElmType);
3433 if (isa<IntegerType>(attrElmType) && !isa<IntegerType>(resultElmType)) {
3435 "expected integer element type for integer elements attribute");
3437 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3440 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3442 return emitOpError()
3443 <<
"expected array or struct type for array attribute";
3449 return emitOpError()
3450 <<
"only supports integer, float, string or elements attributes";
3456 bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3458 auto typedAttr = dyn_cast<TypedAttr>(value);
3465 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3470 if (isBuildableWith(value, type))
3471 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3476 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3484 AtomicOrdering ordering, StringRef syncscope,
3485 unsigned alignment,
bool isVolatile) {
3486 build(builder, state, val.
getType(), binOp, ptr, val, ordering,
3487 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3490 nullptr,
nullptr,
nullptr);
3494 auto valType = getVal().getType();
3495 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3496 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3497 getBinOp() == AtomicBinOp::fminimum ||
3498 getBinOp() == AtomicBinOp::fmaximum) {
3501 return emitOpError(
"expected LLVM IR fixed vector type");
3502 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3505 "expected LLVM IR floating point type for vector element");
3507 return emitOpError(
"expected LLVM IR floating point type");
3509 }
else if (getBinOp() == AtomicBinOp::xchg) {
3512 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3514 auto intType = llvm::dyn_cast<IntegerType>(valType);
3515 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3516 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3518 return emitOpError(
"expected LLVM IR integer type");
3521 if (
static_cast<unsigned>(getOrdering()) <
3522 static_cast<unsigned>(AtomicOrdering::monotonic))
3523 return emitOpError() <<
"expected at least '"
3524 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3537 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3542 AtomicOrdering successOrdering,
3543 AtomicOrdering failureOrdering, StringRef syncscope,
3544 unsigned alignment,
bool isWeak,
bool isVolatile) {
3546 successOrdering, failureOrdering,
3547 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3549 isVolatile,
nullptr,
3550 nullptr,
nullptr,
nullptr);
3554 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3556 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3557 auto valType = getVal().getType();
3560 return emitOpError(
"unexpected LLVM IR type");
3561 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3562 getFailureOrdering() < AtomicOrdering::monotonic)
3563 return emitOpError(
"ordering must be at least 'monotonic'");
3564 if (getFailureOrdering() == AtomicOrdering::release ||
3565 getFailureOrdering() == AtomicOrdering::acq_rel)
3566 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3575 AtomicOrdering ordering, StringRef syncscope) {
3576 build(builder, state, ordering,
3577 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3581 if (getOrdering() == AtomicOrdering::not_atomic ||
3582 getOrdering() == AtomicOrdering::unordered ||
3583 getOrdering() == AtomicOrdering::monotonic)
3584 return emitOpError(
"can be given only acquire, release, acq_rel, "
3585 "and seq_cst orderings");
3595 template <
class ExtOp>
3597 IntegerType inputType, outputType;
3600 return op.emitError(
3601 "input type is a vector but output type is an integer");
3604 return op.emitError(
"input and output vectors are of incompatible shape");
3607 inputType = cast<IntegerType>(
3608 cast<VectorType>(op.getArg().getType()).getElementType());
3609 outputType = cast<IntegerType>(
3610 cast<VectorType>(op.getResult().getType()).getElementType());
3614 inputType = cast<IntegerType>(op.getArg().getType());
3615 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3617 return op.emitError(
3618 "input type is an integer but output type is a vector");
3621 if (outputType.getWidth() <= inputType.getWidth())
3622 return op.emitError(
"integer width of the output type is smaller or "
3623 "equal to the integer width of the input type");
3631 LogicalResult
ZExtOp::verify() {
return verifyExtOp<ZExtOp>(*
this); }
3634 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3638 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3646 LogicalResult
SExtOp::verify() {
return verifyExtOp<SExtOp>(*
this); }
3653 template <
typename T>
3655 typename T::FoldAdaptor adaptor) {
3657 if (castOp.getArg().getType() == castOp.getType())
3658 return castOp.getArg();
3659 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3661 if (prev.getArg().getType() == castOp.getType())
3662 return prev.getArg();
3664 castOp.getArgMutable().set(prev.getArg());
3665 return Value{castOp};
3670 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3675 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3677 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3682 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3683 return emitOpError(
"can only cast pointers from and to pointers");
3688 auto isVector = llvm::IsaPred<VectorType>;
3692 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3693 return emitOpError(
"cannot cast pointer to vector of pointers");
3695 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3696 return emitOpError(
"cannot cast vector of pointers to pointer");
3700 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3701 return emitOpError(
"cannot cast pointers of different address spaces, "
3702 "use 'llvm.addrspacecast' instead");
3711 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3715 Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3723 adaptor.getDynamicIndices());
3727 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
3728 if (integer.getValue().isZero())
3735 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3742 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3743 gepArgs.emplace_back(val);
3745 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3751 gepArgs.emplace_back(integer.getInt());
3759 getDynamicIndicesMutable().assign(dynamicIndices);
3760 setRawConstantIndices(rawConstantIndices);
3761 return Value{*
this};
3767 Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3774 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3778 if (rhs.getValue().getZExtValue() >=
3779 getLhs().
getType().getIntOrFloatBitWidth())
3782 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3794 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3798 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3810 if (!getIntrin().starts_with(
"llvm."))
3811 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3819 build(builder, state,
TypeRange{}, intrin, args,
3820 FastmathFlagsAttr{},
3827 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3828 build(builder, state,
TypeRange{}, intrin, args,
3835 mlir::Type resultType, mlir::StringAttr intrin,
3837 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
3845 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3846 build(builder, state, resultTypes, intrin, args, fastMathFlags,
3853 StringAttr intrinAttr;
3857 ArrayAttr opBundleTags;
3871 return mlir::failure();
3874 return mlir::failure();
3879 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
3880 result &&
failed(*result))
3882 if (opBundleTags && !opBundleTags.empty())
3884 CallIntrinsicOp::getOpBundleTagsAttrName(result.
name).getValue(),
3888 return mlir::failure();
3893 operands, argAttrs, resultAttrs))
3896 parser.
getBuilder(), result, argAttrs, resultAttrs,
3897 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
3900 opBundleOperandTypes,
3901 getOpBundleSizesAttrName(result.
name)))
3904 int32_t numOpBundleOperands = 0;
3905 for (
const auto &operands : opBundleOperands)
3906 numOpBundleOperands += operands.size();
3909 CallIntrinsicOp::getOperandSegmentSizeAttr(),
3911 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
3913 return mlir::success();
3921 p <<
"(" << args <<
")";
3924 if (!getOpBundleOperands().empty()) {
3927 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
3931 {getOperandSegmentSizesAttrName(),
3932 getOpBundleSizesAttrName(), getIntrinAttrName(),
3933 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
3934 getResAttrsAttrName()});
3940 p, args.
getTypes(), getArgAttrsAttr(),
3941 false, getResultTypes(), getResAttrsAttr());
3951 return emitOpError(
"must appear at the module level");
3962 return emitOpError(
"must appear at the module level");
3964 if (!isa<ModuleFlagAttr>(flag))
3965 return emitOpError(
"expected a module flag attribute");
3973 void InlineAsmOp::getEffects(
3976 if (getHasSideEffects()) {
3989 getBlockAddr().getFunction());
3990 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
3993 return emitOpError(
"must reference a function defined by 'llvm.func'");
4003 BlockTagOp BlockAddressOp::getBlockTagOp() {
4009 BlockTagOp blockTagOp =
nullptr;
4010 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4011 if (labelOp.getTag() == getBlockAddr().getTag()) {
4012 blockTagOp = labelOp;
4021 if (!getBlockTagOp())
4023 "expects an existing block label target in the referenced function");
4030 OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4037 assert(index < getNumSuccessors() &&
"invalid successor index");
4049 rangeSegments.push_back(range.size());
4063 Block *destination = nullptr;
4064 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4065 SmallVector<Type> operandTypes;
4067 if (parser.parseSuccessor(destination).failed())
4070 if (succeeded(parser.parseOptionalLParen())) {
4071 if (failed(parser.parseOperandList(
4072 operands, OpAsmParser::Delimiter::None)) ||
4073 failed(parser.parseColonTypeList(operandTypes)) ||
4074 failed(parser.parseRParen()))
4077 succOperandBlocks.push_back(destination);
4078 succOperands.emplace_back(operands);
4079 succOperandsTypes.emplace_back(operandTypes);
4082 "successor blocks")))
4093 llvm::zip(succs, succOperands),
4099 if (!succOperands.empty())
4109 auto operandType = getOperand().getType();
4110 auto resultType = getResult().getType();
4111 auto resultStructType =
4112 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4113 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4114 resultStructType.getBody()[0] != operandType ||
4115 resultStructType.getBody()[1] != operandType) {
4116 return emitOpError(
"expected result type to be an homogeneous struct with "
4117 "two elements matching the operand type, but got ")
4129 return build(builder, state, cond, {},
4141 return build(builder, state, cond,
"align",
ValueRange{ptr, align});
4147 return build(builder, state, cond,
"separate_storage",
4158 auto ptrsVectorType = getPtrs().getType();
4159 Type expectedPtrsVectorType =
4164 if (ptrsVectorType != expectedPtrsVectorType)
4165 return emitOpError(
"expected operand #1 type to be ")
4166 << expectedPtrsVectorType;
4175 auto ptrsVectorType = getPtrs().getType();
4176 Type expectedPtrsVectorType =
4181 if (ptrsVectorType != expectedPtrsVectorType)
4182 return emitOpError(
"expected operand #2 type to be ")
4183 << expectedPtrsVectorType;
4196 build(builder, state, resTys, ptr, mask, passthru, argAttrs,
4204 void LLVM::masked_compressstore::build(
OpBuilder &builder,
4207 ArrayAttr argAttrs =
4209 build(builder, state, value, ptr, mask, argAttrs,
4218 if (!getTailCallKindAttr())
4221 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4223 "tail call kind 'musttail' is not supported by this operation");
4232 void LLVMDialect::initialize() {
4233 registerAttributes();
4236 addTypes<LLVMVoidType,
4239 LLVMMetadataType>();
4245 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4249 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4254 allowUnknownOperations();
4255 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4259 #define GET_OP_CLASSES
4260 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4262 #define GET_OP_CLASSES
4263 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4265 LogicalResult LLVMDialect::verifyDataLayoutString(
4269 if (maybeDataLayout)
4272 std::string message;
4273 llvm::raw_string_ostream messageStream(message);
4274 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4275 reportError(
"invalid data layout descriptor: " + message);
4280 LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4286 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4288 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4289 return verifyDataLayoutString(
4290 stringAttr.getValue(),
4291 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4294 << LLVM::LLVMDialect::getDataLayoutAttrName()
4295 <<
"' to be a string attributes";
4298 LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4306 StringAttr name = paramAttr.
getName();
4308 auto checkUnitAttrType = [&]() -> LogicalResult {
4309 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4310 return op->
emitError() << name <<
" should be a unit attribute";
4313 auto checkTypeAttrType = [&]() -> LogicalResult {
4314 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4315 return op->
emitError() << name <<
" should be a type attribute";
4318 auto checkIntegerAttrType = [&]() -> LogicalResult {
4319 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4320 return op->
emitError() << name <<
" should be an integer attribute";
4323 auto checkPointerType = [&]() -> LogicalResult {
4324 if (!llvm::isa<LLVMPointerType>(paramType))
4326 << name <<
" attribute attached to non-pointer LLVM type";
4329 auto checkIntegerType = [&]() -> LogicalResult {
4330 if (!llvm::isa<IntegerType>(paramType))
4332 << name <<
" attribute attached to non-integer LLVM type";
4335 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4336 if (
failed(checkPointerType()))
4343 if (name == LLVMDialect::getNoAliasAttrName() ||
4344 name == LLVMDialect::getReadonlyAttrName() ||
4345 name == LLVMDialect::getReadnoneAttrName() ||
4346 name == LLVMDialect::getWriteOnlyAttrName() ||
4347 name == LLVMDialect::getNestAttrName() ||
4348 name == LLVMDialect::getNoCaptureAttrName() ||
4349 name == LLVMDialect::getNoFreeAttrName() ||
4350 name == LLVMDialect::getNonNullAttrName()) {
4351 if (
failed(checkUnitAttrType()))
4353 if (verifyValueType &&
failed(checkPointerType()))
4359 if (name == LLVMDialect::getStructRetAttrName() ||
4360 name == LLVMDialect::getByValAttrName() ||
4361 name == LLVMDialect::getByRefAttrName() ||
4362 name == LLVMDialect::getElementTypeAttrName() ||
4363 name == LLVMDialect::getInAllocaAttrName() ||
4364 name == LLVMDialect::getPreallocatedAttrName()) {
4365 if (
failed(checkTypeAttrType()))
4367 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4373 if (name == LLVMDialect::getSExtAttrName() ||
4374 name == LLVMDialect::getZExtAttrName()) {
4375 if (
failed(checkUnitAttrType()))
4377 if (verifyValueType &&
failed(checkIntegerType()))
4383 if (name == LLVMDialect::getAlignAttrName() ||
4384 name == LLVMDialect::getDereferenceableAttrName() ||
4385 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4386 if (
failed(checkIntegerAttrType()))
4388 if (verifyValueType &&
failed(checkPointerType()))
4394 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4395 if (
failed(checkIntegerAttrType()))
4401 if (name == LLVMDialect::getNoUndefAttrName() ||
4402 name == LLVMDialect::getInRegAttrName() ||
4403 name == LLVMDialect::getReturnedAttrName())
4404 return checkUnitAttrType();
4410 LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4414 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4417 Type argType = funcOp.getArgumentTypes()[argIdx];
4419 return verifyParameterAttribute(op, argType, argAttr);
4422 LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4426 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4429 Type resType = funcOp.getResultTypes()[resIdx];
4433 if (llvm::isa<LLVMVoidType>(resType))
4434 return op->
emitError() <<
"cannot attach result attributes to functions "
4435 "with a void return";
4439 auto name = resAttr.
getName();
4440 if (name == LLVMDialect::getAllocAlignAttrName() ||
4441 name == LLVMDialect::getAllocatedPointerAttrName() ||
4442 name == LLVMDialect::getByValAttrName() ||
4443 name == LLVMDialect::getByRefAttrName() ||
4444 name == LLVMDialect::getInAllocaAttrName() ||
4445 name == LLVMDialect::getNestAttrName() ||
4446 name == LLVMDialect::getNoCaptureAttrName() ||
4447 name == LLVMDialect::getNoFreeAttrName() ||
4448 name == LLVMDialect::getPreallocatedAttrName() ||
4449 name == LLVMDialect::getReadnoneAttrName() ||
4450 name == LLVMDialect::getReadonlyAttrName() ||
4451 name == LLVMDialect::getReturnedAttrName() ||
4452 name == LLVMDialect::getStackAlignmentAttrName() ||
4453 name == LLVMDialect::getStructRetAttrName() ||
4454 name == LLVMDialect::getWriteOnlyAttrName())
4455 return op->
emitError() << name <<
" is not a valid result attribute";
4456 return verifyParameterAttribute(op, resType, resAttr);
4464 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4465 if (isa<LLVM::LLVMPointerType>(type))
4466 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4467 if (isa<LLVM::UndefAttr>(value))
4468 return LLVM::UndefOp::create(builder, loc, type);
4469 if (isa<LLVM::PoisonAttr>(value))
4470 return LLVM::PoisonOp::create(builder, loc, type);
4471 if (isa<LLVM::ZeroAttr>(value))
4472 return LLVM::ZeroOp::create(builder, loc, type);
4474 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4482 StringRef name, StringRef value,
4483 LLVM::Linkage linkage) {
4486 "expected builder to point to a block constrained in an op");
4489 assert(module &&
"builder points to an op outside of a module");
4495 auto global = LLVM::GlobalOp::create(
4496 moduleBuilder, loc, type,
true, linkage, name,
4502 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4503 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4516 assert(module &&
"unexpected operation outside of a module");
static OperandRange getSuccessorOperands(Block *block, unsigned successorIndex)
Return the operand range used to transfer operands from block to its successor with the given index.
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
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 int parseOptionalKeywordAlternative(OpAsmParser &parser, ArrayRef< StringRef > keywords)
static ArrayAttr getLLVMAlignParamForCompressExpand(OpBuilder &builder, bool isExpandLoad, uint64_t alignment=1)
static LogicalResult verifyAtomicMemOp(OpTy memOp, Type valueType, ArrayRef< AtomicOrdering > unsupportedOrderings)
Verifies the attributes and the type of atomic memory access operations.
static RetTy parseOptionalLLVMKeyword(OpAsmParser &parser, EnumTy defaultValue)
Parse an enum from the keyword, or default to the provided default value.
static LogicalResult checkGlobalXtorData(Operation *op, ArrayAttr data)
static ParseResult parseGEPIndices(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &indices, DenseI32ArrayAttr &rawConstantIndices)
static LogicalResult verifyOperandBundles(OpType &op)
static ParseResult parseCmpOp(OpAsmParser &parser, OperationState &result)
static void printOneOpBundle(OpAsmPrinter &p, OperandRange operands, TypeRange operandTypes, StringRef tag)
static LogicalResult verifyComdat(Operation *op, std::optional< SymbolRefAttr > attr)
static LLVMFunctionType getLLVMFuncType(MLIRContext *context, TypeRange results, ValueRange args)
Constructs a LLVMFunctionType from MLIR results and args.
static void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type flagType, DenseIntElementsAttr caseValues, SuccessorRange caseDestinations, OperandRangeRange caseOperands, const TypeRangeRange &caseOperandTypes)
static ParseResult resolveOpBundleOperands(OpAsmParser &parser, SMLoc loc, OperationState &state, ArrayRef< SmallVector< OpAsmParser::UnresolvedOperand >> opBundleOperands, ArrayRef< SmallVector< Type >> opBundleOperandTypes, StringAttr opBundleSizesAttrName)
static LogicalResult verifyCallOpVarCalleeType(OpTy callOp)
Verify that the parameter and return types of the variadic callee type match the callOp argument and ...
static ParseResult parseOptionalCallFuncPtr(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operands)
Parses an optional function pointer operand before the call argument list for indirect calls,...
static bool isZeroAttribute(Attribute value)
static void printGEPIndices(OpAsmPrinter &printer, LLVM::GEPOp gepOp, OperandRange indices, DenseI32ArrayAttr rawConstantIndices)
static LLVMStructType getValAndBoolStructType(Type valType)
Returns an LLVM struct type that contains a value type and a boolean type.
static void printOpBundles(OpAsmPrinter &p, Operation *op, OperandRangeRange opBundleOperands, TypeRangeRange opBundleOperandTypes, std::optional< ArrayAttr > opBundleTags)
static void printShuffleType(AsmPrinter &printer, Operation *op, Type v1Type, Type resType, DenseI32ArrayAttr mask)
Nothing to do when the result type is inferred.
static LogicalResult verifyBlockTags(LLVMFuncOp funcOp)
static Type buildLLVMFunctionType(OpAsmParser &parser, SMLoc loc, ArrayRef< Type > inputs, ArrayRef< Type > outputs, function_interface_impl::VariadicFlag variadicFlag)
static auto processFMFAttr(ArrayRef< NamedAttribute > attrs)
static std::optional< ParseResult > parseOpBundles(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand >> &opBundleOperands, SmallVector< SmallVector< Type >> &opBundleOperandTypes, ArrayAttr &opBundleTags)
static ParseResult parseSwitchOpCases(OpAsmParser &parser, Type flagType, DenseIntElementsAttr &caseValues, SmallVectorImpl< Block * > &caseDestinations, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand >> &caseOperands, SmallVectorImpl< SmallVector< Type >> &caseOperandTypes)
<cases> ::= [ (case (, case )* )? ] <case> ::= integer : bb-id (( ssa-use-and-type-list ))?
static TypeAttr getCallOpVarCalleeType(LLVMFunctionType calleeType)
Gets the variadic callee type for a LLVMFunctionType.
static Type getInsertExtractValueElementType(function_ref< InFlightDiagnostic(StringRef)> emitError, Type containerType, ArrayRef< int64_t > position)
Extract the type at position in the LLVM IR aggregate type containerType.
static Type getElementType(Type type)
Determine the element type of type.
static ParseResult parseOneOpBundle(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand >> &opBundleOperands, SmallVector< SmallVector< Type >> &opBundleOperandTypes, SmallVector< Attribute > &opBundleTags)
static ParseResult parseIndirectBrOpSucessors(OpAsmParser &parser, Type &flagType, SmallVectorImpl< Block * > &succOperandBlocks, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand >> &succOperands, SmallVectorImpl< SmallVector< Type >> &succOperandsTypes)
static void printIndirectBrOpSucessors(OpAsmPrinter &p, IndirectBrOp op, Type flagType, SuccessorRange succs, OperandRangeRange succOperands, const TypeRangeRange &succOperandsTypes)
static void printLLVMLinkage(OpAsmPrinter &p, Operation *, LinkageAttr val)
static LogicalResult verifyStructArrayConstant(LLVM::ConstantOp op, LLVM::LLVMArrayType arrayType, ArrayAttr arrayAttr, int dim)
Verifies the constant array represented by arrayAttr matches the provided arrayType.
static ParseResult parseCallTypeAndResolveOperands(OpAsmParser &parser, OperationState &result, bool isDirect, ArrayRef< OpAsmParser::UnresolvedOperand > operands, SmallVectorImpl< DictionaryAttr > &argAttrs, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses the type of a call operation and resolves the operands if the parsing succeeds.
static LogicalResult verifySymbolAttrUse(FlatSymbolRefAttr symbol, Operation *op, SymbolTableCollection &symbolTable)
Verifies symbol's use in op to ensure the symbol is a valid and fully defined llvm....
static Type extractVectorElementType(Type type)
Returns the elemental type of any LLVM-compatible vector type or self.
static bool hasScalableVectorType(Type t)
Check if the given type is a scalable vector type or a vector/array type that contains a nested scala...
static OpFoldResult foldChainableCast(T castOp, typename T::FoldAdaptor adaptor)
Folds a cast op that can be chained.
static void destructureIndices(Type currType, ArrayRef< GEPArg > indices, SmallVectorImpl< int32_t > &rawConstantIndices, SmallVectorImpl< Value > &dynamicIndices)
Destructures the 'indices' parameter into 'rawConstantIndices' and 'dynamicIndices',...
static ParseResult parseCommonGlobalAndAlias(OpAsmParser &parser, OperationState &result)
Parse common attributes that might show up in the same order in both GlobalOp and AliasOp.
static SmallVector< Type, 1 > getCallOpResultTypes(LLVMFunctionType calleeType)
Gets the MLIR Op-like result types of a LLVMFunctionType.
static Type getI1SameShape(Type type)
Returns a boolean type that has the same shape as type.
static void printCommonGlobalAndAlias(OpAsmPrinter &p, OpType op)
static ParseResult parseLLVMLinkage(OpAsmParser &p, LinkageAttr &val)
static Attribute getBoolAttribute(Type type, MLIRContext *ctx, bool value)
Returns a scalar or vector boolean attribute of the given type.
static LogicalResult verifyCallOpDebugInfo(CallOp callOp, LLVMFuncOp callee)
Verify that an inlinable callsite of a debug-info-bearing function in a debug-info-bearing function h...
static ParseResult parseShuffleType(AsmParser &parser, Type v1Type, Type &resType, DenseI32ArrayAttr mask)
Build the result type of a shuffle vector operation.
static LogicalResult verifyExtOp(ExtOp op)
Verifies that the given extension operation operates on consistent scalars or vectors,...
static constexpr const char kElemTypeAttrName[]
static ParseResult parseInsertExtractValueElementType(AsmParser &parser, Type &valueType, Type containerType, DenseI64ArrayAttr position)
Infer the value type from the container type and position.
static LogicalResult verifyStructIndices(Type baseGEPType, unsigned indexPos, GEPIndicesAdaptor< ValueRange > indices, function_ref< InFlightDiagnostic()> emitOpError)
For the given indices, check if they comply with baseGEPType, especially check against LLVMStructType...
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
static void printInsertExtractValueElementType(AsmPrinter &printer, Operation *op, Type valueType, Type containerType, DenseI64ArrayAttr position)
Nothing to print for an inferred type.
#define REGISTER_ENUM_TYPE(Ty)
static std::string diag(const llvm::Value &value)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
static VectorType getVectorType(Type scalarTy, const VectorizationStrategy *strategy)
Returns the vector type resulting from applying the provided vectorization strategy on the scalar typ...
This base class exposes generic asm parser hooks, usable across the various derived parsers.
ParseResult parseSymbolName(StringAttr &result)
Parse an -identifier and store it (without the '@' symbol) in a string attribute.
@ Paren
Parens surrounding zero or more operands.
@ None
Zero or more operands with no delimiters.
@ Square
Square brackets surrounding zero or more operands.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseColonTypeList(SmallVectorImpl< Type > &result)=0
Parse a colon followed by a type list, which must have at least one type.
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.
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseOptionalColonTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional colon followed by a type list, which if present must have at least one type.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
virtual ParseResult parseCustomAttributeWithFallback(Attribute &result, Type type, function_ref< ParseResult(Attribute &result, Type type)> parseAttribute)=0
Parse a custom attribute with the provided callback, unless the next token is #, in which case the ge...
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
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.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
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 printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
virtual void printAttribute(Attribute attr)
Attributes are known-constant values of operations.
This class provides an abstraction over the different types of ranges over Blocks.
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.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
static BoolAttr get(MLIRContext *context, bool value)
This class is a general helper class for creating context-global objects like types,...
IntegerAttr getI32IntegerAttr(int32_t value)
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
IntegerAttr getI64IntegerAttr(int64_t value)
Ty getType(Args &&...args)
Get or construct an instance of the type Ty with provided arguments.
StringAttr getStringAttr(const Twine &bytes)
TypedAttr getZeroAttr(Type type)
MLIRContext * getContext() const
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
NamedAttribute getNamedAttr(StringRef name, Attribute val)
ArrayAttr getStrArrayAttr(ArrayRef< StringRef > values)
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
The main mechanism for performing data layout queries.
static DataLayout closest(Operation *op)
Returns the layout of the closest parent operation carrying layout info.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
An attribute that represents a reference to a dense vector or tensor object.
std::enable_if_t<!std::is_base_of< Attribute, T >::value||std::is_same< Attribute, T >::value, T > getSplatValue() const
Return the splat value for this attribute.
auto getValues() const
Return the held element values as a range of the given type.
Type getElementType() const
Return the element type of this DenseElementsAttr.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
An attribute that represents a reference to a dense integer vector or tensor object.
static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg)
Get an instance of a DenseIntElementsAttr with the given arguments.
A symbol reference with a reference path containing a single element.
StringRef getValue() const
Returns the name of the held symbol reference.
StringAttr getAttr() const
Returns the name of the held symbol reference as a StringAttr.
This class represents a fused location whose metadata is known to be an instance of the given type.
This class represents a diagnostic that is inflight and set to be reported.
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
Class used for building a 'llvm.getelementptr'.
Class used for convenient access and iteration over GEP indices.
bool isDynamicIndex(size_t index) const
Returns whether the GEP index at the given position is a dynamic index.
size_t size() const
Returns the amount of indices of the GEPOp.
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.
This class provides a mutable adaptor for a range of operands.
std::optional< NamedAttribute > getNamed(StringRef name) const
Return the specified named attribute if present, std::nullopt otherwise.
Attribute erase(StringAttr name)
Erase the attribute with the given name from the list.
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
NamedAttribute represents a combination of a name and an Attribute value.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
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 parseSuccessor(Block *&dest)=0
Parse a single operation successor.
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 parseOptionalOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single operand if present.
virtual ParseResult parseSuccessorAndUseList(Block *&dest, SmallVectorImpl< Value > &operands)=0
Parse a single operation successor and its operand list.
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 ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printNewline()=0
Print a newline and indent the printer to the start of the current operation.
virtual void printSuccessorAndUseList(Block *successor, ValueRange succOperands)=0
Print the successor and its operands.
void printOperands(const ContainerType &container)
Print a comma separated list of operands.
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.
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
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.
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
This class represents a single result from folding an operation.
This class provides the API for ops that are known to be isolated from above.
A trait used to provide symbol table functionalities to a region operation.
This class represents a contiguous range of operand ranges, e.g.
This class implements the operand iterators for the Operation class.
type_range getTypes() const
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class implements Optional functionality for ParseResult.
ParseResult value() const
Access the internal ParseResult value.
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.
iterator_range< OpIterator > getOps()
This class represents a specific instance of an effect.
static DerivedEffect * get()
Returns a unique instance for the derived effect class.
This class models how operands are forwarded to block arguments in control flow.
This class implements the successor iterators for Block.
This class represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
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,...
This class provides an abstraction for a range of TypeRange.
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...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
bool isSignlessIntOrIndexOrFloat() const
Return true if this is a signless integer, index, or float type.
This class provides an abstraction over the different types of ranges over Values.
type_range getTypes() const
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.
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
bool wasInterrupted() const
Returns true if the walk was interrupted.
static WalkResult interrupt()
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
Builder from ArrayRef<T>.
ArrayRef< T > asArrayRef() const
A named class for passing around the variadic flag.
void addBytecodeInterface(LLVMDialect *dialect)
Add the interfaces necessary for encoding the LLVM dialect components in bytecode.
Value createGlobalString(Location loc, OpBuilder &builder, StringRef name, StringRef value, Linkage linkage)
Create an LLVM global containing the string "value" at the module containing surrounding the insertio...
Operation * parentLLVMModule(Operation *op)
Lookup parent Module satisfying LLVM conditions on the Module Operation.
Type getVectorType(Type elementType, unsigned numElements, bool isScalable=false)
Creates an LLVM dialect-compatible vector type with the given element type and length.
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
bool isCompatibleOuterType(Type type)
Returns true if the given outer type is compatible with the LLVM dialect without checking its potenti...
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
constexpr int kGEPConstantBitWidth
Bit-width of a 'GEPConstantIndex' within GEPArg.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
bool isTypeCompatibleWithAtomicOp(Type type, const DataLayout &dataLayout)
Returns true if the given type is supported by atomic operations.
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
void printFunctionSignature(OpAsmPrinter &p, TypeRange argTypes, ArrayAttr argAttrs, bool isVariadic, TypeRange resultTypes, ArrayAttr resultAttrs, Region *body=nullptr, bool printEmptyResult=true)
Print a function signature for a call or callable operation.
ParseResult parseFunctionSignature(OpAsmParser &parser, SmallVectorImpl< Type > &argTypes, SmallVectorImpl< DictionaryAttr > &argAttrs, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs, bool mustParseEmptyResult=true)
Parses a function signature using parser.
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)
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)
Value constantIndex(OpBuilder &builder, Location loc, int64_t i)
Generates a constant of index type.
Visibility
This enum describes C++ inheritance visibility.
std::string stringify(T &&t)
Generically convert a value to a std::string.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
detail::constant_int_value_binder m_ConstantInt(IntegerAttr::ValueType *bind_value)
Matches a constant holding a scalar/vector/tensor integer (splat) and writes the integer value to bin...
const FrozenRewritePatternSet GreedyRewriteConfig bool * changed
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...
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
A callable is either a symbol, or an SSA value, that is referenced by a call-like operation.
This is the representation of an operand reference.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
T & getOrAddProperties()
Get (or create) a properties of the provided type to be set on the operation on creation.
SmallVector< Value, 4 > operands
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addSuccessors(Block *successor)
Adds a successor to the operation sate. successor must not be null.
void addTypes(ArrayRef< Type > newTypes)
Region * addRegion()
Create a region that should be attached to the operation.