27#include "llvm/ADT/APFloat.h"
28#include "llvm/ADT/TypeSwitch.h"
29#include "llvm/IR/DataLayout.h"
30#include "llvm/Support/Error.h"
39using mlir::LLVM::cconv::getMaxEnumValForCConv;
40using mlir::LLVM::linkage::getMaxEnumValForLinkage;
41using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
43#include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
54 if (attr.
getName() ==
"fastmathFlags") {
74 << name <<
"' does not reference a valid LLVM function";
75 if (
func.isExternal())
76 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
94 for (
const auto &en : llvm::enumerate(keywords)) {
102template <
typename Ty>
105#define REGISTER_ENUM_TYPE(Ty) \
107 struct EnumTraits<Ty> { \
108 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
109 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
122template <
typename EnumTy,
typename RetTy = EnumTy>
124 EnumTy defaultValue) {
126 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
127 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
131 return static_cast<RetTy
>(defaultValue);
132 return static_cast<RetTy
>(
index);
136 p << stringifyLinkage(val.getLinkage());
140 val = LinkageAttr::get(
148 uint64_t alignment = 1) {
154 if (alignment == 1) {
161 builder.
getNamedAttr(LLVMDialect::getAlignAttrName(), alignmentAttr);
171 int pos = isExpandLoad ? 0 : 1;
173 {alignDictAttr, emptyDictAttr, emptyDictAttr})
175 {emptyDictAttr, alignDictAttr, emptyDictAttr});
187 if (!operands.empty()) {
190 llvm::interleaveComma(operandTypes, p);
199 std::optional<ArrayAttr> opBundleTags) {
200 if (opBundleOperands.empty())
202 assert(opBundleTags &&
"expect operand bundle tags");
205 llvm::interleaveComma(
206 llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
208 auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
226 return p.
emitError(currentParserLoc,
"expect operand bundle tag");
237 opBundleOperands.push_back(std::move(operands));
238 opBundleOperandTypes.push_back(std::move(types));
239 opBundleTags.push_back(StringAttr::get(p.
getContext(), tag));
256 auto bundleParser = [&] {
266 opBundleTags = ArrayAttr::get(p.
getContext(), opBundleTagAttrs);
276 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
277 <<
", " << getOperand(1);
279 p <<
" : " << getLhs().getType();
283 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
284 <<
", " << getOperand(1);
286 p <<
" : " << getLhs().getType();
293template <
typename CmpPredicateType>
295 StringAttr predicateAttr;
298 SMLoc predicateLoc, trailingTypeLoc;
311 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
312 std::optional<ICmpPredicate> predicate =
313 symbolizeICmpPredicate(predicateAttr.getValue());
316 <<
"'" << predicateAttr.getValue()
317 <<
"' is an incorrect value of the 'predicate' attribute";
318 predicateValue =
static_cast<int64_t>(*predicate);
320 std::optional<FCmpPredicate> predicate =
321 symbolizeFCmpPredicate(predicateAttr.getValue());
324 <<
"'" << predicateAttr.getValue()
325 <<
"' is an incorrect value of the 'predicate' attribute";
326 predicateValue =
static_cast<int64_t>(*predicate);
329 result.attributes.set(
"predicate",
336 "expected LLVM dialect-compatible type");
352 ShapedType shapedType = dyn_cast<ShapedType>(type);
359 if (getPredicate() != ICmpPredicate::eq &&
360 getPredicate() != ICmpPredicate::ne)
364 if (getLhs() == getRhs())
366 getPredicate() == ICmpPredicate::eq);
369 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
371 getPredicate() == ICmpPredicate::ne);
374 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
377 getLhsMutable().assign(
rhs);
378 getRhsMutable().assign(
lhs);
396 p <<
' ' << getArraySize() <<
" x " << getElemType();
397 if (getAlignment() && *getAlignment() != 0)
399 {kElemTypeAttrName, getInallocaAttrName()});
403 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
404 p <<
" : " << funcTy;
412 SMLoc trailingTypeLoc;
424 std::optional<NamedAttribute> alignmentAttr =
425 result.attributes.getNamed(
"alignment");
426 if (alignmentAttr.has_value()) {
427 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
430 "expected integer alignment");
431 if (alignmentInt.getValue().isZero())
432 result.attributes.erase(
"alignment");
436 auto funcType = llvm::dyn_cast<FunctionType>(type);
437 if (!funcType || funcType.getNumInputs() != 1 ||
438 funcType.getNumResults() != 1)
441 "expected trailing function type with one argument and one result");
446 Type resultType = funcType.getResult(0);
447 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
450 result.addTypes({funcType.getResult(0)});
454LogicalResult AllocaOp::verify() {
456 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
457 targetExtType && !targetExtType.supportsMemOps())
459 <<
"this target extension type cannot be used in alloca";
469 assert(
index == 0 &&
"invalid successor index");
478 assert(
index < getNumSuccessors() &&
"invalid successor index");
480 : getFalseDestOperandsMutable());
486 std::optional<std::pair<uint32_t, uint32_t>> weights) {
491 static_cast<int32_t
>(weights->second)});
493 build(builder,
result, condition, trueOperands, falseOperands, weightsAttr,
494 {}, trueDest, falseDest);
508 if (!branchWeights.empty())
511 build(builder,
result, value, defaultOperands, caseOperands, caseValues,
512 weightsAttr, defaultDestination, caseDestinations);
521 if (!caseValues.empty()) {
522 ShapedType caseValueType = VectorType::get(
527 build(builder,
result, value, defaultDestination, defaultOperands,
528 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
537 if (!caseValues.empty()) {
538 ShapedType caseValueType = VectorType::get(
543 build(builder,
result, value, defaultDestination, defaultOperands,
544 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
560 auto parseCase = [&]() {
564 values.push_back(APInt(bitWidth, value,
true));
577 caseDestinations.push_back(destination);
578 caseOperands.emplace_back(operands);
579 caseOperandTypes.emplace_back(operandTypes);
585 ShapedType caseValueType =
586 VectorType::get(
static_cast<int64_t>(values.size()), flagType);
605 llvm::zip(caseValues, caseDestinations),
620LogicalResult SwitchOp::verify() {
621 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
623 getCaseValues()->size() !=
624 static_cast<int64_t>(getCaseDestinations().size())))
625 return emitOpError(
"expects number of case values to match number of "
626 "case destinations");
627 if (getCaseValues() &&
629 return emitError(
"expects case value type to match condition value type");
634 assert(
index < getNumSuccessors() &&
"invalid successor index");
636 : getCaseOperandsMutable(
index - 1));
645 getDynamicIndices());
650 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
651 return vectorType.getElementType();
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];
705 GEPNoWrapFlags noWrapFlags,
711 result.addTypes(resultType);
712 result.addAttributes(attributes);
713 result.getOrAddProperties<Properties>().rawConstantIndices =
715 result.getOrAddProperties<Properties>().noWrapFlags = noWrapFlags;
716 result.getOrAddProperties<Properties>().elem_type =
717 TypeAttr::get(elementType);
718 result.addOperands(basePtr);
719 result.addOperands(dynamicIndices);
724 GEPNoWrapFlags noWrapFlags,
726 build(builder,
result, resultType, elementType, basePtr,
736 auto idxParser = [&]() -> ParseResult {
737 int32_t constantIndex;
741 if (failed(parsedInteger.
value()))
743 constantIndices.push_back(constantIndex);
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 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())
793 <<
" indexing a struct is out of bounds";
800 .Case<VectorType, LLVMArrayType>(
801 [&](
auto containerType) -> LogicalResult {
805 .Default([&](
auto otherType) -> LogicalResult {
807 <<
"type " << otherType <<
" cannot be indexed (index #"
819LogicalResult LLVM::GEPOp::verify() {
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.");
837void 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;
870template <
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");
892LogicalResult LoadOp::verify() {
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),
916void StoreOp::getEffects(
925 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
926 getOrdering() != AtomicOrdering::unordered)) {
932LogicalResult StoreOp::verify() {
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;
973 resultType = LLVMVoidType::get(context);
975 resultType = results.front();
976 return LLVMFunctionType::get(resultType, llvm::to_vector(args.
getTypes()),
982 build(builder, state, results, builder.
getStringAttr(callee), args);
987 build(builder, state, results, SymbolRefAttr::get(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,
998 nullptr,
nullptr,
nullptr,
1002 nullptr,
nullptr,
nullptr,
1016 LLVMFunctionType calleeType, StringRef callee,
1018 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1022 LLVMFunctionType calleeType, StringAttr callee,
1024 build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
1042 nullptr,
nullptr,
nullptr,
1050 nullptr,
nullptr,
nullptr,
1056 LLVMFunctionType calleeType,
ValueRange args) {
1061 nullptr,
nullptr,
nullptr,
1062 nullptr,
nullptr,
nullptr,
1068 nullptr,
nullptr,
nullptr,
1083 auto calleeType =
func.getFunctionType();
1087 nullptr,
nullptr,
nullptr,
1088 nullptr,
nullptr,
nullptr,
1094 nullptr,
nullptr,
nullptr,
1112 return getOperand(0);
1118 auto symRef = cast<SymbolRefAttr>(callee);
1119 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1122 return setOperand(0, cast<Value>(callee));
1126 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1131 getCalleeOperands().size());
1138 if (callee.isExternal())
1140 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1144 auto hasSubprogram = [](
Operation *op) {
1149 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1151 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1153 return callOp.emitError()
1154 <<
"inlinable function call in a function with a DISubprogram "
1155 "location must have a debug location";
1161template <
typename OpTy>
1163 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1168 if (!varCalleeType->isVarArg())
1169 return callOp.emitOpError(
1170 "expected var_callee_type to be a variadic function type");
1174 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1175 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1176 << callOp.getArgOperands().size() <<
" parameters";
1179 for (
auto [paramType, operand] :
1180 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1181 if (paramType != operand.getType())
1182 return callOp.emitOpError()
1183 <<
"var_callee_type parameter type mismatch: " << paramType
1184 <<
" != " << operand.getType();
1187 if (!callOp.getNumResults()) {
1188 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1189 return callOp.emitOpError(
"expected var_callee_type to return void");
1191 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1192 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1193 << varCalleeType->getReturnType()
1194 <<
" != " << callOp.getResult().getType();
1199template <
typename OpType>
1202 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1204 auto isStringAttr = [](
Attribute tagAttr) {
1205 return isa<StringAttr>(tagAttr);
1207 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1208 return op.emitError(
"operand bundle tag must be a StringAttr");
1210 size_t numOpBundles = opBundleOperands.size();
1211 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1212 if (numOpBundles != numOpBundleTags)
1213 return op.emitError(
"expected ")
1214 << numOpBundles <<
" operand bundle tags, but actually got "
1230 bool isIndirect =
false;
1236 if (!getNumOperands())
1238 "must have either a `callee` attribute or at least an operand");
1239 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1241 return emitOpError(
"indirect call expects a pointer as callee: ")
1242 << getOperand(0).getType();
1251 <<
"' does not reference a symbol in the current scope";
1252 if (
auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1255 fnType = fn.getFunctionType();
1256 }
else if (
auto ifunc = dyn_cast<IFuncOp>(callee)) {
1257 fnType = ifunc.getIFuncType();
1258 }
else if (isa<AliasOp>(callee)) {
1262 fnType = getCalleeFunctionType();
1266 <<
"' does not reference a valid LLVM function, IFunc, or alias";
1270 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1272 return emitOpError(
"callee does not have a functional type: ") << fnType;
1274 if (funcType.isVarArg() && !getVarCalleeType())
1275 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1279 if (!funcType.isVarArg() &&
1280 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1281 return emitOpError() <<
"incorrect number of operands ("
1282 << (getCalleeOperands().size() - isIndirect)
1283 <<
") for callee (expecting: "
1284 << funcType.getNumParams() <<
")";
1286 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1287 return emitOpError() <<
"incorrect number of operands ("
1288 << (getCalleeOperands().size() - isIndirect)
1289 <<
") for varargs callee (expecting at least: "
1290 << funcType.getNumParams() <<
")";
1292 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1293 if (getOperand(i + isIndirect).
getType() != funcType.getParamType(i))
1294 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1295 << getOperand(i + isIndirect).getType()
1296 <<
" != " << funcType.getParamType(i);
1298 if (getNumResults() == 0 &&
1299 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1300 return emitOpError() <<
"expected function call to produce a value";
1302 if (getNumResults() != 0 &&
1303 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1305 <<
"calling function with void result must not produce values";
1307 if (getNumResults() > 1)
1309 <<
"expected LLVM function call to produce 0 or 1 result";
1311 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1312 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1313 <<
" != " << funcType.getReturnType();
1319 auto callee = getCallee();
1320 bool isDirect = callee.has_value();
1325 if (getCConv() != LLVM::CConv::C)
1326 p << stringifyCConv(getCConv()) <<
' ';
1328 if (getTailCallKind() != LLVM::TailCallKind::None)
1329 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1338 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1339 p <<
'(' << args <<
')';
1342 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1343 p <<
" vararg(" << *varCalleeType <<
")";
1345 if (!getOpBundleOperands().empty()) {
1348 getOpBundleOperands().getTypes(), getOpBundleTags());
1352 {getCalleeAttrName(), getTailCallKindAttrName(),
1353 getVarCalleeTypeAttrName(), getCConvAttrName(),
1354 getOperandSegmentSizesAttrName(),
1355 getOpBundleSizesAttrName(),
1356 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1357 getResAttrsAttrName()});
1361 p << getOperand(0).getType() <<
", ";
1365 p, args.getTypes(), getArgAttrsAttr(),
1366 false, getResultTypes(), getResAttrsAttr());
1381 types.emplace_back();
1386 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1391 resTypes, resultAttrs)) {
1393 return parser.
emitError(trailingTypesLoc,
1394 "expected direct call to have 1 trailing types");
1395 return parser.
emitError(trailingTypesLoc,
1396 "expected trailing function type");
1399 if (resTypes.size() > 1)
1400 return parser.
emitError(trailingTypesLoc,
1401 "expected function with 0 or 1 result");
1402 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1403 return parser.
emitError(trailingTypesLoc,
1404 "expected a non-void result type");
1410 llvm::append_range(types, argTypes);
1414 if (!resTypes.empty())
1415 result.addTypes(resTypes);
1428 if (failed(*parseResult))
1429 return *parseResult;
1430 operands.push_back(funcPtrOperand);
1439 StringAttr opBundleSizesAttrName) {
1440 unsigned opBundleIndex = 0;
1441 for (
const auto &[operands, types] :
1442 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1443 if (operands.size() != types.size())
1444 return parser.
emitError(loc,
"expected ")
1446 <<
" types for operand bundle operands for operand bundle #"
1447 << opBundleIndex <<
", but actually got " << types.size();
1453 opBundleSizes.reserve(opBundleOperands.size());
1454 for (
const auto &operands : opBundleOperands)
1455 opBundleSizes.push_back(operands.size());
1458 opBundleSizesAttrName,
1470 SymbolRefAttr funcAttr;
1471 TypeAttr varCalleeType;
1479 getCConvAttrName(
result.name),
1484 getTailCallKindAttrName(
result.name),
1487 parser, LLVM::TailCallKind::None)));
1492 bool isDirect = operands.empty();
1505 StringAttr varCalleeTypeAttrName =
1506 CallOp::getVarCalleeTypeAttrName(
result.name);
1518 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1521 if (opBundleTags && !opBundleTags.empty())
1522 result.addAttribute(CallOp::getOpBundleTagsAttrName(
result.name).getValue(),
1532 argAttrs, resultAttrs))
1536 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1538 opBundleOperandTypes,
1539 getOpBundleSizesAttrName(
result.name)))
1542 int32_t numOpBundleOperands = 0;
1543 for (
const auto &operands : opBundleOperands)
1544 numOpBundleOperands += operands.size();
1547 CallOp::getOperandSegmentSizeAttr(),
1549 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1553LLVMFunctionType CallOp::getCalleeFunctionType() {
1554 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1555 return *varCalleeType;
1566 auto calleeType =
func.getFunctionType();
1569 nullptr,
nullptr, normalOps, unwindOps,
1570 nullptr,
nullptr, {}, {}, normal, unwind);
1577 build(builder, state, tys,
1578 nullptr, callee, ops,
nullptr,
1579 nullptr, normalOps, unwindOps,
nullptr,
nullptr, {}, {},
1589 nullptr,
nullptr, normalOps, unwindOps,
1590 nullptr,
nullptr, {}, {}, normal, unwind);
1594 assert(
index < getNumSuccessors() &&
"invalid successor index");
1596 : getUnwindDestOperandsMutable());
1604 return getOperand(0);
1610 auto symRef = cast<SymbolRefAttr>(callee);
1611 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1614 return setOperand(0, cast<Value>(callee));
1618 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1623 getCalleeOperands().size());
1626LogicalResult InvokeOp::verify() {
1630 Block *unwindDest = getUnwindDest();
1631 if (unwindDest->
empty())
1632 return emitError(
"must have at least one operation in unwind destination");
1635 if (!isa<LandingpadOp>(unwindDest->
front()))
1636 return emitError(
"first operation in unwind destination should be a "
1637 "llvm.landingpad operation");
1646 auto callee = getCallee();
1647 bool isDirect = callee.has_value();
1652 if (getCConv() != LLVM::CConv::C)
1653 p << stringifyCConv(getCConv()) <<
' ';
1661 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1668 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1669 p <<
" vararg(" << *varCalleeType <<
")";
1671 if (!getOpBundleOperands().empty()) {
1674 getOpBundleOperands().getTypes(), getOpBundleTags());
1678 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1679 getCConvAttrName(), getVarCalleeTypeAttrName(),
1680 getOpBundleSizesAttrName(),
1681 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1682 getResAttrsAttrName()});
1686 p << getOperand(0).getType() <<
", ";
1688 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1690 false, getResultTypes(), getResAttrsAttr());
1703 SymbolRefAttr funcAttr;
1704 TypeAttr varCalleeType;
1708 Block *normalDest, *unwindDest;
1714 getCConvAttrName(
result.name),
1721 bool isDirect = operands.empty();
1737 StringAttr varCalleeTypeAttrName =
1738 InvokeOp::getVarCalleeTypeAttrName(
result.name);
1750 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1753 if (opBundleTags && !opBundleTags.empty())
1755 InvokeOp::getOpBundleTagsAttrName(
result.name).getValue(),
1765 argAttrs, resultAttrs))
1769 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1772 opBundleOperandTypes,
1773 getOpBundleSizesAttrName(
result.name)))
1776 result.addSuccessors({normalDest, unwindDest});
1777 result.addOperands(normalOperands);
1778 result.addOperands(unwindOperands);
1780 int32_t numOpBundleOperands = 0;
1781 for (
const auto &operands : opBundleOperands)
1782 numOpBundleOperands += operands.size();
1785 InvokeOp::getOperandSegmentSizeAttr(),
1787 static_cast<int32_t>(normalOperands.size()),
1788 static_cast<int32_t>(unwindOperands.size()),
1789 numOpBundleOperands}));
1793LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1794 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1795 return *varCalleeType;
1803LogicalResult LandingpadOp::verify() {
1805 if (LLVMFuncOp
func = (*this)->getParentOfType<LLVMFuncOp>()) {
1806 if (!
func.getPersonality())
1808 "llvm.landingpad needs to be in a function with a personality");
1814 if (!getCleanup() && getOperands().empty())
1815 return emitError(
"landingpad instruction expects at least one clause or "
1816 "cleanup attribute");
1818 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1819 value = getOperand(idx);
1820 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1827 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1830 <<
"global addresses expected as operand to "
1831 "bitcast used in clauses for landingpad";
1839 << idx <<
" is not a known constant - null, addressof, bitcast";
1846 p << (getCleanup() ?
" cleanup " :
" ");
1849 for (
auto value : getOperands()) {
1852 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1853 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1900 Type llvmType = containerType;
1902 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1910 for (
int64_t idx : position) {
1911 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1912 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1913 emitError(
"position out of bounds: ") << idx;
1916 llvmType = arrayType.getElementType();
1917 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1919 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1920 emitError(
"position out of bounds: ") << idx;
1923 llvmType = structType.getBody()[idx];
1925 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1936 for (
int64_t idx : position) {
1937 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1938 llvmType = structType.getBody()[idx];
1940 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1952 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
1953 ShapedType shapedType = elementsAttr.getShapedType();
1954 if (!shapedType.hasRank() || shapedType.getRank() != 1)
1956 if (
index <
static_cast<size_t>(elementsAttr.getNumElements()))
1960 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
1961 if (
index < arrayAttr.getValue().size())
1962 return arrayAttr[
index];
1965 if (isa<ZeroAttr, UndefAttr, PoisonAttr>(attr))
1970OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1971 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
1973 newPos.append(getPosition().begin(), getPosition().end());
1974 setPosition(newPos);
1975 getContainerMutable().set(extractValueOp.getContainer());
1981 for (
int64_t pos : getPosition()) {
1986 return containerAttr;
1989 Value container = getContainer();
1991 while (
auto insertValueOp = container.
getDefiningOp<InsertValueOp>()) {
1993 auto extractPosSize = extractPos.size();
1994 auto insertPosSize = insertPos.size();
1997 if (extractPos == insertPos)
1998 return insertValueOp.getValue();
2012 if (extractPosSize > insertPosSize &&
2013 extractPos.take_front(insertPosSize) == insertPos) {
2014 container = insertValueOp.getValue();
2015 extractPos = extractPos.drop_front(insertPosSize);
2031 if (insertPosSize > extractPosSize &&
2032 extractPos == insertPos.take_front(extractPosSize))
2037 container = insertValueOp.getContainer();
2043 if (container == getContainer())
2045 setPosition(extractPos);
2046 getContainerMutable().assign(container);
2050LogicalResult ExtractValueOp::verify() {
2057 if (getRes().
getType() != valueType)
2058 return emitOpError() <<
"Type mismatch: extracting from "
2059 << getContainer().getType() <<
" should produce "
2060 << valueType <<
" but this op returns "
2061 << getRes().getType();
2067 build(builder, state,
2106 LogicalResult matchAndRewrite(InsertValueOp insertOp,
2107 PatternRewriter &rewriter)
const override {
2108 bool changed =
false;
2114 auto insertBaseIdx = insertOp.getPosition()[0];
2115 for (
auto &use : insertOp->getUses()) {
2116 if (
auto extractOp = dyn_cast<ExtractValueOp>(use.getOwner())) {
2117 auto baseIdx = extractOp.getPosition()[0];
2120 if (baseIdx == insertBaseIdx)
2122 posToExtractOps[baseIdx].push_back(extractOp);
2127 Value nextContainer = insertOp.getContainer();
2128 while (!posToExtractOps.empty()) {
2130 dyn_cast_or_null<InsertValueOp>(nextContainer.
getDefiningOp());
2133 nextContainer = curInsert.getContainer();
2136 auto curInsertBaseIdx = curInsert.getPosition()[0];
2137 auto it = posToExtractOps.find(curInsertBaseIdx);
2138 if (it == posToExtractOps.end())
2142 for (
auto &extractOp : it->second) {
2144 extractOp.getContainerMutable().assign(curInsert);
2149 assert(!it->second.empty());
2151 posToExtractOps.erase(it);
2155 for (
auto &[baseIdx, extracts] : posToExtractOps) {
2156 for (
auto &extractOp : extracts) {
2158 extractOp.getContainerMutable().assign(nextContainer);
2161 assert(!extracts.empty() &&
"Empty list in map");
2171 patterns.
add<ResolveExtractValueSource>(context);
2180 [&](StringRef msg) {
2193LogicalResult InsertValueOp::verify() {
2200 if (getValue().
getType() != valueType)
2201 return emitOpError() <<
"Type mismatch: cannot insert "
2202 << getValue().getType() <<
" into "
2203 << getContainer().getType();
2212LogicalResult ReturnOp::verify() {
2213 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2217 Type expectedType = parent.getFunctionType().getReturnType();
2218 if (llvm::isa<LLVMVoidType>(expectedType)) {
2222 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2226 if (llvm::isa<LLVMVoidType>(expectedType))
2229 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2232 if (expectedType != getArg().
getType()) {
2234 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2245 return dyn_cast_or_null<GlobalOp>(
2250 return dyn_cast_or_null<LLVMFuncOp>(
2255 return dyn_cast_or_null<AliasOp>(
2260 return dyn_cast_or_null<IFuncOp>(
2269 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2270 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2271 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2272 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2274 if (!global && !function && !alias && !ifunc)
2275 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2276 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2278 LLVMPointerType type =
getType();
2279 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2280 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2281 return emitOpError(
"pointer address space must match address space of the "
2282 "referenced global or alias");
2289 return getGlobalNameAttr();
2310 getFunctionNameAttr());
2311 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2312 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2314 if (!function && !alias)
2316 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2319 if (alias.getInitializer()
2320 .walk([&](AddressOfOp addrOp) {
2321 if (addrOp.getGlobal(symbolTable))
2322 return WalkResult::interrupt();
2323 return WalkResult::advance();
2326 return emitOpError(
"must reference an alias to a function");
2329 if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2330 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2332 "target function with 'extern_weak' linkage not allowed");
2340 return DSOLocalEquivalentAttr::get(
getContext(), getFunctionNameAttr());
2348 StringRef symName) {
2351 Region *body =
result.addRegion();
2355LogicalResult ComdatOp::verifyRegions() {
2356 Region &body = getBody();
2357 for (Operation &op : body.
getOps())
2358 if (!isa<ComdatSelectorOp>(op))
2359 return op.emitError(
2360 "only comdat selector symbols can appear in a comdat region");
2370 bool isConstant, Linkage linkage, StringRef name,
2371 Attribute value, uint64_t alignment,
unsigned addrSpace,
2372 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2377 result.addAttribute(getGlobalTypeAttrName(
result.name), TypeAttr::get(type));
2382 result.addAttribute(getValueAttrName(
result.name), value);
2387 result.addAttribute(getThreadLocal_AttrName(
result.name),
2390 result.addAttribute(getComdatAttrName(
result.name), comdat);
2400 LinkageAttr::get(builder.
getContext(), linkage));
2404 result.attributes.append(attrs.begin(), attrs.end());
2406 if (!dbgExprs.empty())
2408 ArrayAttr::get(builder.
getContext(), dbgExprs));
2413template <
typename OpType>
2415 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2416 StringRef visibility = stringifyVisibility(op.getVisibility_());
2417 if (!visibility.empty())
2418 p << visibility <<
' ';
2419 if (op.getThreadLocal_())
2420 p <<
"thread_local ";
2421 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2422 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2434 if (
auto value = getValueOrNull())
2437 if (
auto comdat = getComdat())
2438 p <<
" comdat(" << *comdat <<
')';
2444 {SymbolTable::getSymbolAttrName(),
2445 getGlobalTypeAttrName(), getConstantAttrName(),
2446 getValueAttrName(), getLinkageAttrName(),
2447 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2448 getVisibility_AttrName(), getComdatAttrName()});
2451 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2455 Region &initializer = getInitializerRegion();
2456 if (!initializer.
empty()) {
2463 std::optional<SymbolRefAttr> attr) {
2468 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2469 return op->
emitError() <<
"expected comdat symbol";
2479 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2480 if (blockTags.contains(blockTagOp.getTag())) {
2481 blockTagOp.emitError()
2482 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2483 <<
"' in the same function: ";
2486 blockTags.insert(blockTagOp.getTag());
2495template <
typename OpType>
2501 OpType::getLinkageAttrName(
result.name),
2503 parser, LLVM::Linkage::External)));
2506 result.addAttribute(OpType::getVisibility_AttrName(
result.name),
2509 parser, LLVM::Visibility::Default)));
2512 result.addAttribute(OpType::getThreadLocal_AttrName(
result.name),
2516 result.addAttribute(OpType::getUnnamedAddrAttrName(
result.name),
2519 parser, LLVM::UnnamedAddr::None)));
2556 SymbolRefAttr comdat;
2561 result.addAttribute(getComdatAttrName(
result.name), comdat);
2569 if (types.size() > 1)
2573 if (types.empty()) {
2574 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2576 auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2577 strAttr.getValue().size());
2578 types.push_back(arrayType);
2581 "type can only be omitted for string globals");
2591 result.addAttribute(getGlobalTypeAttrName(
result.name),
2592 TypeAttr::get(types[0]));
2597 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2598 return intValue.getValue().isZero();
2599 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2600 return fpValue.getValue().isZero();
2601 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2603 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2605 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2610LogicalResult GlobalOp::verify() {
2612 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2614 :
llvm::isa<PointerElementTypeInterface>(
getType());
2617 "expects type to be a valid element type for an LLVM global");
2619 return emitOpError(
"must appear at the module level");
2621 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2622 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2623 IntegerType elementType =
2624 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) :
nullptr;
2625 if (!elementType || elementType.getWidth() != 8 ||
2626 type.getNumElements() != strAttr.getValue().size())
2628 "requires an i8 array type of the length equal to that of the string "
2632 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2633 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2635 <<
"this target extension type cannot be used in a global";
2638 return emitOpError() <<
"global with target extension type can only be "
2639 "initialized with zero-initializer";
2642 if (getLinkage() == Linkage::Common) {
2643 if (
Attribute value = getValueOrNull()) {
2646 <<
"expected zero value for '"
2647 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2652 if (getLinkage() == Linkage::Appending) {
2653 if (!llvm::isa<LLVMArrayType>(
getType())) {
2654 return emitOpError() <<
"expected array type for '"
2655 << stringifyLinkage(Linkage::Appending)
2663 std::optional<uint64_t> alignAttr = getAlignment();
2664 if (alignAttr.has_value()) {
2665 uint64_t value = alignAttr.value();
2666 if (!llvm::isPowerOf2_64(value))
2667 return emitError() <<
"alignment attribute is not a power of 2";
2673LogicalResult GlobalOp::verifyRegions() {
2674 if (
Block *
b = getInitializerBlock()) {
2675 ReturnOp ret = cast<ReturnOp>(
b->getTerminator());
2676 if (ret.operand_type_begin() == ret.operand_type_end())
2677 return emitOpError(
"initializer region cannot return void");
2678 if (*ret.operand_type_begin() !=
getType())
2680 << *ret.operand_type_begin() <<
" does not match global type "
2684 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2685 if (!iface || !iface.hasNoEffect())
2686 return op.emitError()
2687 <<
"ops with side effects not allowed in global initializers";
2690 if (getValueOrNull())
2691 return emitOpError(
"cannot have both initializer value and region");
2706 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2709 return op->
emitError(
"data element must be symbol or #llvm.zero");
2722LogicalResult GlobalCtorsOp::verify() {
2726 if (getCtors().size() == getPriorities().size() &&
2727 getCtors().size() == getData().size())
2730 "ctors, priorities, and data must have the same number of elements");
2747LogicalResult GlobalDtorsOp::verify() {
2751 if (getDtors().size() == getPriorities().size() &&
2752 getDtors().size() == getData().size())
2755 "dtors, priorities, and data must have the same number of elements");
2763 Linkage linkage, StringRef name,
bool dsoLocal,
2767 result.addAttribute(getAliasTypeAttrName(
result.name), TypeAttr::get(type));
2772 result.addAttribute(getThreadLocal_AttrName(
result.name),
2776 LinkageAttr::get(builder.
getContext(), linkage));
2777 result.attributes.append(attrs.begin(), attrs.end());
2787 {SymbolTable::getSymbolAttrName(),
2788 getAliasTypeAttrName(), getLinkageAttrName(),
2789 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2790 getVisibility_AttrName()});
2793 p <<
" : " <<
getType() <<
' ';
2819 if (types.size() > 1)
2827 TypeAttr::get(types[0]));
2831LogicalResult AliasOp::verify() {
2833 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2835 :
llvm::isa<PointerElementTypeInterface>(
getType());
2838 "expects type to be a valid element type for an LLVM global alias");
2841 switch (getLinkage()) {
2842 case Linkage::External:
2843 case Linkage::Internal:
2844 case Linkage::Private:
2846 case Linkage::WeakODR:
2847 case Linkage::Linkonce:
2848 case Linkage::LinkonceODR:
2849 case Linkage::AvailableExternally:
2853 <<
"'" << stringifyLinkage(getLinkage())
2854 <<
"' linkage not supported in aliases, available options: private, "
2855 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2856 "available_externally";
2862LogicalResult AliasOp::verifyRegions() {
2863 Block &
b = getInitializerBlock();
2864 auto ret = cast<ReturnOp>(
b.getTerminator());
2865 if (ret.getNumOperands() == 0 ||
2866 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2867 return emitOpError(
"initializer region must always return a pointer");
2870 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2871 if (!iface || !iface.hasNoEffect())
2872 return op.emitError()
2873 <<
"ops with side effects are not allowed in alias initializers";
2879unsigned AliasOp::getAddrSpace() {
2880 Block &initializer = getInitializerBlock();
2882 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2883 return ptrTy.getAddressSpace();
2891 Type iFuncType, StringRef resolverName,
Type resolverType,
2892 Linkage linkage, LLVM::Visibility visibility) {
2893 return build(builder,
result, name, iFuncType, resolverName, resolverType,
2895 UnnamedAddr::None, visibility);
2902 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2903 auto alias = dyn_cast<AliasOp>(symbol);
2905 Block &initBlock = alias.getInitializerBlock();
2907 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
2914 resolver = addrOp.getFunction(symbolTable);
2915 alias = addrOp.getAlias(symbolTable);
2918 return emitOpError(
"must have a function resolver");
2919 Linkage linkage = resolver.getLinkage();
2920 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
2921 return emitOpError(
"resolver must be a definition");
2922 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
2923 return emitOpError(
"resolver must return a pointer");
2924 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
2925 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
2926 return emitOpError(
"resolver has incorrect type");
2930LogicalResult IFuncOp::verify() {
2931 switch (getLinkage()) {
2932 case Linkage::External:
2933 case Linkage::Internal:
2934 case Linkage::Private:
2936 case Linkage::WeakODR:
2937 case Linkage::Linkonce:
2938 case Linkage::LinkonceODR:
2941 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
2942 <<
"' linkage not supported in ifuncs, available "
2943 "options: private, internal, linkonce, weak, "
2944 "linkonce_odr, weak_odr, or external linkage";
2956 auto containerType = v1.
getType();
2960 build(builder, state, vType, v1, v2, mask);
2974 "expected an LLVM compatible vector type");
2985LogicalResult ShuffleVectorOp::verify() {
2987 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2988 return emitOpError(
"expected a splat operation for scalable vectors");
2994OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
2996 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
2997 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
3001 if (getMask().size() != 1 || getMask()[0] != 0)
3012 assert(empty() &&
"function already has an entry block");
3017 LLVMFunctionType type = getFunctionType();
3018 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
3019 entry->
addArgument(type.getParamType(i), getLoc());
3024 StringRef name,
Type type, LLVM::Linkage linkage,
3025 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
3028 std::optional<uint64_t> functionEntryCount) {
3032 result.addAttribute(getFunctionTypeAttrName(
result.name),
3033 TypeAttr::get(type));
3035 LinkageAttr::get(builder.
getContext(), linkage));
3037 CConvAttr::get(builder.
getContext(), cconv));
3038 result.attributes.append(attrs.begin(), attrs.end());
3043 result.addAttribute(getComdatAttrName(
result.name), comdat);
3044 if (functionEntryCount)
3045 result.addAttribute(getFunctionEntryCountAttrName(
result.name),
3048 std::optional<NamedAttribute> duplicate =
result.attributes.findDuplicate();
3049 if (duplicate.has_value()) {
3050 llvm::report_fatal_error(
3051 Twine(
"LLVMFuncOp propagated an attribute that is meant "
3052 "to be constructed by the builder: ") +
3053 duplicate->getName().str());
3056 if (argAttrs.empty())
3059 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
3060 "expected as many argument attribute lists as arguments");
3062 builder,
result, argAttrs, {},
3063 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3074 if (outputs.size() > 1) {
3075 parser.
emitError(loc,
"failed to construct function type: expected zero or "
3076 "one function result");
3082 for (
auto t : inputs) {
3084 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3085 "type for function arguments");
3088 llvmInputs.push_back(t);
3093 outputs.empty() ? LLVMVoidType::get(
b.getContext()) : outputs.front();
3095 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3096 "type for function results")
3100 return LLVMFunctionType::get(llvmOutput, llvmInputs,
3116 parser, LLVM::Linkage::External)));
3119 result.addAttribute(getVisibility_AttrName(
result.name),
3122 parser, LLVM::Visibility::Default)));
3125 result.addAttribute(getUnnamedAddrAttrName(
result.name),
3128 parser, LLVM::UnnamedAddr::None)));
3132 getCConvAttrName(
result.name),
3136 StringAttr nameAttr;
3146 parser,
true, entryArgs, isVariadic, resultTypes,
3151 for (
auto &arg : entryArgs)
3152 argTypes.push_back(arg.type);
3158 result.addAttribute(getFunctionTypeAttrName(
result.name),
3159 TypeAttr::get(type));
3167 auto intTy = IntegerType::get(parser.
getContext(), 32);
3169 getVscaleRangeAttrName(
result.name),
3170 LLVM::VScaleRangeAttr::get(parser.
getContext(),
3171 IntegerAttr::get(intTy, minRange),
3172 IntegerAttr::get(intTy, maxRange)));
3176 SymbolRefAttr comdat;
3181 result.addAttribute(getComdatAttrName(
result.name), comdat);
3188 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3190 auto *body =
result.addRegion();
3201 if (getLinkage() != LLVM::Linkage::External)
3202 p << stringifyLinkage(getLinkage()) <<
' ';
3203 StringRef visibility = stringifyVisibility(getVisibility_());
3204 if (!visibility.empty())
3205 p << visibility <<
' ';
3206 if (
auto unnamedAddr = getUnnamedAddr()) {
3207 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3211 if (getCConv() != LLVM::CConv::C)
3212 p << stringifyCConv(getCConv()) <<
' ';
3216 LLVMFunctionType fnType = getFunctionType();
3219 argTypes.reserve(fnType.getNumParams());
3220 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3221 argTypes.push_back(fnType.getParamType(i));
3223 Type returnType = fnType.getReturnType();
3224 if (!llvm::isa<LLVMVoidType>(returnType))
3225 resTypes.push_back(returnType);
3228 isVarArg(), resTypes);
3231 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3232 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3233 << vscale->getMaxRange().getInt() <<
')';
3236 if (
auto comdat = getComdat())
3237 p <<
" comdat(" << *comdat <<
')';
3241 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3242 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3243 getComdatAttrName(), getUnnamedAddrAttrName(),
3244 getVscaleRangeAttrName()});
3247 Region &body = getBody();
3248 if (!body.empty()) {
3259LogicalResult LLVMFuncOp::verify() {
3260 if (getLinkage() == LLVM::Linkage::Common)
3262 << stringifyLinkage(LLVM::Linkage::Common)
3269 if (getLinkage() != LLVM::Linkage::External &&
3270 getLinkage() != LLVM::Linkage::ExternWeak)
3271 return emitOpError() <<
"external functions must have '"
3272 << stringifyLinkage(LLVM::Linkage::External)
3274 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3280 if (isNoInline() && isAlwaysInline())
3281 return emitError(
"no_inline and always_inline attributes are incompatible");
3283 if (isOptimizeNone() && !isNoInline())
3284 return emitOpError(
"with optimize_none must also be no_inline");
3286 Type landingpadResultTy;
3287 StringRef diagnosticMessage;
3288 bool isLandingpadTypeConsistent =
3290 const auto checkType = [&](
Type type, StringRef errorMessage) {
3291 if (!landingpadResultTy) {
3292 landingpadResultTy = type;
3295 if (landingpadResultTy != type) {
3296 diagnosticMessage = errorMessage;
3302 .Case([&](LandingpadOp landingpad) {
3303 constexpr StringLiteral errorMessage =
3304 "'llvm.landingpad' should have a consistent result type "
3305 "inside a function";
3306 return checkType(landingpad.getType(), errorMessage);
3308 .Case([&](ResumeOp resume) {
3309 constexpr StringLiteral errorMessage =
3310 "'llvm.resume' should have a consistent input type inside a "
3312 return checkType(resume.getValue().getType(), errorMessage);
3315 }).wasInterrupted();
3316 if (!isLandingpadTypeConsistent) {
3317 assert(!diagnosticMessage.empty() &&
3318 "Expecting a non-empty diagnostic message");
3330LogicalResult LLVMFuncOp::verifyRegions() {
3334 unsigned numArguments = getFunctionType().getNumParams();
3335 Block &entryBlock = front();
3336 for (
unsigned i = 0; i < numArguments; ++i) {
3340 << i <<
" is not of LLVM type";
3346Region *LLVMFuncOp::getCallableRegion() {
3375OpFoldResult LLVM::MetadataAsValueOp::fold(FoldAdaptor) {
3376 return getMetadataAttr();
3383LogicalResult LLVM::ZeroOp::verify() {
3384 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3385 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3387 <<
"target extension type does not support zero-initializer";
3409 if (
auto vecType = dyn_cast<VectorType>(t)) {
3410 assert(!vecType.isScalable() &&
3411 "number of elements of a scalable vector type is unknown");
3412 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3414 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3415 return arrayType.getNumElements() *
3423 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3424 type = arrayType.getElementType();
3425 if (
auto vecType = dyn_cast<VectorType>(type))
3426 return vecType.getElementType();
3427 if (
auto tenType = dyn_cast<TensorType>(type))
3428 return tenType.getElementType();
3435 if (
auto vecType = dyn_cast<VectorType>(t)) {
3436 if (vecType.isScalable())
3440 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3448 LLVM::LLVMArrayType arrayType,
3450 if (arrayType.getNumElements() != arrayAttr.size())
3451 return op.emitOpError()
3452 <<
"array attribute size does not match array type size in "
3454 << dim <<
": " << arrayAttr.size() <<
" vs. "
3455 << arrayType.getNumElements();
3460 if (
auto subArrayType =
3461 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3462 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3463 if (elementsVerified.insert(elementAttr).second) {
3464 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3466 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3468 return op.emitOpError()
3469 <<
"nested attribute for sub-array in dimension " << dim
3470 <<
" at index " << idx
3471 <<
" must be a zero, or undef, or array attribute";
3485 Type elementType = arrayType.getElementType();
3486 if (isa<LLVM::LLVMPointerType>(elementType)) {
3487 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3489 LLVM::PoisonAttr>(elementAttr))
3491 return op.emitOpError()
3492 <<
"pointer array element at index " << idx
3493 <<
" must be a flat symbol reference, zero, undef, or poison";
3497 auto structType = dyn_cast<LLVM::LLVMStructType>(elementType);
3499 return op.emitOpError() <<
"for array with an array attribute must have a "
3500 "struct element type";
3504 size_t numStructElements = structType.getBody().size();
3505 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3506 if (elementsVerified.insert(elementAttr).second) {
3507 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3509 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3511 return op.emitOpError()
3512 <<
"nested attribute for struct element at index " << idx
3513 <<
" must be a zero, or undef, or array attribute";
3514 if (subArrayAttr.size() != numStructElements)
3515 return op.emitOpError()
3516 <<
"nested array attribute size for struct element at index "
3517 << idx <<
" must match struct size: " << subArrayAttr.size()
3518 <<
" vs. " << numStructElements;
3525LogicalResult LLVM::ConstantOp::verify() {
3526 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3527 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3528 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3529 !arrayType.getElementType().isInteger(8)) {
3531 << sAttr.getValue().size()
3532 <<
" i8 elements for the string constant";
3536 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3537 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3539 return emitOpError() <<
"expected array attribute for struct type";
3542 if (arrayAttr.size() != elementTypes.size()) {
3543 return emitOpError() <<
"expected array attribute of size "
3544 << elementTypes.size();
3546 for (
auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3548 return emitOpError() <<
"expected struct element types to be floating "
3549 "point type or integer type";
3551 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3552 return emitOpError() <<
"expected element of array attribute to be "
3553 "floating point or integer";
3555 if (cast<TypedAttr>(attr).
getType() != type)
3557 <<
"struct element at index " << i <<
" is of wrong type";
3562 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3563 return emitOpError() <<
"does not support target extension type.";
3574 auto verifyFloatSemantics =
3575 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3576 Type constantElementType) -> LogicalResult {
3577 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3578 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3580 <<
"attribute and type have different float semantics";
3584 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3585 if (isa<IntegerType>(constantElementType)) {
3586 if (!constantElementType.isInteger(floatWidth))
3587 return emitOpError() <<
"expected integer type of width " << floatWidth;
3595 if (isa<IntegerAttr>(getValue())) {
3596 if (!llvm::isa<IntegerType>(
getType()))
3598 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3599 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3600 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3604 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3605 if (!splatElementsAttr)
3607 <<
"scalable vector type requires a splat attribute";
3610 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3611 return emitOpError() <<
"expected vector or array type";
3614 int64_t attrNumElements = elementsAttr.getNumElements();
3617 <<
"type and attribute have a different number of elements: "
3623 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3624 return verifyFloatSemantics(floatType.getFloatSemantics(), resultElmType);
3626 if (isa<IntegerType>(attrElmType) && !isa<IntegerType>(resultElmType)) {
3628 "expected integer element type for integer elements attribute");
3630 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3633 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3636 <<
"expected array or struct type for array attribute";
3643 <<
"only supports integer, float, string or elements attributes";
3649bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3651 auto typedAttr = dyn_cast<TypedAttr>(value);
3658 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3663 if (isBuildableWith(value, type))
3664 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3669OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3677 AtomicOrdering ordering, StringRef syncscope,
3678 unsigned alignment,
bool isVolatile) {
3679 build(builder, state, val.
getType(), binOp,
ptr, val, ordering,
3680 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3683 nullptr,
nullptr,
nullptr);
3686LogicalResult AtomicRMWOp::verify() {
3687 auto valType = getVal().getType();
3688 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3689 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3690 getBinOp() == AtomicBinOp::fminimum ||
3691 getBinOp() == AtomicBinOp::fmaximum ||
3692 getBinOp() == AtomicBinOp::fminimumnum ||
3693 getBinOp() == AtomicBinOp::fmaximumnum) {
3696 return emitOpError(
"expected LLVM IR fixed vector type");
3697 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3700 "expected LLVM IR floating point type for vector element");
3702 return emitOpError(
"expected LLVM IR floating point type");
3704 }
else if (getBinOp() == AtomicBinOp::xchg) {
3707 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3709 auto intType = llvm::dyn_cast<IntegerType>(valType);
3710 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3711 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3713 return emitOpError(
"expected LLVM IR integer type");
3716 if (
static_cast<unsigned>(getOrdering()) <
3717 static_cast<unsigned>(AtomicOrdering::monotonic))
3719 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3731 auto boolType = IntegerType::get(valType.
getContext(), 1);
3732 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3737 AtomicOrdering successOrdering,
3738 AtomicOrdering failureOrdering, StringRef syncscope,
3739 unsigned alignment,
bool isWeak,
bool isVolatile) {
3741 successOrdering, failureOrdering,
3742 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3744 isVolatile,
nullptr,
3745 nullptr,
nullptr,
nullptr);
3748LogicalResult AtomicCmpXchgOp::verify() {
3749 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3751 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3752 auto valType = getVal().getType();
3756 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3757 getFailureOrdering() < AtomicOrdering::monotonic)
3758 return emitOpError(
"ordering must be at least 'monotonic'");
3759 if (getFailureOrdering() == AtomicOrdering::release ||
3760 getFailureOrdering() == AtomicOrdering::acq_rel)
3761 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3770 AtomicOrdering ordering, StringRef syncscope) {
3771 build(builder, state, ordering,
3772 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3775LogicalResult FenceOp::verify() {
3776 if (getOrdering() == AtomicOrdering::not_atomic ||
3777 getOrdering() == AtomicOrdering::unordered ||
3778 getOrdering() == AtomicOrdering::monotonic)
3779 return emitOpError(
"can be given only acquire, release, acq_rel, "
3780 "and seq_cst orderings");
3790template <
class ExtOp>
3792 IntegerType inputType, outputType;
3795 return op.emitError(
3796 "input type is a vector but output type is an integer");
3799 return op.emitError(
"input and output vectors are of incompatible shape");
3802 inputType = cast<IntegerType>(
3803 cast<VectorType>(op.getArg().getType()).getElementType());
3804 outputType = cast<IntegerType>(
3805 cast<VectorType>(op.getResult().getType()).getElementType());
3809 inputType = cast<IntegerType>(op.getArg().getType());
3810 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3812 return op.emitError(
3813 "input type is an integer but output type is a vector");
3816 if (outputType.getWidth() <= inputType.getWidth())
3817 return op.emitError(
"integer width of the output type is smaller or "
3818 "equal to the integer width of the input type");
3829 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3833 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3834 return IntegerAttr::get(
getType(), arg.getValue().zext(targetSize));
3848template <
typename T>
3850 typename T::FoldAdaptor adaptor) {
3852 if (castOp.getArg().getType() == castOp.getType())
3853 return castOp.getArg();
3854 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3856 if (prev.getArg().getType() == castOp.getType())
3857 return prev.getArg();
3859 castOp.getArgMutable().set(prev.getArg());
3860 return Value{castOp};
3865OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3869LogicalResult LLVM::BitcastOp::verify() {
3870 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3872 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3877 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3878 return emitOpError(
"can only cast pointers from and to pointers");
3883 auto isVector = llvm::IsaPred<VectorType>;
3887 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3888 return emitOpError(
"cannot cast pointer to vector of pointers");
3890 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3891 return emitOpError(
"cannot cast vector of pointers to pointer");
3895 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3896 return emitOpError(
"cannot cast pointers of different address spaces, "
3897 "use 'llvm.addrspacecast' instead");
3902LogicalResult LLVM::PtrToAddrOp::verify() {
3909 assert(width &&
"pointers always return an index bitwidth");
3910 if (width != integerType.getWidth())
3911 return emitOpError(
"bit-width of integer result type ")
3912 << integerType <<
" must match the pointer bitwidth (" << *width
3913 <<
") specified in the datalayout";
3922OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3926Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3934 adaptor.getDynamicIndices());
3938 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(
indices[0]))
3939 if (integer.getValue().isZero())
3943 bool changed =
false;
3945 for (
auto iter : llvm::enumerate(
indices)) {
3946 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3949 if (!
indices.isDynamicIndex(iter.index()) || !integer ||
3953 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3954 gepArgs.emplace_back(val);
3956 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3962 gepArgs.emplace_back(integer.getInt());
3970 getDynamicIndicesMutable().assign(dynamicIndices);
3971 setRawConstantIndices(rawConstantIndices);
3972 return Value{*
this};
3978Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3985 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3989 if (
rhs.getValue().getZExtValue() >=
3990 getLhs().
getType().getIntOrFloatBitWidth())
3993 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3997 return IntegerAttr::get(
getType(),
lhs.getValue().shl(
rhs.getValue()));
4005 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4009 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4013 return IntegerAttr::get(
getType(),
lhs.getValue() |
rhs.getValue());
4020LogicalResult CallIntrinsicOp::verify() {
4021 if (!getIntrin().starts_with(
"llvm."))
4022 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
4030 build(builder, state,
TypeRange{}, intrin, args,
4031 FastmathFlagsAttr{},
4038 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4039 build(builder, state,
TypeRange{}, intrin, args,
4046 mlir::Type resultType, mlir::StringAttr intrin,
4048 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
4056 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4057 build(builder, state, resultTypes, intrin, args, fastMathFlags,
4062ParseResult CallIntrinsicOp::parse(
OpAsmParser &parser,
4064 StringAttr intrinAttr;
4074 result.addAttribute(CallIntrinsicOp::getIntrinAttrName(
result.name),
4082 return mlir::failure();
4085 return mlir::failure();
4090 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
4093 if (opBundleTags && !opBundleTags.empty())
4095 CallIntrinsicOp::getOpBundleTagsAttrName(
result.name).getValue(),
4099 return mlir::failure();
4104 operands, argAttrs, resultAttrs))
4108 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
4111 opBundleOperandTypes,
4112 getOpBundleSizesAttrName(
result.name)))
4115 int32_t numOpBundleOperands = 0;
4116 for (
const auto &operands : opBundleOperands)
4117 numOpBundleOperands += operands.size();
4120 CallIntrinsicOp::getOperandSegmentSizeAttr(),
4122 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
4124 return mlir::success();
4132 p <<
"(" << args <<
")";
4135 if (!getOpBundleOperands().empty()) {
4138 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
4142 {getOperandSegmentSizesAttrName(),
4143 getOpBundleSizesAttrName(), getIntrinAttrName(),
4144 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
4145 getResAttrsAttrName()});
4151 p, args.
getTypes(), getArgAttrsAttr(),
4152 false, getResultTypes(), getResAttrsAttr());
4159LogicalResult LinkerOptionsOp::verify() {
4162 return emitOpError(
"must appear at the module level");
4170LogicalResult ModuleFlagsOp::verify() {
4173 return emitOpError(
"must appear at the module level");
4175 if (!isa<ModuleFlagAttr>(flag))
4176 return emitOpError(
"expected a module flag attribute");
4184void InlineAsmOp::getEffects(
4187 if (getHasSideEffects()) {
4200 getBlockAddr().getFunction());
4201 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
4204 return emitOpError(
"must reference a function defined by 'llvm.func'");
4214BlockTagOp BlockAddressOp::getBlockTagOp() {
4219 auto funcOp = dyn_cast<LLVMFuncOp>(sym);
4222 BlockTagOp blockTagOp =
nullptr;
4223 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4224 if (labelOp.getTag() == getBlockAddr().getTag()) {
4225 blockTagOp = labelOp;
4233LogicalResult BlockAddressOp::verify() {
4234 if (!getBlockTagOp())
4236 "expects an existing block label target in the referenced function");
4243OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4250 assert(
index < getNumSuccessors() &&
"invalid successor index");
4262 rangeSegments.push_back(range.size());
4276 Block *destination = nullptr;
4277 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4278 SmallVector<Type> operandTypes;
4280 if (parser.parseSuccessor(destination).failed())
4283 if (succeeded(parser.parseOptionalLParen())) {
4284 if (failed(parser.parseOperandList(
4285 operands, OpAsmParser::Delimiter::None)) ||
4286 failed(parser.parseColonTypeList(operandTypes)) ||
4287 failed(parser.parseRParen()))
4290 succOperandBlocks.push_back(destination);
4291 succOperands.emplace_back(operands);
4292 succOperandsTypes.emplace_back(operandTypes);
4295 "successor blocks")))
4306 llvm::zip(succs, succOperands),
4312 if (!succOperands.empty())
4321LogicalResult LLVM::SincosOp::verify() {
4322 auto operandType = getOperand().getType();
4323 auto resultType = getResult().getType();
4324 auto resultStructType =
4325 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4326 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4327 resultStructType.getBody()[0] != operandType ||
4328 resultStructType.getBody()[1] != operandType) {
4329 return emitOpError(
"expected result type to be an homogeneous struct with "
4330 "two elements matching the operand type, but got ")
4342 return build(builder, state, cond, {},
4354 return build(builder, state, cond,
"align",
ValueRange{
ptr, align});
4360 return build(builder, state, cond,
"separate_storage",
4370LogicalResult LLVM::masked_gather::verify() {
4371 auto ptrsVectorType = getPtrs().getType();
4372 Type expectedPtrsVectorType =
4377 if (ptrsVectorType != expectedPtrsVectorType)
4378 return emitOpError(
"expected operand #1 type to be ")
4379 << expectedPtrsVectorType;
4387LogicalResult LLVM::masked_scatter::verify() {
4388 auto ptrsVectorType = getPtrs().getType();
4389 Type expectedPtrsVectorType =
4394 if (ptrsVectorType != expectedPtrsVectorType)
4395 return emitOpError(
"expected operand #2 type to be ")
4396 << expectedPtrsVectorType;
4409 build(builder, state, resTys,
ptr, mask, passthru, argAttrs,
4417void LLVM::masked_compressstore::build(
OpBuilder &builder,
4422 build(builder, state, value,
ptr, mask, argAttrs,
4430LogicalResult InlineAsmOp::verify() {
4431 if (!getTailCallKindAttr())
4434 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4436 "tail call kind 'musttail' is not supported by this operation");
4446 Value divisor = getRhs();
4461 Value divisor = getRhs();
4473void LLVMDialect::initialize() {
4474 registerAttributes();
4477 addTypes<LLVMVoidType,
4479 LLVMMetadataType>();
4485#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4489#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4494 allowUnknownOperations();
4495 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4499#define GET_OP_CLASSES
4500#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4502#define GET_OP_CLASSES
4503#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4505LogicalResult LLVMDialect::verifyDataLayoutString(
4508 llvm::DataLayout::parse(descr);
4509 if (maybeDataLayout)
4512 std::string message;
4513 llvm::raw_string_ostream messageStream(message);
4514 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4515 reportError(
"invalid data layout descriptor: " + message);
4520LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4526 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4528 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4529 return verifyDataLayoutString(
4530 stringAttr.getValue(),
4531 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4534 << LLVM::LLVMDialect::getDataLayoutAttrName()
4535 <<
"' to be a string attributes";
4538LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4546 StringAttr name = paramAttr.
getName();
4548 auto checkUnitAttrType = [&]() -> LogicalResult {
4549 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4550 return op->
emitError() << name <<
" should be a unit attribute";
4553 auto checkTypeAttrType = [&]() -> LogicalResult {
4554 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4555 return op->
emitError() << name <<
" should be a type attribute";
4558 auto checkIntegerAttrType = [&]() -> LogicalResult {
4559 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4560 return op->
emitError() << name <<
" should be an integer attribute";
4563 auto checkPointerType = [&]() -> LogicalResult {
4564 if (!llvm::isa<LLVMPointerType>(paramType))
4566 << name <<
" attribute attached to non-pointer LLVM type";
4569 auto checkIntegerType = [&]() -> LogicalResult {
4570 if (!llvm::isa<IntegerType>(paramType))
4572 << name <<
" attribute attached to non-integer LLVM type";
4575 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4576 if (
failed(checkPointerType()))
4583 if (name == LLVMDialect::getNoAliasAttrName() ||
4584 name == LLVMDialect::getReadonlyAttrName() ||
4585 name == LLVMDialect::getReadnoneAttrName() ||
4586 name == LLVMDialect::getWriteOnlyAttrName() ||
4587 name == LLVMDialect::getNestAttrName() ||
4588 name == LLVMDialect::getNoCaptureAttrName() ||
4589 name == LLVMDialect::getNoFreeAttrName() ||
4590 name == LLVMDialect::getNonNullAttrName()) {
4591 if (
failed(checkUnitAttrType()))
4593 if (verifyValueType &&
failed(checkPointerType()))
4599 if (name == LLVMDialect::getStructRetAttrName() ||
4600 name == LLVMDialect::getByValAttrName() ||
4601 name == LLVMDialect::getByRefAttrName() ||
4602 name == LLVMDialect::getElementTypeAttrName() ||
4603 name == LLVMDialect::getInAllocaAttrName() ||
4604 name == LLVMDialect::getPreallocatedAttrName()) {
4605 if (
failed(checkTypeAttrType()))
4607 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4613 if (name == LLVMDialect::getSExtAttrName() ||
4614 name == LLVMDialect::getZExtAttrName()) {
4615 if (
failed(checkUnitAttrType()))
4617 if (verifyValueType &&
failed(checkIntegerType()))
4623 if (name == LLVMDialect::getAlignAttrName() ||
4624 name == LLVMDialect::getDereferenceableAttrName() ||
4625 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4626 if (
failed(checkIntegerAttrType()))
4628 if (verifyValueType &&
failed(checkPointerType()))
4634 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4635 if (
failed(checkIntegerAttrType()))
4641 if (name == LLVMDialect::getNoUndefAttrName() ||
4642 name == LLVMDialect::getInRegAttrName() ||
4643 name == LLVMDialect::getReturnedAttrName())
4644 return checkUnitAttrType();
4650LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4654 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4657 Type argType = funcOp.getArgumentTypes()[argIdx];
4659 return verifyParameterAttribute(op, argType, argAttr);
4662LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4666 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4669 Type resType = funcOp.getResultTypes()[resIdx];
4673 if (llvm::isa<LLVMVoidType>(resType))
4674 return op->
emitError() <<
"cannot attach result attributes to functions "
4675 "with a void return";
4679 auto name = resAttr.
getName();
4680 if (name == LLVMDialect::getAllocAlignAttrName() ||
4681 name == LLVMDialect::getAllocatedPointerAttrName() ||
4682 name == LLVMDialect::getByValAttrName() ||
4683 name == LLVMDialect::getByRefAttrName() ||
4684 name == LLVMDialect::getInAllocaAttrName() ||
4685 name == LLVMDialect::getNestAttrName() ||
4686 name == LLVMDialect::getNoCaptureAttrName() ||
4687 name == LLVMDialect::getNoFreeAttrName() ||
4688 name == LLVMDialect::getPreallocatedAttrName() ||
4689 name == LLVMDialect::getReadnoneAttrName() ||
4690 name == LLVMDialect::getReadonlyAttrName() ||
4691 name == LLVMDialect::getReturnedAttrName() ||
4692 name == LLVMDialect::getStackAlignmentAttrName() ||
4693 name == LLVMDialect::getStructRetAttrName() ||
4694 name == LLVMDialect::getWriteOnlyAttrName())
4695 return op->
emitError() << name <<
" is not a valid result attribute";
4696 return verifyParameterAttribute(op, resType, resAttr);
4704 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4705 if (isa<LLVM::LLVMPointerType>(type))
4706 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4707 if (isa<LLVM::UndefAttr>(value))
4708 return LLVM::UndefOp::create(builder, loc, type);
4709 if (isa<LLVM::PoisonAttr>(value))
4710 return LLVM::PoisonOp::create(builder, loc, type);
4711 if (isa<LLVM::ZeroAttr>(value))
4712 return LLVM::ZeroOp::create(builder, loc, type);
4713 if (isa<LLVM::MDStringAttr, LLVM::MDConstantAttr, LLVM::MDFuncAttr,
4714 LLVM::MDNodeAttr>(value))
4715 if (isa<LLVM::LLVMMetadataType>(type))
4716 return LLVM::MetadataAsValueOp::create(builder, loc, type, value);
4718 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4726 StringRef name, StringRef value,
4727 LLVM::Linkage linkage) {
4730 "expected builder to point to a block constrained in an op");
4732 builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4733 assert(module &&
"builder points to an op outside of a module");
4738 auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4739 auto global = LLVM::GlobalOp::create(
4740 moduleBuilder, loc, type,
true, linkage, name,
4743 LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4746 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4747 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4759 module = module->getParentOp();
4760 assert(module &&
"unexpected operation outside of a module");
p<< " : "<< getMemRefType()<< ", "<< getType();}static LogicalResult verifyVectorMemoryOp(Operation *op, MemRefType memrefType, VectorType vectorType) { if(memrefType.getElementType() !=vectorType.getElementType()) return op-> emitOpError("requires memref and vector types of the same elemental type")
Given a list of lists of parsed operands, populates uniqueOperands with unique operands.
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
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 parseSwitchOpCases(OpAsmParser &parser, Type flagType, DenseIntElementsAttr &caseValues, SmallVectorImpl< Block * > &caseDestinations, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand > > &caseOperands, SmallVectorImpl< SmallVector< Type > > &caseOperandTypes)
<cases> ::= [ (case (, case )* )?
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 std::optional< ParseResult > parseOpBundles(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand > > &opBundleOperands, SmallVector< SmallVector< Type > > &opBundleOperandTypes, ArrayAttr &opBundleTags)
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 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 ParseResult parseOneOpBundle(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand > > &opBundleOperands, SmallVector< SmallVector< Type > > &opBundleOperandTypes, SmallVector< Attribute > &opBundleTags)
static Type getElementType(Type type)
Determine the element type of type.
static void printIndirectBrOpSucessors(OpAsmPrinter &p, IndirectBrOp op, Type flagType, SuccessorRange succs, OperandRangeRange succOperands, const TypeRangeRange &succOperandsTypes)
static ParseResult resolveOpBundleOperands(OpAsmParser &parser, SMLoc loc, OperationState &state, ArrayRef< SmallVector< OpAsmParser::UnresolvedOperand > > opBundleOperands, ArrayRef< SmallVector< Type > > opBundleOperandTypes, StringAttr opBundleSizesAttrName)
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 SmallVector< Type, 1 > getCallOpResultTypes(LLVMFunctionType calleeType)
Gets the MLIR Op-like result types of a LLVMFunctionType.
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 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 Attribute extractElementAt(Attribute attr, size_t index)
Extracts the element at the given index from an attribute.
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
static void printInsertExtractValueElementType(AsmPrinter &printer, Operation *op, Type valueType, Type containerType, DenseI64ArrayAttr position)
Nothing to print for an inferred type.
static ParseResult parseIndirectBrOpSucessors(OpAsmParser &parser, Type &flagType, SmallVectorImpl< Block * > &succOperandBlocks, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand > > &succOperands, SmallVectorImpl< SmallVector< Type > > &succOperandsTypes)
#define REGISTER_ENUM_TYPE(Ty)
static std::string diag(const llvm::Value &value)
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 Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual 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)
virtual void printNewline()
Print a newline and indent the printer to the start of the current operation/attribute/type.
Attributes are known-constant values of operations.
MLIRContext * getContext() const
Return the context this attribute belongs to.
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)
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
MLIRContext * getContext() const
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.
std::optional< uint64_t > getTypeIndexBitwidth(Type t) const
Returns the bitwidth that should be used when performing index computations for the given pointer-lik...
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
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.
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.
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 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...
OperandRange operand_range
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
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()
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
void modifyOpInPlace(Operation *root, CallableT &&callable)
This method is a utility wrapper around an in-place modification of an operation.
This class represents a specific instance of an effect.
static DerivedEffect * get()
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)
ArrayRef< T > asArrayRef() const
A named class for passing around the variadic flag.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
void addBytecodeInterface(LLVMDialect *dialect)
Add the interfaces necessary for encoding the LLVM dialect components in bytecode.
Value createGlobalString(Location loc, OpBuilder &builder, StringRef name, StringRef value, Linkage linkage)
Create an LLVM global containing the string "value" at the module containing surrounding the insertio...
Operation * parentLLVMModule(Operation *op)
Lookup parent Module satisfying LLVM conditions on the Module Operation.
Type getVectorType(Type elementType, unsigned numElements, bool isScalable=false)
Creates an LLVM dialect-compatible vector type with the given element type and length.
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
bool isCompatibleOuterType(Type type)
Returns true if the given outer type is compatible with the LLVM dialect without checking its potenti...
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
constexpr int kGEPConstantBitWidth
Bit-width of a 'GEPConstantIndex' within GEPArg.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
bool isTypeCompatibleWithAtomicOp(Type type, const DataLayout &dataLayout)
Returns true if the given type is supported by atomic operations.
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Speculatability
This enum is returned from the getSpeculatability method in the ConditionallySpeculatable op interfac...
constexpr auto Speculatable
constexpr auto NotSpeculatable
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.
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.
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...
detail::DenseArrayAttrImpl< int64_t > DenseI64ArrayAttr
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
detail::constant_int_range_predicate_matcher m_IntRangeWithoutNegOneS()
Matches a constant scalar / vector splat / tensor splat integer or a signed integer range that does n...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
detail::DenseArrayAttrImpl< int32_t > DenseI32ArrayAttr
llvm::TypeSwitch< T, ResultT > TypeSwitch
detail::constant_int_range_predicate_matcher m_IntRangeWithoutZeroS()
Matches a constant scalar / vector splat / tensor splat integer or a signed integer range that does n...
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
llvm::function_ref< Fn > function_ref
detail::constant_int_range_predicate_matcher m_IntRangeWithoutZeroU()
Matches a constant scalar / vector splat / tensor splat integer or a unsigned integer range that does...
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.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
OpRewritePattern(MLIRContext *context, PatternBenefit benefit=1, ArrayRef< StringRef > generatedNames={})
Patterns must specify the root operation name they match against, and can also specify the benefit of...
This represents an operation in an abstracted form, suitable for use with the builder APIs.
T & getOrAddProperties()
Get (or create) the 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.