27 #include "llvm/ADT/APFloat.h"
28 #include "llvm/ADT/TypeSwitch.h"
29 #include "llvm/IR/DataLayout.h"
30 #include "llvm/Support/Error.h"
37 using mlir::LLVM::cconv::getMaxEnumValForCConv;
38 using mlir::LLVM::linkage::getMaxEnumValForLinkage;
39 using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
41 #include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
52 if (attr.
getName() ==
"fastmathFlags") {
54 FastmathFlagsAttr::get(attr.getValue().getContext(), {});
72 << name <<
"' does not reference a valid LLVM function";
73 if (func.isExternal())
74 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
100 template <
typename Ty>
101 struct EnumTraits {};
103 #define REGISTER_ENUM_TYPE(Ty) \
105 struct EnumTraits<Ty> { \
106 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
107 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
120 template <
typename EnumTy,
typename RetTy = EnumTy>
122 EnumTy defaultValue) {
124 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
129 return static_cast<RetTy
>(defaultValue);
130 return static_cast<RetTy
>(index);
134 p << stringifyLinkage(val.getLinkage());
140 parseOptionalLLVMKeyword<LLVM::Linkage>(p, LLVM::Linkage::External));
146 uint64_t alignment = 1) {
152 if (alignment == 1) {
159 builder.
getNamedAttr(LLVMDialect::getAlignAttrName(), alignmentAttr);
169 int pos = isExpandLoad ? 0 : 1;
171 {alignDictAttr, emptyDictAttr, emptyDictAttr})
173 {emptyDictAttr, alignDictAttr, emptyDictAttr});
185 if (!operands.empty()) {
188 llvm::interleaveComma(operandTypes, p);
197 std::optional<ArrayAttr> opBundleTags) {
198 if (opBundleOperands.empty())
200 assert(opBundleTags &&
"expect operand bundle tags");
203 llvm::interleaveComma(
204 llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
206 auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
224 return p.
emitError(currentParserLoc,
"expect operand bundle tag");
235 opBundleOperands.push_back(std::move(operands));
236 opBundleOperandTypes.push_back(std::move(types));
246 ArrayAttr &opBundleTags) {
254 auto bundleParser = [&] {
274 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
275 <<
", " << getOperand(1);
277 p <<
" : " << getLhs().getType();
281 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
282 <<
", " << getOperand(1);
284 p <<
" : " << getLhs().getType();
291 template <
typename CmpPredicateType>
293 StringAttr predicateAttr;
296 SMLoc predicateLoc, trailingTypeLoc;
308 int64_t predicateValue = 0;
309 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
310 std::optional<ICmpPredicate> predicate =
311 symbolizeICmpPredicate(predicateAttr.getValue());
314 <<
"'" << predicateAttr.getValue()
315 <<
"' is an incorrect value of the 'predicate' attribute";
316 predicateValue =
static_cast<int64_t
>(*predicate);
318 std::optional<FCmpPredicate> predicate =
319 symbolizeFCmpPredicate(predicateAttr.getValue());
322 <<
"'" << predicateAttr.getValue()
323 <<
"' is an incorrect value of the 'predicate' attribute";
324 predicateValue =
static_cast<int64_t
>(*predicate);
334 "expected LLVM dialect-compatible type");
340 return parseCmpOp<ICmpPredicate>(parser, result);
344 return parseCmpOp<FCmpPredicate>(parser, result);
350 ShapedType shapedType = dyn_cast<ShapedType>(type);
357 if (getPredicate() != ICmpPredicate::eq &&
358 getPredicate() != ICmpPredicate::ne)
362 if (getLhs() == getRhs())
364 getPredicate() == ICmpPredicate::eq);
367 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
369 getPredicate() == ICmpPredicate::ne);
372 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
373 Value lhs = getLhs();
374 Value rhs = getRhs();
375 getLhsMutable().assign(rhs);
376 getRhsMutable().assign(lhs);
394 p <<
' ' << getArraySize() <<
" x " << getElemType();
395 if (getAlignment() && *getAlignment() != 0)
397 {kElemTypeAttrName, getInallocaAttrName()});
401 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
402 p <<
" : " << funcTy;
410 SMLoc trailingTypeLoc;
422 std::optional<NamedAttribute> alignmentAttr =
424 if (alignmentAttr.has_value()) {
425 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
428 "expected integer alignment");
429 if (alignmentInt.getValue().isZero())
434 auto funcType = llvm::dyn_cast<FunctionType>(type);
435 if (!funcType || funcType.getNumInputs() != 1 ||
436 funcType.getNumResults() != 1)
439 "expected trailing function type with one argument and one result");
444 Type resultType = funcType.getResult(0);
445 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
448 result.
addTypes({funcType.getResult(0)});
454 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
455 targetExtType && !targetExtType.supportsMemOps())
457 <<
"this target extension type cannot be used in alloca";
467 assert(index == 0 &&
"invalid successor index");
476 assert(index < getNumSuccessors() &&
"invalid successor index");
478 : getFalseDestOperandsMutable());
484 std::optional<std::pair<uint32_t, uint32_t>> weights) {
489 static_cast<int32_t
>(weights->second)});
491 build(builder, result, condition, trueOperands, falseOperands, weightsAttr,
492 {}, trueDest, falseDest);
506 if (!branchWeights.empty())
509 build(builder, result, value, defaultOperands, caseOperands, caseValues,
510 weightsAttr, defaultDestination, caseDestinations);
519 if (!caseValues.empty()) {
521 static_cast<int64_t
>(caseValues.size()), value.
getType());
525 build(builder, result, value, defaultDestination, defaultOperands,
526 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
535 if (!caseValues.empty()) {
537 static_cast<int64_t
>(caseValues.size()), value.
getType());
541 build(builder, result, value, defaultDestination, defaultOperands,
542 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
558 auto parseCase = [&]() {
562 values.push_back(APInt(bitWidth, value,
true));
575 caseDestinations.push_back(destination);
576 caseOperands.emplace_back(operands);
577 caseOperandTypes.emplace_back(operandTypes);
583 ShapedType caseValueType =
603 llvm::zip(caseValues, caseDestinations),
619 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
621 getCaseValues()->size() !=
622 static_cast<int64_t
>(getCaseDestinations().size())))
623 return emitOpError(
"expects number of case values to match number of "
624 "case destinations");
625 if (getCaseValues() &&
627 return emitError(
"expects case value type to match condition value type");
632 assert(index < getNumSuccessors() &&
"invalid successor index");
634 : getCaseOperandsMutable(index - 1));
641 constexpr int32_t GEPOp::kDynamicIndex;
645 getDynamicIndices());
650 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
651 return vectorType.getElementType();
663 for (
const GEPArg &iter : indices) {
668 bool requiresConst = !rawConstantIndices.empty() &&
669 isa_and_nonnull<LLVMStructType>(currType);
670 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
674 rawConstantIndices.push_back(intC.getSExtValue());
676 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
677 dynamicIndices.push_back(val);
680 rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
685 if (rawConstantIndices.size() == 1 || !currType)
689 .Case<VectorType, LLVMArrayType>([](
auto containerType) {
690 return containerType.getElementType();
692 .Case([&](LLVMStructType structType) ->
Type {
693 int64_t memberIndex = rawConstantIndices.back();
694 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
695 structType.getBody().size())
696 return structType.getBody()[memberIndex];
699 .Default(
Type(
nullptr));
705 GEPNoWrapFlags noWrapFlags,
724 GEPNoWrapFlags noWrapFlags,
726 build(builder, result, resultType, elementType, basePtr,
736 auto idxParser = [&]() -> ParseResult {
747 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
761 llvm::interleaveComma(
764 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
767 printer << cast<IntegerAttr>(cst).getInt();
777 if (indexPos >= indices.
size())
782 .Case<LLVMStructType>([&](LLVMStructType structType) -> LogicalResult {
783 auto attr = dyn_cast<IntegerAttr>(indices[indexPos]);
785 return emitOpError() <<
"expected index " << indexPos
786 <<
" indexing a struct to be constant";
788 int32_t gepIndex = attr.getInt();
791 static_cast<size_t>(gepIndex) >= elementTypes.size())
792 return emitOpError() <<
"index " << indexPos
793 <<
" indexing a struct is out of bounds";
798 indices, emitOpError);
800 .Case<VectorType, LLVMArrayType>(
801 [&](
auto containerType) -> LogicalResult {
803 indexPos + 1, indices, emitOpError);
805 .Default([&](
auto otherType) -> LogicalResult {
807 <<
"type " << otherType <<
" cannot be indexed (index #"
820 if (
static_cast<size_t>(
821 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
822 getDynamicIndices().size())
823 return emitOpError(
"expected as many dynamic indices as specified in '")
824 << getRawConstantIndicesAttrName().getValue() <<
"'";
826 if (getNoWrapFlags() == GEPNoWrapFlags::inboundsFlag)
827 return emitOpError(
"'inbounds_flag' cannot be used directly.");
830 [&] {
return emitOpError(); });
837 void LoadOp::getEffects(
846 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
847 getOrdering() != AtomicOrdering::unordered)) {
858 if (!isa<IntegerType, LLVMPointerType>(type))
863 if (bitWidth.isScalable())
866 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
870 template <
typename OpTy>
874 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
877 return memOp.emitOpError(
"unsupported type ")
878 << valueType <<
" for atomic access";
879 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
880 return memOp.emitOpError(
"unsupported ordering '")
881 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
882 if (!memOp.getAlignment())
883 return memOp.emitOpError(
"expected alignment for atomic access");
886 if (memOp.getSyncscope())
887 return memOp.emitOpError(
888 "expected syncscope to be null for non-atomic access");
893 Type valueType = getResult().getType();
895 {AtomicOrdering::release, AtomicOrdering::acq_rel});
899 Value addr,
unsigned alignment,
bool isVolatile,
900 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
901 AtomicOrdering ordering, StringRef syncscope) {
902 build(builder, state, type, addr,
904 isNonTemporal, isInvariant, isInvariantGroup, ordering,
905 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
916 void StoreOp::getEffects(
925 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
926 getOrdering() != AtomicOrdering::unordered)) {
933 Type valueType = getValue().getType();
935 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
939 Value addr,
unsigned alignment,
bool isVolatile,
940 bool isNonTemporal,
bool isInvariantGroup,
941 AtomicOrdering ordering, StringRef syncscope) {
942 build(builder, state, value, addr,
944 isNonTemporal, isInvariantGroup, ordering,
945 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
947 nullptr,
nullptr,
nullptr);
957 Type resultType = calleeType.getReturnType();
958 if (!isa<LLVM::LLVMVoidType>(resultType))
959 results.push_back(resultType);
965 return calleeType.isVarArg() ?
TypeAttr::get(calleeType) :
nullptr;
975 resultType = results.front();
982 build(builder, state, results, builder.
getStringAttr(callee), args);
992 assert(callee &&
"expected non-null callee in direct call builder");
993 build(builder, state, results,
994 nullptr, callee, args,
nullptr,
997 nullptr,
nullptr,
nullptr,
1007 LLVMFunctionType calleeType, StringRef callee,
1009 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1013 LLVMFunctionType calleeType, StringAttr callee,
1031 nullptr,
nullptr,
nullptr,
1037 LLVMFunctionType calleeType,
ValueRange args) {
1042 nullptr,
nullptr,
nullptr,
1043 nullptr,
nullptr,
nullptr,
1054 auto calleeType = func.getFunctionType();
1058 nullptr,
nullptr,
nullptr,
1059 nullptr,
nullptr,
nullptr,
1073 return getOperand(0);
1079 auto symRef = cast<SymbolRefAttr>(callee);
1080 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1083 return setOperand(0, cast<Value>(callee));
1087 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1092 getCalleeOperands().size());
1099 if (callee.isExternal())
1101 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1105 auto hasSubprogram = [](
Operation *op) {
1110 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1112 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1114 return callOp.emitError()
1115 <<
"inlinable function call in a function with a DISubprogram "
1116 "location must have a debug location";
1122 template <
typename OpTy>
1124 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1129 if (!varCalleeType->isVarArg())
1130 return callOp.emitOpError(
1131 "expected var_callee_type to be a variadic function type");
1135 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1136 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1137 << callOp.getArgOperands().size() <<
" parameters";
1140 for (
auto [paramType, operand] :
1141 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1142 if (paramType != operand.getType())
1143 return callOp.emitOpError()
1144 <<
"var_callee_type parameter type mismatch: " << paramType
1145 <<
" != " << operand.getType();
1148 if (!callOp.getNumResults()) {
1149 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1150 return callOp.emitOpError(
"expected var_callee_type to return void");
1152 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1153 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1154 << varCalleeType->getReturnType()
1155 <<
" != " << callOp.getResult().getType();
1160 template <
typename OpType>
1163 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1165 auto isStringAttr = [](
Attribute tagAttr) {
1166 return isa<StringAttr>(tagAttr);
1168 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1169 return op.emitError(
"operand bundle tag must be a StringAttr");
1171 size_t numOpBundles = opBundleOperands.size();
1172 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1173 if (numOpBundles != numOpBundleTags)
1174 return op.emitError(
"expected ")
1175 << numOpBundles <<
" operand bundle tags, but actually got "
1191 bool isIndirect =
false;
1197 if (!getNumOperands())
1199 "must have either a `callee` attribute or at least an operand");
1200 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1202 return emitOpError(
"indirect call expects a pointer as callee: ")
1203 << getOperand(0).getType();
1210 return emitOpError()
1212 <<
"' does not reference a symbol in the current scope";
1213 if (
auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1216 fnType = fn.getFunctionType();
1217 }
else if (
auto ifunc = dyn_cast<IFuncOp>(callee)) {
1218 fnType = ifunc.getIFuncType();
1220 return emitOpError()
1222 <<
"' does not reference a valid LLVM function or IFunc";
1226 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1228 return emitOpError(
"callee does not have a functional type: ") << fnType;
1230 if (funcType.isVarArg() && !getVarCalleeType())
1231 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1235 if (!funcType.isVarArg() &&
1236 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1237 return emitOpError() <<
"incorrect number of operands ("
1238 << (getCalleeOperands().size() - isIndirect)
1239 <<
") for callee (expecting: "
1240 << funcType.getNumParams() <<
")";
1242 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1243 return emitOpError() <<
"incorrect number of operands ("
1244 << (getCalleeOperands().size() - isIndirect)
1245 <<
") for varargs callee (expecting at least: "
1246 << funcType.getNumParams() <<
")";
1248 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1249 if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1250 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1251 << getOperand(i + isIndirect).getType()
1252 <<
" != " << funcType.getParamType(i);
1254 if (getNumResults() == 0 &&
1255 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1256 return emitOpError() <<
"expected function call to produce a value";
1258 if (getNumResults() != 0 &&
1259 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1260 return emitOpError()
1261 <<
"calling function with void result must not produce values";
1263 if (getNumResults() > 1)
1264 return emitOpError()
1265 <<
"expected LLVM function call to produce 0 or 1 result";
1267 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1268 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1269 <<
" != " << funcType.getReturnType();
1275 auto callee = getCallee();
1276 bool isDirect = callee.has_value();
1281 if (getCConv() != LLVM::CConv::C)
1282 p << stringifyCConv(getCConv()) <<
' ';
1285 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1294 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1295 p <<
'(' << args <<
')';
1298 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1299 p <<
" vararg(" << *varCalleeType <<
")";
1301 if (!getOpBundleOperands().empty()) {
1304 getOpBundleOperands().getTypes(), getOpBundleTags());
1308 {getCalleeAttrName(), getTailCallKindAttrName(),
1309 getVarCalleeTypeAttrName(), getCConvAttrName(),
1310 getOperandSegmentSizesAttrName(),
1311 getOpBundleSizesAttrName(),
1312 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1313 getResAttrsAttrName()});
1317 p << getOperand(0).getType() <<
", ";
1321 p, args.getTypes(), getArgAttrsAttr(),
1322 false, getResultTypes(), getResAttrsAttr());
1337 types.emplace_back();
1342 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1347 resTypes, resultAttrs)) {
1349 return parser.
emitError(trailingTypesLoc,
1350 "expected direct call to have 1 trailing types");
1351 return parser.
emitError(trailingTypesLoc,
1352 "expected trailing function type");
1355 if (resTypes.size() > 1)
1356 return parser.
emitError(trailingTypesLoc,
1357 "expected function with 0 or 1 result");
1358 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1359 return parser.
emitError(trailingTypesLoc,
1360 "expected a non-void result type");
1366 llvm::append_range(types, argTypes);
1370 if (resTypes.size() != 0)
1384 if (
failed(*parseResult))
1385 return *parseResult;
1386 operands.push_back(funcPtrOperand);
1395 StringAttr opBundleSizesAttrName) {
1396 unsigned opBundleIndex = 0;
1397 for (
const auto &[operands, types] :
1398 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1399 if (operands.size() != types.size())
1400 return parser.
emitError(loc,
"expected ")
1402 <<
" types for operand bundle operands for operand bundle #"
1403 << opBundleIndex <<
", but actually got " << types.size();
1409 opBundleSizes.reserve(opBundleOperands.size());
1410 for (
const auto &operands : opBundleOperands)
1411 opBundleSizes.push_back(operands.size());
1414 opBundleSizesAttrName,
1426 SymbolRefAttr funcAttr;
1427 TypeAttr varCalleeType;
1431 ArrayAttr opBundleTags;
1435 getCConvAttrName(result.
name),
1437 parseOptionalLLVMKeyword<CConv>(parser, LLVM::CConv::C)));
1440 getTailCallKindAttrName(result.
name),
1442 parseOptionalLLVMKeyword<TailCallKind>(
1448 bool isDirect = operands.empty();
1461 StringAttr varCalleeTypeAttrName =
1462 CallOp::getVarCalleeTypeAttrName(result.
name);
1474 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1475 result &&
failed(*result))
1477 if (opBundleTags && !opBundleTags.empty())
1478 result.
addAttribute(CallOp::getOpBundleTagsAttrName(result.
name).getValue(),
1488 argAttrs, resultAttrs))
1491 parser.
getBuilder(), result, argAttrs, resultAttrs,
1492 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
1494 opBundleOperandTypes,
1495 getOpBundleSizesAttrName(result.
name)))
1498 int32_t numOpBundleOperands = 0;
1499 for (
const auto &operands : opBundleOperands)
1500 numOpBundleOperands += operands.size();
1503 CallOp::getOperandSegmentSizeAttr(),
1505 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1509 LLVMFunctionType CallOp::getCalleeFunctionType() {
1510 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1511 return *varCalleeType;
1522 auto calleeType = func.getFunctionType();
1525 nullptr,
nullptr, normalOps, unwindOps,
1526 nullptr,
nullptr, {}, {}, normal, unwind);
1533 build(builder, state, tys,
1534 nullptr, callee, ops,
nullptr,
1535 nullptr, normalOps, unwindOps,
nullptr,
nullptr, {}, {},
1545 nullptr,
nullptr, normalOps, unwindOps,
1546 nullptr,
nullptr, {}, {}, normal, unwind);
1550 assert(index < getNumSuccessors() &&
"invalid successor index");
1552 : getUnwindDestOperandsMutable());
1560 return getOperand(0);
1566 auto symRef = cast<SymbolRefAttr>(callee);
1567 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1570 return setOperand(0, cast<Value>(callee));
1574 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1579 getCalleeOperands().size());
1586 Block *unwindDest = getUnwindDest();
1587 if (unwindDest->
empty())
1588 return emitError(
"must have at least one operation in unwind destination");
1591 if (!isa<LandingpadOp>(unwindDest->
front()))
1592 return emitError(
"first operation in unwind destination should be a "
1593 "llvm.landingpad operation");
1602 auto callee = getCallee();
1603 bool isDirect = callee.has_value();
1608 if (getCConv() != LLVM::CConv::C)
1609 p << stringifyCConv(getCConv()) <<
' ';
1617 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1624 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1625 p <<
" vararg(" << *varCalleeType <<
")";
1627 if (!getOpBundleOperands().empty()) {
1630 getOpBundleOperands().getTypes(), getOpBundleTags());
1634 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1635 getCConvAttrName(), getVarCalleeTypeAttrName(),
1636 getOpBundleSizesAttrName(),
1637 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1638 getResAttrsAttrName()});
1642 p << getOperand(0).getType() <<
", ";
1644 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1646 false, getResultTypes(), getResAttrsAttr());
1659 SymbolRefAttr funcAttr;
1660 TypeAttr varCalleeType;
1663 ArrayAttr opBundleTags;
1664 Block *normalDest, *unwindDest;
1670 getCConvAttrName(result.
name),
1672 parseOptionalLLVMKeyword<CConv>(parser, LLVM::CConv::C)));
1677 bool isDirect = operands.empty();
1693 StringAttr varCalleeTypeAttrName =
1694 InvokeOp::getVarCalleeTypeAttrName(result.
name);
1706 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1707 result &&
failed(*result))
1709 if (opBundleTags && !opBundleTags.empty())
1711 InvokeOp::getOpBundleTagsAttrName(result.
name).getValue(),
1721 argAttrs, resultAttrs))
1724 parser.
getBuilder(), result, argAttrs, resultAttrs,
1725 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
1728 opBundleOperandTypes,
1729 getOpBundleSizesAttrName(result.
name)))
1736 int32_t numOpBundleOperands = 0;
1737 for (
const auto &operands : opBundleOperands)
1738 numOpBundleOperands += operands.size();
1741 InvokeOp::getOperandSegmentSizeAttr(),
1743 static_cast<int32_t>(normalOperands.size()),
1744 static_cast<int32_t>(unwindOperands.size()),
1745 numOpBundleOperands}));
1749 LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1750 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1751 return *varCalleeType;
1761 if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1762 if (!func.getPersonality())
1764 "llvm.landingpad needs to be in a function with a personality");
1770 if (!getCleanup() && getOperands().empty())
1771 return emitError(
"landingpad instruction expects at least one clause or "
1772 "cleanup attribute");
1774 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1775 value = getOperand(idx);
1776 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1783 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1786 <<
"global addresses expected as operand to "
1787 "bitcast used in clauses for landingpad";
1795 << idx <<
" is not a known constant - null, addressof, bitcast";
1802 p << (getCleanup() ?
" cleanup " :
" ");
1805 for (
auto value : getOperands()) {
1808 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1809 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1856 Type llvmType = containerType;
1858 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1866 for (int64_t idx : position) {
1867 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1868 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1869 emitError(
"position out of bounds: ") << idx;
1872 llvmType = arrayType.getElementType();
1873 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1875 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1876 emitError(
"position out of bounds: ") << idx;
1879 llvmType = structType.getBody()[idx];
1881 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1892 for (int64_t idx : position) {
1893 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1894 llvmType = structType.getBody()[idx];
1896 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1901 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1902 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
1904 newPos.append(getPosition().begin(), getPosition().end());
1905 setPosition(newPos);
1906 getContainerMutable().set(extractValueOp.getContainer());
1914 if (isa<SplatElementsAttr>(constval))
1916 if (getPosition().size() == 1)
1921 auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1924 bool switchedToInsertedValue =
false;
1925 while (insertValueOp) {
1927 auto extractPosSize = extractPos.size();
1928 auto insertPosSize = insertPos.size();
1931 if (extractPos == insertPos)
1932 return insertValueOp.getValue();
1946 if (extractPosSize > insertPosSize &&
1947 extractPos.take_front(insertPosSize) == insertPos) {
1948 insertValueOp = insertValueOp.getValue().getDefiningOp<InsertValueOp>();
1949 extractPos = extractPos.drop_front(insertPosSize);
1950 switchedToInsertedValue =
true;
1955 unsigned min =
std::min(extractPosSize, insertPosSize);
1967 if (extractPos.take_front(
min) == insertPos.take_front(
min))
1972 if (!switchedToInsertedValue) {
1975 getContainerMutable().assign(insertValueOp.getContainer());
1976 result = getResult();
1978 insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1984 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1990 if (getRes().
getType() != valueType)
1991 return emitOpError() <<
"Type mismatch: extracting from "
1992 << getContainer().getType() <<
" should produce "
1993 << valueType <<
" but this op returns "
1994 << getRes().getType();
2000 build(builder, state,
2015 [&](StringRef msg) {
2019 return success(!!valueType);
2029 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
2035 if (getValue().
getType() != valueType)
2036 return emitOpError() <<
"Type mismatch: cannot insert "
2037 << getValue().getType() <<
" into "
2038 << getContainer().getType();
2048 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2052 Type expectedType = parent.getFunctionType().getReturnType();
2053 if (llvm::isa<LLVMVoidType>(expectedType)) {
2057 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2061 if (llvm::isa<LLVMVoidType>(expectedType))
2064 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2067 if (expectedType != getArg().
getType()) {
2069 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2080 return dyn_cast_or_null<GlobalOp>(
2085 return dyn_cast_or_null<LLVMFuncOp>(
2090 return dyn_cast_or_null<AliasOp>(
2095 return dyn_cast_or_null<IFuncOp>(
2104 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2105 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2106 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2107 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2109 if (!global && !
function && !alias && !ifunc)
2110 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2111 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2113 LLVMPointerType type =
getType();
2114 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2115 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2116 return emitOpError(
"pointer address space must match address space of the "
2117 "referenced global or alias");
2124 return getGlobalNameAttr();
2145 getFunctionNameAttr());
2146 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2147 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2149 if (!
function && !alias)
2151 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2154 if (alias.getInitializer()
2155 .walk([&](AddressOfOp addrOp) {
2156 if (addrOp.getGlobal(symbolTable))
2157 return WalkResult::interrupt();
2158 return WalkResult::advance();
2161 return emitOpError(
"must reference an alias to a function");
2164 if ((
function &&
function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2165 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2167 "target function with 'extern_weak' linkage not allowed");
2183 StringRef symName) {
2190 LogicalResult ComdatOp::verifyRegions() {
2191 Region &body = getBody();
2193 if (!isa<ComdatSelectorOp>(op))
2194 return op.emitError(
2195 "only comdat selector symbols can appear in a comdat region");
2205 bool isConstant, Linkage linkage, StringRef name,
2206 Attribute value, uint64_t alignment,
unsigned addrSpace,
2207 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2241 if (!dbgExprs.empty())
2248 template <
typename OpType>
2250 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2251 StringRef visibility = stringifyVisibility(op.getVisibility_());
2252 if (!visibility.empty())
2253 p << visibility <<
' ';
2254 if (op.getThreadLocal_())
2255 p <<
"thread_local ";
2256 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2257 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2264 printCommonGlobalAndAlias<GlobalOp>(p, *
this);
2269 if (
auto value = getValueOrNull())
2272 if (
auto comdat = getComdat())
2273 p <<
" comdat(" << *comdat <<
')';
2279 {SymbolTable::getSymbolAttrName(),
2280 getGlobalTypeAttrName(), getConstantAttrName(),
2281 getValueAttrName(), getLinkageAttrName(),
2282 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2283 getVisibility_AttrName(), getComdatAttrName()});
2286 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2290 Region &initializer = getInitializerRegion();
2291 if (!initializer.
empty()) {
2298 std::optional<SymbolRefAttr> attr) {
2303 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2304 return op->
emitError() <<
"expected comdat symbol";
2314 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2315 if (blockTags.contains(blockTagOp.getTag())) {
2316 blockTagOp.emitError()
2317 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2318 <<
"' in the same function: ";
2319 return WalkResult::interrupt();
2321 blockTags.insert(blockTagOp.getTag());
2330 template <
typename OpType>
2336 OpType::getLinkageAttrName(result.
name),
2338 parser, LLVM::Linkage::External)));
2343 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2344 parser, LLVM::Visibility::Default)));
2353 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2369 if (parseCommonGlobalAndAlias<GlobalOp>(parser, result).
failed())
2391 SymbolRefAttr comdat;
2404 if (types.size() > 1)
2408 if (types.empty()) {
2409 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2412 strAttr.getValue().size());
2413 types.push_back(arrayType);
2416 "type can only be omitted for string globals");
2432 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2433 return intValue.getValue().isZero();
2434 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2435 return fpValue.getValue().isZero();
2436 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2438 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2440 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2447 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2448 LLVMMetadataType, LLVMLabelType>(
getType())
2449 : llvm::isa<PointerElementTypeInterface>(
getType());
2452 "expects type to be a valid element type for an LLVM global");
2454 return emitOpError(
"must appear at the module level");
2456 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2457 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2458 IntegerType elementType =
2459 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2460 if (!elementType || elementType.getWidth() != 8 ||
2461 type.getNumElements() != strAttr.getValue().size())
2463 "requires an i8 array type of the length equal to that of the string "
2467 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2468 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2469 return emitOpError()
2470 <<
"this target extension type cannot be used in a global";
2473 return emitOpError() <<
"global with target extension type can only be "
2474 "initialized with zero-initializer";
2477 if (getLinkage() == Linkage::Common) {
2478 if (
Attribute value = getValueOrNull()) {
2480 return emitOpError()
2481 <<
"expected zero value for '"
2482 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2487 if (getLinkage() == Linkage::Appending) {
2488 if (!llvm::isa<LLVMArrayType>(
getType())) {
2489 return emitOpError() <<
"expected array type for '"
2490 << stringifyLinkage(Linkage::Appending)
2498 std::optional<uint64_t> alignAttr = getAlignment();
2499 if (alignAttr.has_value()) {
2500 uint64_t value = alignAttr.value();
2501 if (!llvm::isPowerOf2_64(value))
2502 return emitError() <<
"alignment attribute is not a power of 2";
2508 LogicalResult GlobalOp::verifyRegions() {
2509 if (
Block *b = getInitializerBlock()) {
2510 ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2511 if (ret.operand_type_begin() == ret.operand_type_end())
2512 return emitOpError(
"initializer region cannot return void");
2513 if (*ret.operand_type_begin() !=
getType())
2514 return emitOpError(
"initializer region type ")
2515 << *ret.operand_type_begin() <<
" does not match global type "
2519 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2520 if (!iface || !iface.hasNoEffect())
2521 return op.emitError()
2522 <<
"ops with side effects not allowed in global initializers";
2525 if (getValueOrNull())
2526 return emitOpError(
"cannot have both initializer value and region");
2541 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2544 return op->
emitError(
"data element must be symbol or #llvm.zero");
2561 if (getCtors().size() == getPriorities().size() &&
2562 getCtors().size() == getData().size())
2565 "ctors, priorities, and data must have the same number of elements");
2586 if (getDtors().size() == getPriorities().size() &&
2587 getDtors().size() == getData().size())
2590 "dtors, priorities, and data must have the same number of elements");
2598 Linkage linkage, StringRef name,
bool dsoLocal,
2618 printCommonGlobalAndAlias<AliasOp>(p, *
this);
2622 {SymbolTable::getSymbolAttrName(),
2623 getAliasTypeAttrName(), getLinkageAttrName(),
2624 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2625 getVisibility_AttrName()});
2628 p <<
" : " <<
getType() <<
' ';
2641 if (parseCommonGlobalAndAlias<AliasOp>(parser, result).
failed())
2654 if (types.size() > 1)
2668 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2669 LLVMMetadataType, LLVMLabelType>(
getType())
2670 : llvm::isa<PointerElementTypeInterface>(
getType());
2673 "expects type to be a valid element type for an LLVM global alias");
2676 switch (getLinkage()) {
2677 case Linkage::External:
2678 case Linkage::Internal:
2679 case Linkage::Private:
2681 case Linkage::WeakODR:
2682 case Linkage::Linkonce:
2683 case Linkage::LinkonceODR:
2684 case Linkage::AvailableExternally:
2687 return emitOpError()
2688 <<
"'" << stringifyLinkage(getLinkage())
2689 <<
"' linkage not supported in aliases, available options: private, "
2690 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2691 "available_externally";
2697 LogicalResult AliasOp::verifyRegions() {
2698 Block &b = getInitializerBlock();
2700 if (ret.getNumOperands() == 0 ||
2701 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2702 return emitOpError(
"initializer region must always return a pointer");
2705 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2706 if (!iface || !iface.hasNoEffect())
2707 return op.emitError()
2708 <<
"ops with side effects are not allowed in alias initializers";
2714 unsigned AliasOp::getAddrSpace() {
2715 Block &initializer = getInitializerBlock();
2717 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2718 return ptrTy.getAddressSpace();
2726 Type iFuncType, StringRef resolverName,
Type resolverType,
2728 return build(builder, result, name, iFuncType, resolverName, resolverType,
2737 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2738 auto alias = dyn_cast<AliasOp>(symbol);
2740 Block &initBlock = alias.getInitializerBlock();
2742 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
2749 resolver = addrOp.getFunction(symbolTable);
2750 alias = addrOp.getAlias(symbolTable);
2753 return emitOpError(
"must have a function resolver");
2754 Linkage linkage = resolver.getLinkage();
2755 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
2756 return emitOpError(
"resolver must be a definition");
2757 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
2758 return emitOpError(
"resolver must return a pointer");
2759 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
2760 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
2761 return emitOpError(
"resolver has incorrect type");
2766 switch (getLinkage()) {
2767 case Linkage::External:
2768 case Linkage::Internal:
2769 case Linkage::Private:
2771 case Linkage::WeakODR:
2772 case Linkage::Linkonce:
2773 case Linkage::LinkonceODR:
2776 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
2777 <<
"' linkage not supported in ifuncs, available "
2778 "options: private, internal, linkonce, weak, "
2779 "linkonce_odr, weak_odr, or external linkage";
2791 auto containerType = v1.
getType();
2795 build(builder, state, vType, v1, v2, mask);
2796 state.addAttributes(attrs);
2809 "expected an LLVM compatible vector type");
2822 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2823 return emitOpError(
"expected a splat operation for scalable vectors");
2833 assert(empty() &&
"function already has an entry block");
2838 LLVMFunctionType type = getFunctionType();
2839 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2840 entry->
addArgument(type.getParamType(i), getLoc());
2845 StringRef name,
Type type, LLVM::Linkage linkage,
2846 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2849 std::optional<uint64_t> functionEntryCount) {
2865 if (functionEntryCount)
2868 if (argAttrs.empty())
2871 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2872 "expected as many argument attribute lists as arguments");
2874 builder, result, argAttrs, {},
2875 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2886 if (outputs.size() > 1) {
2887 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2888 "one function result");
2894 for (
auto t : inputs) {
2896 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2897 "type for function arguments");
2900 llvmInputs.push_back(t);
2907 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2908 "type for function results")
2927 parseOptionalLLVMKeyword<Linkage>(
2928 parser, LLVM::Linkage::External)));
2933 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2934 parser, LLVM::Visibility::Default)));
2939 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2944 getCConvAttrName(result.
name),
2946 parseOptionalLLVMKeyword<CConv>(parser, LLVM::CConv::C)));
2948 StringAttr nameAttr;
2958 parser,
true, entryArgs, isVariadic, resultTypes,
2963 for (
auto &arg : entryArgs)
2964 argTypes.push_back(arg.type);
2974 int64_t minRange, maxRange;
2981 getVscaleRangeAttrName(result.
name),
2988 SymbolRefAttr comdat;
2999 parser.
getBuilder(), result, entryArgs, resultAttrs,
3000 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
3013 if (getLinkage() != LLVM::Linkage::External)
3014 p << stringifyLinkage(getLinkage()) <<
' ';
3015 StringRef visibility = stringifyVisibility(getVisibility_());
3016 if (!visibility.empty())
3017 p << visibility <<
' ';
3018 if (
auto unnamedAddr = getUnnamedAddr()) {
3019 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3023 if (getCConv() != LLVM::CConv::C)
3024 p << stringifyCConv(getCConv()) <<
' ';
3028 LLVMFunctionType fnType = getFunctionType();
3031 argTypes.reserve(fnType.getNumParams());
3032 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3033 argTypes.push_back(fnType.getParamType(i));
3035 Type returnType = fnType.getReturnType();
3036 if (!llvm::isa<LLVMVoidType>(returnType))
3037 resTypes.push_back(returnType);
3040 isVarArg(), resTypes);
3043 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3044 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3045 << vscale->getMaxRange().getInt() <<
')';
3048 if (
auto comdat = getComdat())
3049 p <<
" comdat(" << *comdat <<
')';
3053 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3054 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3055 getComdatAttrName(), getUnnamedAddrAttrName(),
3056 getVscaleRangeAttrName()});
3059 Region &body = getBody();
3060 if (!body.empty()) {
3072 if (getLinkage() == LLVM::Linkage::Common)
3073 return emitOpError() <<
"functions cannot have '"
3074 << stringifyLinkage(LLVM::Linkage::Common)
3081 if (getLinkage() != LLVM::Linkage::External &&
3082 getLinkage() != LLVM::Linkage::ExternWeak)
3083 return emitOpError() <<
"external functions must have '"
3084 << stringifyLinkage(LLVM::Linkage::External)
3086 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3092 if (isNoInline() && isAlwaysInline())
3093 return emitError(
"no_inline and always_inline attributes are incompatible");
3095 if (isOptimizeNone() && !isNoInline())
3096 return emitOpError(
"with optimize_none must also be no_inline");
3098 Type landingpadResultTy;
3099 StringRef diagnosticMessage;
3100 bool isLandingpadTypeConsistent =
3102 const auto checkType = [&](
Type type, StringRef errorMessage) {
3103 if (!landingpadResultTy) {
3104 landingpadResultTy = type;
3107 if (landingpadResultTy != type) {
3108 diagnosticMessage = errorMessage;
3114 .Case<LandingpadOp>([&](
auto landingpad) {
3115 constexpr StringLiteral errorMessage =
3116 "'llvm.landingpad' should have a consistent result type "
3117 "inside a function";
3118 return checkType(landingpad.getType(), errorMessage);
3120 .Case<ResumeOp>([&](
auto resume) {
3121 constexpr StringLiteral errorMessage =
3122 "'llvm.resume' should have a consistent input type inside a "
3124 return checkType(resume.getValue().getType(), errorMessage);
3127 }).wasInterrupted();
3128 if (!isLandingpadTypeConsistent) {
3129 assert(!diagnosticMessage.empty() &&
3130 "Expecting a non-empty diagnostic message");
3142 LogicalResult LLVMFuncOp::verifyRegions() {
3146 unsigned numArguments = getFunctionType().getNumParams();
3147 Block &entryBlock = front();
3148 for (
unsigned i = 0; i < numArguments; ++i) {
3151 return emitOpError(
"entry block argument #")
3152 << i <<
" is not of LLVM type";
3158 Region *LLVMFuncOp::getCallableRegion() {
3187 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3188 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3189 return emitOpError()
3190 <<
"target extension type does not support zero-initializer";
3212 if (
auto vecType = dyn_cast<VectorType>(t)) {
3213 assert(!vecType.isScalable() &&
3214 "number of elements of a scalable vector type is unknown");
3215 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3217 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3218 return arrayType.getNumElements() *
3226 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3227 type = arrayType.getElementType();
3228 if (
auto vecType = dyn_cast<VectorType>(type))
3229 return vecType.getElementType();
3230 if (
auto tenType = dyn_cast<TensorType>(type))
3231 return tenType.getElementType();
3238 if (
auto vecType = dyn_cast<VectorType>(t)) {
3239 if (vecType.isScalable())
3243 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3251 LLVM::LLVMArrayType arrayType,
3252 ArrayAttr arrayAttr,
int dim) {
3253 if (arrayType.getNumElements() != arrayAttr.size())
3254 return op.emitOpError()
3255 <<
"array attribute size does not match array type size in "
3257 << dim <<
": " << arrayAttr.size() <<
" vs. "
3258 << arrayType.getNumElements();
3263 if (
auto subArrayType =
3264 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3266 if (elementsVerified.insert(elementAttr).second) {
3267 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3269 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3271 return op.emitOpError()
3272 <<
"nested attribute for sub-array in dimension " << dim
3273 <<
" at index " << idx
3274 <<
" must be a zero, or undef, or array attribute";
3288 auto structType = dyn_cast<LLVM::LLVMStructType>(arrayType.getElementType());
3290 return op.emitOpError() <<
"for array with an array attribute must have a "
3291 "struct element type";
3295 size_t numStructElements = structType.getBody().size();
3297 if (elementsVerified.insert(elementAttr).second) {
3298 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3300 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3302 return op.emitOpError()
3303 <<
"nested attribute for struct element at index " << idx
3304 <<
" must be a zero, or undef, or array attribute";
3305 if (subArrayAttr.size() != numStructElements)
3306 return op.emitOpError()
3307 <<
"nested array attribute size for struct element at index "
3308 << idx <<
" must match struct size: " << subArrayAttr.size()
3309 <<
" vs. " << numStructElements;
3317 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3318 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3319 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3320 !arrayType.getElementType().isInteger(8)) {
3321 return emitOpError() <<
"expected array type of "
3322 << sAttr.getValue().size()
3323 <<
" i8 elements for the string constant";
3327 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3328 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3330 return emitOpError() <<
"expected array attribute for struct type";
3333 if (arrayAttr.size() != elementTypes.size()) {
3334 return emitOpError() <<
"expected array attribute of size "
3335 << elementTypes.size();
3337 for (
auto [i, attr, type] :
llvm::enumerate(arrayAttr, elementTypes)) {
3339 return emitOpError() <<
"expected struct element types to be floating "
3340 "point type or integer type";
3342 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3343 return emitOpError() <<
"expected element of array attribute to be "
3344 "floating point or integer";
3346 if (cast<TypedAttr>(attr).
getType() != type)
3347 return emitOpError()
3348 <<
"struct element at index " << i <<
" is of wrong type";
3353 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3354 return emitOpError() <<
"does not support target extension type.";
3365 auto verifyFloatSemantics =
3366 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3367 Type constantElementType) -> LogicalResult {
3368 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3369 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3370 return emitOpError()
3371 <<
"attribute and type have different float semantics";
3375 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3376 if (isa<IntegerType>(constantElementType)) {
3377 if (!constantElementType.isInteger(floatWidth))
3378 return emitOpError() <<
"expected integer type of width " << floatWidth;
3386 if (isa<IntegerAttr>(getValue())) {
3387 if (!llvm::isa<IntegerType>(
getType()))
3388 return emitOpError() <<
"expected integer type";
3389 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3390 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3391 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3395 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3396 if (!splatElementsAttr)
3397 return emitOpError()
3398 <<
"scalable vector type requires a splat attribute";
3401 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3402 return emitOpError() <<
"expected vector or array type";
3405 int64_t attrNumElements = elementsAttr.getNumElements();
3407 return emitOpError()
3408 <<
"type and attribute have a different number of elements: "
3414 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3415 return verifyFloatSemantics(floatType.getFloatSemantics(), resultElmType);
3417 if (isa<IntegerType>(attrElmType) && !isa<IntegerType>(resultElmType)) {
3419 "expected integer element type for integer elements attribute");
3421 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3424 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3426 return emitOpError()
3427 <<
"expected array or struct type for array attribute";
3433 return emitOpError()
3434 <<
"only supports integer, float, string or elements attributes";
3440 bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3442 auto typedAttr = dyn_cast<TypedAttr>(value);
3449 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3454 if (isBuildableWith(value, type))
3455 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3460 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3468 AtomicOrdering ordering, StringRef syncscope,
3469 unsigned alignment,
bool isVolatile) {
3470 build(builder, state, val.
getType(), binOp, ptr, val, ordering,
3471 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3474 nullptr,
nullptr,
nullptr);
3478 auto valType = getVal().getType();
3479 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3480 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3481 getBinOp() == AtomicBinOp::fminimum ||
3482 getBinOp() == AtomicBinOp::fmaximum) {
3485 return emitOpError(
"expected LLVM IR fixed vector type");
3486 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3489 "expected LLVM IR floating point type for vector element");
3491 return emitOpError(
"expected LLVM IR floating point type");
3493 }
else if (getBinOp() == AtomicBinOp::xchg) {
3496 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3498 auto intType = llvm::dyn_cast<IntegerType>(valType);
3499 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3500 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3502 return emitOpError(
"expected LLVM IR integer type");
3505 if (
static_cast<unsigned>(getOrdering()) <
3506 static_cast<unsigned>(AtomicOrdering::monotonic))
3507 return emitOpError() <<
"expected at least '"
3508 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3521 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3526 AtomicOrdering successOrdering,
3527 AtomicOrdering failureOrdering, StringRef syncscope,
3528 unsigned alignment,
bool isWeak,
bool isVolatile) {
3530 successOrdering, failureOrdering,
3531 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3533 isVolatile,
nullptr,
3534 nullptr,
nullptr,
nullptr);
3538 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3540 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3541 auto valType = getVal().getType();
3544 return emitOpError(
"unexpected LLVM IR type");
3545 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3546 getFailureOrdering() < AtomicOrdering::monotonic)
3547 return emitOpError(
"ordering must be at least 'monotonic'");
3548 if (getFailureOrdering() == AtomicOrdering::release ||
3549 getFailureOrdering() == AtomicOrdering::acq_rel)
3550 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3559 AtomicOrdering ordering, StringRef syncscope) {
3560 build(builder, state, ordering,
3561 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3565 if (getOrdering() == AtomicOrdering::not_atomic ||
3566 getOrdering() == AtomicOrdering::unordered ||
3567 getOrdering() == AtomicOrdering::monotonic)
3568 return emitOpError(
"can be given only acquire, release, acq_rel, "
3569 "and seq_cst orderings");
3579 template <
class ExtOp>
3581 IntegerType inputType, outputType;
3584 return op.emitError(
3585 "input type is a vector but output type is an integer");
3588 return op.emitError(
"input and output vectors are of incompatible shape");
3591 inputType = cast<IntegerType>(
3592 cast<VectorType>(op.getArg().getType()).getElementType());
3593 outputType = cast<IntegerType>(
3594 cast<VectorType>(op.getResult().getType()).getElementType());
3598 inputType = cast<IntegerType>(op.getArg().getType());
3599 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3601 return op.emitError(
3602 "input type is an integer but output type is a vector");
3605 if (outputType.getWidth() <= inputType.getWidth())
3606 return op.emitError(
"integer width of the output type is smaller or "
3607 "equal to the integer width of the input type");
3615 LogicalResult
ZExtOp::verify() {
return verifyExtOp<ZExtOp>(*
this); }
3618 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3622 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3630 LogicalResult
SExtOp::verify() {
return verifyExtOp<SExtOp>(*
this); }
3637 template <
typename T>
3639 typename T::FoldAdaptor adaptor) {
3641 if (castOp.getArg().getType() == castOp.getType())
3642 return castOp.getArg();
3643 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3645 if (prev.getArg().getType() == castOp.getType())
3646 return prev.getArg();
3648 castOp.getArgMutable().set(prev.getArg());
3649 return Value{castOp};
3654 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3659 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3661 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3666 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3667 return emitOpError(
"can only cast pointers from and to pointers");
3672 auto isVector = llvm::IsaPred<VectorType>;
3676 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3677 return emitOpError(
"cannot cast pointer to vector of pointers");
3679 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3680 return emitOpError(
"cannot cast vector of pointers to pointer");
3684 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3685 return emitOpError(
"cannot cast pointers of different address spaces, "
3686 "use 'llvm.addrspacecast' instead");
3695 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3699 Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3707 adaptor.getDynamicIndices());
3711 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
3712 if (integer.getValue().isZero())
3719 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3726 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3727 gepArgs.emplace_back(val);
3729 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3735 gepArgs.emplace_back(integer.getInt());
3743 getDynamicIndicesMutable().assign(dynamicIndices);
3744 setRawConstantIndices(rawConstantIndices);
3745 return Value{*
this};
3751 Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3758 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3762 if (rhs.getValue().getZExtValue() >=
3763 getLhs().
getType().getIntOrFloatBitWidth())
3766 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3778 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3782 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3794 if (!getIntrin().starts_with(
"llvm."))
3795 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3803 build(builder, state,
TypeRange{}, intrin, args,
3804 FastmathFlagsAttr{},
3811 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3812 build(builder, state,
TypeRange{}, intrin, args,
3819 mlir::Type resultType, mlir::StringAttr intrin,
3821 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
3829 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3830 build(builder, state, resultTypes, intrin, args, fastMathFlags,
3837 StringAttr intrinAttr;
3841 ArrayAttr opBundleTags;
3855 return mlir::failure();
3858 return mlir::failure();
3863 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
3864 result &&
failed(*result))
3866 if (opBundleTags && !opBundleTags.empty())
3868 CallIntrinsicOp::getOpBundleTagsAttrName(result.
name).getValue(),
3872 return mlir::failure();
3877 operands, argAttrs, resultAttrs))
3880 parser.
getBuilder(), result, argAttrs, resultAttrs,
3881 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
3884 opBundleOperandTypes,
3885 getOpBundleSizesAttrName(result.
name)))
3888 int32_t numOpBundleOperands = 0;
3889 for (
const auto &operands : opBundleOperands)
3890 numOpBundleOperands += operands.size();
3893 CallIntrinsicOp::getOperandSegmentSizeAttr(),
3895 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
3897 return mlir::success();
3905 p <<
"(" << args <<
")";
3908 if (!getOpBundleOperands().empty()) {
3911 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
3915 {getOperandSegmentSizesAttrName(),
3916 getOpBundleSizesAttrName(), getIntrinAttrName(),
3917 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
3918 getResAttrsAttrName()});
3924 p, args.
getTypes(), getArgAttrsAttr(),
3925 false, getResultTypes(), getResAttrsAttr());
3935 return emitOpError(
"must appear at the module level");
3946 return emitOpError(
"must appear at the module level");
3948 if (!isa<ModuleFlagAttr>(flag))
3949 return emitOpError(
"expected a module flag attribute");
3957 void InlineAsmOp::getEffects(
3960 if (getHasSideEffects()) {
3973 getBlockAddr().getFunction());
3974 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
3977 return emitOpError(
"must reference a function defined by 'llvm.func'");
3987 BlockTagOp BlockAddressOp::getBlockTagOp() {
3993 BlockTagOp blockTagOp =
nullptr;
3994 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
3995 if (labelOp.getTag() == getBlockAddr().getTag()) {
3996 blockTagOp = labelOp;
4005 if (!getBlockTagOp())
4007 "expects an existing block label target in the referenced function");
4014 OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4021 assert(index < getNumSuccessors() &&
"invalid successor index");
4033 rangeSegments.push_back(range.size());
4047 Block *destination = nullptr;
4048 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4049 SmallVector<Type> operandTypes;
4051 if (parser.parseSuccessor(destination).failed())
4054 if (succeeded(parser.parseOptionalLParen())) {
4055 if (failed(parser.parseOperandList(
4056 operands, OpAsmParser::Delimiter::None)) ||
4057 failed(parser.parseColonTypeList(operandTypes)) ||
4058 failed(parser.parseRParen()))
4061 succOperandBlocks.push_back(destination);
4062 succOperands.emplace_back(operands);
4063 succOperandsTypes.emplace_back(operandTypes);
4066 "successor blocks")))
4077 llvm::zip(succs, succOperands),
4083 if (!succOperands.empty())
4094 return build(builder, state, cond, {},
4106 return build(builder, state, cond,
"align",
ValueRange{ptr, align});
4112 return build(builder, state, cond,
"separate_storage",
4123 auto ptrsVectorType = getPtrs().getType();
4124 Type expectedPtrsVectorType =
4129 if (ptrsVectorType != expectedPtrsVectorType)
4130 return emitOpError(
"expected operand #1 type to be ")
4131 << expectedPtrsVectorType;
4140 auto ptrsVectorType = getPtrs().getType();
4141 Type expectedPtrsVectorType =
4146 if (ptrsVectorType != expectedPtrsVectorType)
4147 return emitOpError(
"expected operand #2 type to be ")
4148 << expectedPtrsVectorType;
4161 build(builder, state, resTys, ptr, mask, passthru, argAttrs,
4169 void LLVM::masked_compressstore::build(
OpBuilder &builder,
4172 ArrayAttr argAttrs =
4174 build(builder, state, value, ptr, mask, argAttrs,
4183 if (!getTailCallKindAttr())
4186 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4188 "tail call kind 'musttail' is not supported by this operation");
4197 void LLVMDialect::initialize() {
4198 registerAttributes();
4201 addTypes<LLVMVoidType,
4204 LLVMMetadataType>();
4210 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4214 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4219 allowUnknownOperations();
4220 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4223 #define GET_OP_CLASSES
4224 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4226 #define GET_OP_CLASSES
4227 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4229 LogicalResult LLVMDialect::verifyDataLayoutString(
4233 if (maybeDataLayout)
4236 std::string message;
4237 llvm::raw_string_ostream messageStream(message);
4238 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4239 reportError(
"invalid data layout descriptor: " + message);
4244 LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4250 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4252 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4253 return verifyDataLayoutString(
4254 stringAttr.getValue(),
4255 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4258 << LLVM::LLVMDialect::getDataLayoutAttrName()
4259 <<
"' to be a string attributes";
4262 LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4270 StringAttr name = paramAttr.
getName();
4272 auto checkUnitAttrType = [&]() -> LogicalResult {
4273 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4274 return op->
emitError() << name <<
" should be a unit attribute";
4277 auto checkTypeAttrType = [&]() -> LogicalResult {
4278 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4279 return op->
emitError() << name <<
" should be a type attribute";
4282 auto checkIntegerAttrType = [&]() -> LogicalResult {
4283 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4284 return op->
emitError() << name <<
" should be an integer attribute";
4287 auto checkPointerType = [&]() -> LogicalResult {
4288 if (!llvm::isa<LLVMPointerType>(paramType))
4290 << name <<
" attribute attached to non-pointer LLVM type";
4293 auto checkIntegerType = [&]() -> LogicalResult {
4294 if (!llvm::isa<IntegerType>(paramType))
4296 << name <<
" attribute attached to non-integer LLVM type";
4299 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4300 if (
failed(checkPointerType()))
4307 if (name == LLVMDialect::getNoAliasAttrName() ||
4308 name == LLVMDialect::getReadonlyAttrName() ||
4309 name == LLVMDialect::getReadnoneAttrName() ||
4310 name == LLVMDialect::getWriteOnlyAttrName() ||
4311 name == LLVMDialect::getNestAttrName() ||
4312 name == LLVMDialect::getNoCaptureAttrName() ||
4313 name == LLVMDialect::getNoFreeAttrName() ||
4314 name == LLVMDialect::getNonNullAttrName()) {
4315 if (
failed(checkUnitAttrType()))
4317 if (verifyValueType &&
failed(checkPointerType()))
4323 if (name == LLVMDialect::getStructRetAttrName() ||
4324 name == LLVMDialect::getByValAttrName() ||
4325 name == LLVMDialect::getByRefAttrName() ||
4326 name == LLVMDialect::getElementTypeAttrName() ||
4327 name == LLVMDialect::getInAllocaAttrName() ||
4328 name == LLVMDialect::getPreallocatedAttrName()) {
4329 if (
failed(checkTypeAttrType()))
4331 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4337 if (name == LLVMDialect::getSExtAttrName() ||
4338 name == LLVMDialect::getZExtAttrName()) {
4339 if (
failed(checkUnitAttrType()))
4341 if (verifyValueType &&
failed(checkIntegerType()))
4347 if (name == LLVMDialect::getAlignAttrName() ||
4348 name == LLVMDialect::getDereferenceableAttrName() ||
4349 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4350 if (
failed(checkIntegerAttrType()))
4352 if (verifyValueType &&
failed(checkPointerType()))
4358 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4359 if (
failed(checkIntegerAttrType()))
4365 if (name == LLVMDialect::getNoUndefAttrName() ||
4366 name == LLVMDialect::getInRegAttrName() ||
4367 name == LLVMDialect::getReturnedAttrName())
4368 return checkUnitAttrType();
4374 LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4378 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4381 Type argType = funcOp.getArgumentTypes()[argIdx];
4383 return verifyParameterAttribute(op, argType, argAttr);
4386 LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4390 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4393 Type resType = funcOp.getResultTypes()[resIdx];
4397 if (llvm::isa<LLVMVoidType>(resType))
4398 return op->
emitError() <<
"cannot attach result attributes to functions "
4399 "with a void return";
4403 auto name = resAttr.
getName();
4404 if (name == LLVMDialect::getAllocAlignAttrName() ||
4405 name == LLVMDialect::getAllocatedPointerAttrName() ||
4406 name == LLVMDialect::getByValAttrName() ||
4407 name == LLVMDialect::getByRefAttrName() ||
4408 name == LLVMDialect::getInAllocaAttrName() ||
4409 name == LLVMDialect::getNestAttrName() ||
4410 name == LLVMDialect::getNoCaptureAttrName() ||
4411 name == LLVMDialect::getNoFreeAttrName() ||
4412 name == LLVMDialect::getPreallocatedAttrName() ||
4413 name == LLVMDialect::getReadnoneAttrName() ||
4414 name == LLVMDialect::getReadonlyAttrName() ||
4415 name == LLVMDialect::getReturnedAttrName() ||
4416 name == LLVMDialect::getStackAlignmentAttrName() ||
4417 name == LLVMDialect::getStructRetAttrName() ||
4418 name == LLVMDialect::getWriteOnlyAttrName())
4419 return op->
emitError() << name <<
" is not a valid result attribute";
4420 return verifyParameterAttribute(op, resType, resAttr);
4428 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4429 if (isa<LLVM::LLVMPointerType>(type))
4430 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4431 if (isa<LLVM::UndefAttr>(value))
4432 return LLVM::UndefOp::create(builder, loc, type);
4433 if (isa<LLVM::PoisonAttr>(value))
4434 return LLVM::PoisonOp::create(builder, loc, type);
4435 if (isa<LLVM::ZeroAttr>(value))
4436 return LLVM::ZeroOp::create(builder, loc, type);
4438 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4446 StringRef name, StringRef value,
4447 LLVM::Linkage linkage) {
4450 "expected builder to point to a block constrained in an op");
4453 assert(module &&
"builder points to an op outside of a module");
4459 auto global = LLVM::GlobalOp::create(
4460 moduleBuilder, loc, type,
true, linkage, name,
4466 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4467 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4480 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 bool isTypeCompatibleWithAtomicOp(Type type, const DataLayout &dataLayout)
Returns true if the given type is supported by atomic operations.
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.
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 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.