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();
1261 <<
"' does not reference a valid LLVM function or IFunc";
1265 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1267 return emitOpError(
"callee does not have a functional type: ") << fnType;
1269 if (funcType.isVarArg() && !getVarCalleeType())
1270 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1274 if (!funcType.isVarArg() &&
1275 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1276 return emitOpError() <<
"incorrect number of operands ("
1277 << (getCalleeOperands().size() - isIndirect)
1278 <<
") for callee (expecting: "
1279 << funcType.getNumParams() <<
")";
1281 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1282 return emitOpError() <<
"incorrect number of operands ("
1283 << (getCalleeOperands().size() - isIndirect)
1284 <<
") for varargs callee (expecting at least: "
1285 << funcType.getNumParams() <<
")";
1287 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1288 if (getOperand(i + isIndirect).
getType() != funcType.getParamType(i))
1289 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1290 << getOperand(i + isIndirect).getType()
1291 <<
" != " << funcType.getParamType(i);
1293 if (getNumResults() == 0 &&
1294 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1295 return emitOpError() <<
"expected function call to produce a value";
1297 if (getNumResults() != 0 &&
1298 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1300 <<
"calling function with void result must not produce values";
1302 if (getNumResults() > 1)
1304 <<
"expected LLVM function call to produce 0 or 1 result";
1306 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1307 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1308 <<
" != " << funcType.getReturnType();
1314 auto callee = getCallee();
1315 bool isDirect = callee.has_value();
1320 if (getCConv() != LLVM::CConv::C)
1321 p << stringifyCConv(getCConv()) <<
' ';
1323 if (getTailCallKind() != LLVM::TailCallKind::None)
1324 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1333 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1334 p <<
'(' << args <<
')';
1337 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1338 p <<
" vararg(" << *varCalleeType <<
")";
1340 if (!getOpBundleOperands().empty()) {
1343 getOpBundleOperands().getTypes(), getOpBundleTags());
1347 {getCalleeAttrName(), getTailCallKindAttrName(),
1348 getVarCalleeTypeAttrName(), getCConvAttrName(),
1349 getOperandSegmentSizesAttrName(),
1350 getOpBundleSizesAttrName(),
1351 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1352 getResAttrsAttrName()});
1356 p << getOperand(0).getType() <<
", ";
1360 p, args.getTypes(), getArgAttrsAttr(),
1361 false, getResultTypes(), getResAttrsAttr());
1376 types.emplace_back();
1381 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1386 resTypes, resultAttrs)) {
1388 return parser.
emitError(trailingTypesLoc,
1389 "expected direct call to have 1 trailing types");
1390 return parser.
emitError(trailingTypesLoc,
1391 "expected trailing function type");
1394 if (resTypes.size() > 1)
1395 return parser.
emitError(trailingTypesLoc,
1396 "expected function with 0 or 1 result");
1397 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1398 return parser.
emitError(trailingTypesLoc,
1399 "expected a non-void result type");
1405 llvm::append_range(types, argTypes);
1409 if (!resTypes.empty())
1410 result.addTypes(resTypes);
1423 if (failed(*parseResult))
1424 return *parseResult;
1425 operands.push_back(funcPtrOperand);
1434 StringAttr opBundleSizesAttrName) {
1435 unsigned opBundleIndex = 0;
1436 for (
const auto &[operands, types] :
1437 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1438 if (operands.size() != types.size())
1439 return parser.
emitError(loc,
"expected ")
1441 <<
" types for operand bundle operands for operand bundle #"
1442 << opBundleIndex <<
", but actually got " << types.size();
1448 opBundleSizes.reserve(opBundleOperands.size());
1449 for (
const auto &operands : opBundleOperands)
1450 opBundleSizes.push_back(operands.size());
1453 opBundleSizesAttrName,
1465 SymbolRefAttr funcAttr;
1466 TypeAttr varCalleeType;
1474 getCConvAttrName(
result.name),
1479 getTailCallKindAttrName(
result.name),
1482 parser, LLVM::TailCallKind::None)));
1487 bool isDirect = operands.empty();
1500 StringAttr varCalleeTypeAttrName =
1501 CallOp::getVarCalleeTypeAttrName(
result.name);
1513 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1516 if (opBundleTags && !opBundleTags.empty())
1517 result.addAttribute(CallOp::getOpBundleTagsAttrName(
result.name).getValue(),
1527 argAttrs, resultAttrs))
1531 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1533 opBundleOperandTypes,
1534 getOpBundleSizesAttrName(
result.name)))
1537 int32_t numOpBundleOperands = 0;
1538 for (
const auto &operands : opBundleOperands)
1539 numOpBundleOperands += operands.size();
1542 CallOp::getOperandSegmentSizeAttr(),
1544 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1548LLVMFunctionType CallOp::getCalleeFunctionType() {
1549 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1550 return *varCalleeType;
1561 auto calleeType =
func.getFunctionType();
1564 nullptr,
nullptr, normalOps, unwindOps,
1565 nullptr,
nullptr, {}, {}, normal, unwind);
1572 build(builder, state, tys,
1573 nullptr, callee, ops,
nullptr,
1574 nullptr, normalOps, unwindOps,
nullptr,
nullptr, {}, {},
1584 nullptr,
nullptr, normalOps, unwindOps,
1585 nullptr,
nullptr, {}, {}, normal, unwind);
1589 assert(
index < getNumSuccessors() &&
"invalid successor index");
1591 : getUnwindDestOperandsMutable());
1599 return getOperand(0);
1605 auto symRef = cast<SymbolRefAttr>(callee);
1606 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1609 return setOperand(0, cast<Value>(callee));
1613 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1618 getCalleeOperands().size());
1621LogicalResult InvokeOp::verify() {
1625 Block *unwindDest = getUnwindDest();
1626 if (unwindDest->
empty())
1627 return emitError(
"must have at least one operation in unwind destination");
1630 if (!isa<LandingpadOp>(unwindDest->
front()))
1631 return emitError(
"first operation in unwind destination should be a "
1632 "llvm.landingpad operation");
1641 auto callee = getCallee();
1642 bool isDirect = callee.has_value();
1647 if (getCConv() != LLVM::CConv::C)
1648 p << stringifyCConv(getCConv()) <<
' ';
1656 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1663 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1664 p <<
" vararg(" << *varCalleeType <<
")";
1666 if (!getOpBundleOperands().empty()) {
1669 getOpBundleOperands().getTypes(), getOpBundleTags());
1673 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1674 getCConvAttrName(), getVarCalleeTypeAttrName(),
1675 getOpBundleSizesAttrName(),
1676 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1677 getResAttrsAttrName()});
1681 p << getOperand(0).getType() <<
", ";
1683 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1685 false, getResultTypes(), getResAttrsAttr());
1698 SymbolRefAttr funcAttr;
1699 TypeAttr varCalleeType;
1703 Block *normalDest, *unwindDest;
1709 getCConvAttrName(
result.name),
1716 bool isDirect = operands.empty();
1732 StringAttr varCalleeTypeAttrName =
1733 InvokeOp::getVarCalleeTypeAttrName(
result.name);
1745 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1748 if (opBundleTags && !opBundleTags.empty())
1750 InvokeOp::getOpBundleTagsAttrName(
result.name).getValue(),
1760 argAttrs, resultAttrs))
1764 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1767 opBundleOperandTypes,
1768 getOpBundleSizesAttrName(
result.name)))
1771 result.addSuccessors({normalDest, unwindDest});
1772 result.addOperands(normalOperands);
1773 result.addOperands(unwindOperands);
1775 int32_t numOpBundleOperands = 0;
1776 for (
const auto &operands : opBundleOperands)
1777 numOpBundleOperands += operands.size();
1780 InvokeOp::getOperandSegmentSizeAttr(),
1782 static_cast<int32_t>(normalOperands.size()),
1783 static_cast<int32_t>(unwindOperands.size()),
1784 numOpBundleOperands}));
1788LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1789 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1790 return *varCalleeType;
1798LogicalResult LandingpadOp::verify() {
1800 if (LLVMFuncOp
func = (*this)->getParentOfType<LLVMFuncOp>()) {
1801 if (!
func.getPersonality())
1803 "llvm.landingpad needs to be in a function with a personality");
1809 if (!getCleanup() && getOperands().empty())
1810 return emitError(
"landingpad instruction expects at least one clause or "
1811 "cleanup attribute");
1813 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1814 value = getOperand(idx);
1815 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1822 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1825 <<
"global addresses expected as operand to "
1826 "bitcast used in clauses for landingpad";
1834 << idx <<
" is not a known constant - null, addressof, bitcast";
1841 p << (getCleanup() ?
" cleanup " :
" ");
1844 for (
auto value : getOperands()) {
1847 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1848 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1895 Type llvmType = containerType;
1897 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1905 for (
int64_t idx : position) {
1906 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1907 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1908 emitError(
"position out of bounds: ") << idx;
1911 llvmType = arrayType.getElementType();
1912 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1914 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1915 emitError(
"position out of bounds: ") << idx;
1918 llvmType = structType.getBody()[idx];
1920 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1931 for (
int64_t idx : position) {
1932 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1933 llvmType = structType.getBody()[idx];
1935 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1946 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
1947 if (
index <
static_cast<size_t>(elementsAttr.getNumElements()))
1951 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
1952 if (
index < arrayAttr.getValue().size())
1953 return arrayAttr[
index];
1956 if (isa<ZeroAttr, UndefAttr, PoisonAttr>(attr))
1961OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1962 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
1964 newPos.append(getPosition().begin(), getPosition().end());
1965 setPosition(newPos);
1966 getContainerMutable().set(extractValueOp.getContainer());
1972 for (
int64_t pos : getPosition()) {
1977 return containerAttr;
1980 Value container = getContainer();
1982 while (
auto insertValueOp = container.
getDefiningOp<InsertValueOp>()) {
1984 auto extractPosSize = extractPos.size();
1985 auto insertPosSize = insertPos.size();
1988 if (extractPos == insertPos)
1989 return insertValueOp.getValue();
2003 if (extractPosSize > insertPosSize &&
2004 extractPos.take_front(insertPosSize) == insertPos) {
2005 container = insertValueOp.getValue();
2006 extractPos = extractPos.drop_front(insertPosSize);
2022 if (insertPosSize > extractPosSize &&
2023 extractPos == insertPos.take_front(extractPosSize))
2028 container = insertValueOp.getContainer();
2034 if (container == getContainer())
2036 setPosition(extractPos);
2037 getContainerMutable().assign(container);
2041LogicalResult ExtractValueOp::verify() {
2048 if (getRes().
getType() != valueType)
2049 return emitOpError() <<
"Type mismatch: extracting from "
2050 << getContainer().getType() <<
" should produce "
2051 << valueType <<
" but this op returns "
2052 << getRes().getType();
2058 build(builder, state,
2097 LogicalResult matchAndRewrite(InsertValueOp insertOp,
2098 PatternRewriter &rewriter)
const override {
2099 bool changed =
false;
2105 auto insertBaseIdx = insertOp.getPosition()[0];
2106 for (
auto &use : insertOp->getUses()) {
2107 if (
auto extractOp = dyn_cast<ExtractValueOp>(use.getOwner())) {
2108 auto baseIdx = extractOp.getPosition()[0];
2111 if (baseIdx == insertBaseIdx)
2113 posToExtractOps[baseIdx].push_back(extractOp);
2118 Value nextContainer = insertOp.getContainer();
2119 while (!posToExtractOps.empty()) {
2121 dyn_cast_or_null<InsertValueOp>(nextContainer.
getDefiningOp());
2124 nextContainer = curInsert.getContainer();
2127 auto curInsertBaseIdx = curInsert.getPosition()[0];
2128 auto it = posToExtractOps.find(curInsertBaseIdx);
2129 if (it == posToExtractOps.end())
2133 for (
auto &extractOp : it->second) {
2135 extractOp.getContainerMutable().assign(curInsert);
2140 assert(!it->second.empty());
2142 posToExtractOps.erase(it);
2146 for (
auto &[baseIdx, extracts] : posToExtractOps) {
2147 for (
auto &extractOp : extracts) {
2149 extractOp.getContainerMutable().assign(nextContainer);
2152 assert(!extracts.empty() &&
"Empty list in map");
2162 patterns.
add<ResolveExtractValueSource>(context);
2171 [&](StringRef msg) {
2184LogicalResult InsertValueOp::verify() {
2191 if (getValue().
getType() != valueType)
2192 return emitOpError() <<
"Type mismatch: cannot insert "
2193 << getValue().getType() <<
" into "
2194 << getContainer().getType();
2203LogicalResult ReturnOp::verify() {
2204 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2208 Type expectedType = parent.getFunctionType().getReturnType();
2209 if (llvm::isa<LLVMVoidType>(expectedType)) {
2213 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2217 if (llvm::isa<LLVMVoidType>(expectedType))
2220 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2223 if (expectedType != getArg().
getType()) {
2225 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2236 return dyn_cast_or_null<GlobalOp>(
2241 return dyn_cast_or_null<LLVMFuncOp>(
2246 return dyn_cast_or_null<AliasOp>(
2251 return dyn_cast_or_null<IFuncOp>(
2260 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2261 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2262 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2263 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2265 if (!global && !function && !alias && !ifunc)
2266 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2267 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2269 LLVMPointerType type =
getType();
2270 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2271 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2272 return emitOpError(
"pointer address space must match address space of the "
2273 "referenced global or alias");
2280 return getGlobalNameAttr();
2301 getFunctionNameAttr());
2302 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2303 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2305 if (!function && !alias)
2307 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2310 if (alias.getInitializer()
2311 .walk([&](AddressOfOp addrOp) {
2312 if (addrOp.getGlobal(symbolTable))
2313 return WalkResult::interrupt();
2314 return WalkResult::advance();
2317 return emitOpError(
"must reference an alias to a function");
2320 if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2321 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2323 "target function with 'extern_weak' linkage not allowed");
2331 return DSOLocalEquivalentAttr::get(
getContext(), getFunctionNameAttr());
2339 StringRef symName) {
2342 Region *body =
result.addRegion();
2346LogicalResult ComdatOp::verifyRegions() {
2347 Region &body = getBody();
2348 for (Operation &op : body.
getOps())
2349 if (!isa<ComdatSelectorOp>(op))
2350 return op.emitError(
2351 "only comdat selector symbols can appear in a comdat region");
2361 bool isConstant, Linkage linkage, StringRef name,
2362 Attribute value, uint64_t alignment,
unsigned addrSpace,
2363 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2368 result.addAttribute(getGlobalTypeAttrName(
result.name), TypeAttr::get(type));
2373 result.addAttribute(getValueAttrName(
result.name), value);
2378 result.addAttribute(getThreadLocal_AttrName(
result.name),
2381 result.addAttribute(getComdatAttrName(
result.name), comdat);
2391 LinkageAttr::get(builder.
getContext(), linkage));
2395 result.attributes.append(attrs.begin(), attrs.end());
2397 if (!dbgExprs.empty())
2399 ArrayAttr::get(builder.
getContext(), dbgExprs));
2404template <
typename OpType>
2406 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2407 StringRef visibility = stringifyVisibility(op.getVisibility_());
2408 if (!visibility.empty())
2409 p << visibility <<
' ';
2410 if (op.getThreadLocal_())
2411 p <<
"thread_local ";
2412 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2413 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2425 if (
auto value = getValueOrNull())
2428 if (
auto comdat = getComdat())
2429 p <<
" comdat(" << *comdat <<
')';
2435 {SymbolTable::getSymbolAttrName(),
2436 getGlobalTypeAttrName(), getConstantAttrName(),
2437 getValueAttrName(), getLinkageAttrName(),
2438 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2439 getVisibility_AttrName(), getComdatAttrName()});
2442 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2446 Region &initializer = getInitializerRegion();
2447 if (!initializer.
empty()) {
2454 std::optional<SymbolRefAttr> attr) {
2459 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2460 return op->
emitError() <<
"expected comdat symbol";
2470 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2471 if (blockTags.contains(blockTagOp.getTag())) {
2472 blockTagOp.emitError()
2473 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2474 <<
"' in the same function: ";
2477 blockTags.insert(blockTagOp.getTag());
2486template <
typename OpType>
2492 OpType::getLinkageAttrName(
result.name),
2494 parser, LLVM::Linkage::External)));
2497 result.addAttribute(OpType::getVisibility_AttrName(
result.name),
2500 parser, LLVM::Visibility::Default)));
2503 result.addAttribute(OpType::getThreadLocal_AttrName(
result.name),
2507 result.addAttribute(OpType::getUnnamedAddrAttrName(
result.name),
2510 parser, LLVM::UnnamedAddr::None)));
2547 SymbolRefAttr comdat;
2552 result.addAttribute(getComdatAttrName(
result.name), comdat);
2560 if (types.size() > 1)
2564 if (types.empty()) {
2565 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2567 auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2568 strAttr.getValue().size());
2569 types.push_back(arrayType);
2572 "type can only be omitted for string globals");
2582 result.addAttribute(getGlobalTypeAttrName(
result.name),
2583 TypeAttr::get(types[0]));
2588 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2589 return intValue.getValue().isZero();
2590 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2591 return fpValue.getValue().isZero();
2592 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2594 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2596 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2601LogicalResult GlobalOp::verify() {
2603 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2604 LLVMMetadataType, LLVMLabelType>(
getType())
2605 :
llvm::isa<PointerElementTypeInterface>(
getType());
2608 "expects type to be a valid element type for an LLVM global");
2610 return emitOpError(
"must appear at the module level");
2612 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2613 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2614 IntegerType elementType =
2615 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) :
nullptr;
2616 if (!elementType || elementType.getWidth() != 8 ||
2617 type.getNumElements() != strAttr.getValue().size())
2619 "requires an i8 array type of the length equal to that of the string "
2623 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2624 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2626 <<
"this target extension type cannot be used in a global";
2629 return emitOpError() <<
"global with target extension type can only be "
2630 "initialized with zero-initializer";
2633 if (getLinkage() == Linkage::Common) {
2634 if (
Attribute value = getValueOrNull()) {
2637 <<
"expected zero value for '"
2638 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2643 if (getLinkage() == Linkage::Appending) {
2644 if (!llvm::isa<LLVMArrayType>(
getType())) {
2645 return emitOpError() <<
"expected array type for '"
2646 << stringifyLinkage(Linkage::Appending)
2654 std::optional<uint64_t> alignAttr = getAlignment();
2655 if (alignAttr.has_value()) {
2656 uint64_t value = alignAttr.value();
2657 if (!llvm::isPowerOf2_64(value))
2658 return emitError() <<
"alignment attribute is not a power of 2";
2664LogicalResult GlobalOp::verifyRegions() {
2665 if (
Block *
b = getInitializerBlock()) {
2666 ReturnOp ret = cast<ReturnOp>(
b->getTerminator());
2667 if (ret.operand_type_begin() == ret.operand_type_end())
2668 return emitOpError(
"initializer region cannot return void");
2669 if (*ret.operand_type_begin() !=
getType())
2671 << *ret.operand_type_begin() <<
" does not match global type "
2675 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2676 if (!iface || !iface.hasNoEffect())
2677 return op.emitError()
2678 <<
"ops with side effects not allowed in global initializers";
2681 if (getValueOrNull())
2682 return emitOpError(
"cannot have both initializer value and region");
2697 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2700 return op->
emitError(
"data element must be symbol or #llvm.zero");
2713LogicalResult GlobalCtorsOp::verify() {
2717 if (getCtors().size() == getPriorities().size() &&
2718 getCtors().size() == getData().size())
2721 "ctors, priorities, and data must have the same number of elements");
2738LogicalResult GlobalDtorsOp::verify() {
2742 if (getDtors().size() == getPriorities().size() &&
2743 getDtors().size() == getData().size())
2746 "dtors, priorities, and data must have the same number of elements");
2754 Linkage linkage, StringRef name,
bool dsoLocal,
2758 result.addAttribute(getAliasTypeAttrName(
result.name), TypeAttr::get(type));
2763 result.addAttribute(getThreadLocal_AttrName(
result.name),
2767 LinkageAttr::get(builder.
getContext(), linkage));
2768 result.attributes.append(attrs.begin(), attrs.end());
2778 {SymbolTable::getSymbolAttrName(),
2779 getAliasTypeAttrName(), getLinkageAttrName(),
2780 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2781 getVisibility_AttrName()});
2784 p <<
" : " <<
getType() <<
' ';
2810 if (types.size() > 1)
2818 TypeAttr::get(types[0]));
2822LogicalResult AliasOp::verify() {
2824 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2825 LLVMMetadataType, LLVMLabelType>(
getType())
2826 :
llvm::isa<PointerElementTypeInterface>(
getType());
2829 "expects type to be a valid element type for an LLVM global alias");
2832 switch (getLinkage()) {
2833 case Linkage::External:
2834 case Linkage::Internal:
2835 case Linkage::Private:
2837 case Linkage::WeakODR:
2838 case Linkage::Linkonce:
2839 case Linkage::LinkonceODR:
2840 case Linkage::AvailableExternally:
2844 <<
"'" << stringifyLinkage(getLinkage())
2845 <<
"' linkage not supported in aliases, available options: private, "
2846 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2847 "available_externally";
2853LogicalResult AliasOp::verifyRegions() {
2854 Block &
b = getInitializerBlock();
2855 auto ret = cast<ReturnOp>(
b.getTerminator());
2856 if (ret.getNumOperands() == 0 ||
2857 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2858 return emitOpError(
"initializer region must always return a pointer");
2861 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2862 if (!iface || !iface.hasNoEffect())
2863 return op.emitError()
2864 <<
"ops with side effects are not allowed in alias initializers";
2870unsigned AliasOp::getAddrSpace() {
2871 Block &initializer = getInitializerBlock();
2873 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2874 return ptrTy.getAddressSpace();
2882 Type iFuncType, StringRef resolverName,
Type resolverType,
2883 Linkage linkage, LLVM::Visibility visibility) {
2884 return build(builder,
result, name, iFuncType, resolverName, resolverType,
2886 UnnamedAddr::None, visibility);
2893 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2894 auto alias = dyn_cast<AliasOp>(symbol);
2896 Block &initBlock = alias.getInitializerBlock();
2898 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
2905 resolver = addrOp.getFunction(symbolTable);
2906 alias = addrOp.getAlias(symbolTable);
2909 return emitOpError(
"must have a function resolver");
2910 Linkage linkage = resolver.getLinkage();
2911 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
2912 return emitOpError(
"resolver must be a definition");
2913 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
2914 return emitOpError(
"resolver must return a pointer");
2915 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
2916 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
2917 return emitOpError(
"resolver has incorrect type");
2921LogicalResult IFuncOp::verify() {
2922 switch (getLinkage()) {
2923 case Linkage::External:
2924 case Linkage::Internal:
2925 case Linkage::Private:
2927 case Linkage::WeakODR:
2928 case Linkage::Linkonce:
2929 case Linkage::LinkonceODR:
2932 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
2933 <<
"' linkage not supported in ifuncs, available "
2934 "options: private, internal, linkonce, weak, "
2935 "linkonce_odr, weak_odr, or external linkage";
2947 auto containerType = v1.
getType();
2951 build(builder, state, vType, v1, v2, mask);
2965 "expected an LLVM compatible vector type");
2976LogicalResult ShuffleVectorOp::verify() {
2978 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2979 return emitOpError(
"expected a splat operation for scalable vectors");
2985OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
2987 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
2988 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
2992 if (getMask().size() != 1 || getMask()[0] != 0)
3003 assert(empty() &&
"function already has an entry block");
3008 LLVMFunctionType type = getFunctionType();
3009 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
3010 entry->
addArgument(type.getParamType(i), getLoc());
3015 StringRef name,
Type type, LLVM::Linkage linkage,
3016 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
3019 std::optional<uint64_t> functionEntryCount) {
3023 result.addAttribute(getFunctionTypeAttrName(
result.name),
3024 TypeAttr::get(type));
3026 LinkageAttr::get(builder.
getContext(), linkage));
3028 CConvAttr::get(builder.
getContext(), cconv));
3029 result.attributes.append(attrs.begin(), attrs.end());
3034 result.addAttribute(getComdatAttrName(
result.name), comdat);
3035 if (functionEntryCount)
3036 result.addAttribute(getFunctionEntryCountAttrName(
result.name),
3039 std::optional<NamedAttribute> duplicate =
result.attributes.findDuplicate();
3040 if (duplicate.has_value()) {
3041 llvm::report_fatal_error(
3042 Twine(
"LLVMFuncOp propagated an attribute that is meant "
3043 "to be constructed by the builder: ") +
3044 duplicate->getName().str());
3047 if (argAttrs.empty())
3050 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
3051 "expected as many argument attribute lists as arguments");
3053 builder,
result, argAttrs, {},
3054 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3065 if (outputs.size() > 1) {
3066 parser.
emitError(loc,
"failed to construct function type: expected zero or "
3067 "one function result");
3073 for (
auto t : inputs) {
3075 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3076 "type for function arguments");
3079 llvmInputs.push_back(t);
3084 outputs.empty() ? LLVMVoidType::get(
b.getContext()) : outputs.front();
3086 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3087 "type for function results")
3091 return LLVMFunctionType::get(llvmOutput, llvmInputs,
3107 parser, LLVM::Linkage::External)));
3110 result.addAttribute(getVisibility_AttrName(
result.name),
3113 parser, LLVM::Visibility::Default)));
3116 result.addAttribute(getUnnamedAddrAttrName(
result.name),
3119 parser, LLVM::UnnamedAddr::None)));
3123 getCConvAttrName(
result.name),
3127 StringAttr nameAttr;
3137 parser,
true, entryArgs, isVariadic, resultTypes,
3142 for (
auto &arg : entryArgs)
3143 argTypes.push_back(arg.type);
3149 result.addAttribute(getFunctionTypeAttrName(
result.name),
3150 TypeAttr::get(type));
3158 auto intTy = IntegerType::get(parser.
getContext(), 32);
3160 getVscaleRangeAttrName(
result.name),
3161 LLVM::VScaleRangeAttr::get(parser.
getContext(),
3162 IntegerAttr::get(intTy, minRange),
3163 IntegerAttr::get(intTy, maxRange)));
3167 SymbolRefAttr comdat;
3172 result.addAttribute(getComdatAttrName(
result.name), comdat);
3179 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3181 auto *body =
result.addRegion();
3192 if (getLinkage() != LLVM::Linkage::External)
3193 p << stringifyLinkage(getLinkage()) <<
' ';
3194 StringRef visibility = stringifyVisibility(getVisibility_());
3195 if (!visibility.empty())
3196 p << visibility <<
' ';
3197 if (
auto unnamedAddr = getUnnamedAddr()) {
3198 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3202 if (getCConv() != LLVM::CConv::C)
3203 p << stringifyCConv(getCConv()) <<
' ';
3207 LLVMFunctionType fnType = getFunctionType();
3210 argTypes.reserve(fnType.getNumParams());
3211 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3212 argTypes.push_back(fnType.getParamType(i));
3214 Type returnType = fnType.getReturnType();
3215 if (!llvm::isa<LLVMVoidType>(returnType))
3216 resTypes.push_back(returnType);
3219 isVarArg(), resTypes);
3222 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3223 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3224 << vscale->getMaxRange().getInt() <<
')';
3227 if (
auto comdat = getComdat())
3228 p <<
" comdat(" << *comdat <<
')';
3232 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3233 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3234 getComdatAttrName(), getUnnamedAddrAttrName(),
3235 getVscaleRangeAttrName()});
3238 Region &body = getBody();
3239 if (!body.empty()) {
3250LogicalResult LLVMFuncOp::verify() {
3251 if (getLinkage() == LLVM::Linkage::Common)
3253 << stringifyLinkage(LLVM::Linkage::Common)
3260 if (getLinkage() != LLVM::Linkage::External &&
3261 getLinkage() != LLVM::Linkage::ExternWeak)
3262 return emitOpError() <<
"external functions must have '"
3263 << stringifyLinkage(LLVM::Linkage::External)
3265 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3271 if (isNoInline() && isAlwaysInline())
3272 return emitError(
"no_inline and always_inline attributes are incompatible");
3274 if (isOptimizeNone() && !isNoInline())
3275 return emitOpError(
"with optimize_none must also be no_inline");
3277 Type landingpadResultTy;
3278 StringRef diagnosticMessage;
3279 bool isLandingpadTypeConsistent =
3281 const auto checkType = [&](
Type type, StringRef errorMessage) {
3282 if (!landingpadResultTy) {
3283 landingpadResultTy = type;
3286 if (landingpadResultTy != type) {
3287 diagnosticMessage = errorMessage;
3293 .Case([&](LandingpadOp landingpad) {
3294 constexpr StringLiteral errorMessage =
3295 "'llvm.landingpad' should have a consistent result type "
3296 "inside a function";
3297 return checkType(landingpad.getType(), errorMessage);
3299 .Case([&](ResumeOp resume) {
3300 constexpr StringLiteral errorMessage =
3301 "'llvm.resume' should have a consistent input type inside a "
3303 return checkType(resume.getValue().getType(), errorMessage);
3306 }).wasInterrupted();
3307 if (!isLandingpadTypeConsistent) {
3308 assert(!diagnosticMessage.empty() &&
3309 "Expecting a non-empty diagnostic message");
3321LogicalResult LLVMFuncOp::verifyRegions() {
3325 unsigned numArguments = getFunctionType().getNumParams();
3326 Block &entryBlock = front();
3327 for (
unsigned i = 0; i < numArguments; ++i) {
3331 << i <<
" is not of LLVM type";
3337Region *LLVMFuncOp::getCallableRegion() {
3365LogicalResult LLVM::ZeroOp::verify() {
3366 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3367 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3369 <<
"target extension type does not support zero-initializer";
3391 if (
auto vecType = dyn_cast<VectorType>(t)) {
3392 assert(!vecType.isScalable() &&
3393 "number of elements of a scalable vector type is unknown");
3394 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3396 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3397 return arrayType.getNumElements() *
3405 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3406 type = arrayType.getElementType();
3407 if (
auto vecType = dyn_cast<VectorType>(type))
3408 return vecType.getElementType();
3409 if (
auto tenType = dyn_cast<TensorType>(type))
3410 return tenType.getElementType();
3417 if (
auto vecType = dyn_cast<VectorType>(t)) {
3418 if (vecType.isScalable())
3422 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3430 LLVM::LLVMArrayType arrayType,
3432 if (arrayType.getNumElements() != arrayAttr.size())
3433 return op.emitOpError()
3434 <<
"array attribute size does not match array type size in "
3436 << dim <<
": " << arrayAttr.size() <<
" vs. "
3437 << arrayType.getNumElements();
3442 if (
auto subArrayType =
3443 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3444 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3445 if (elementsVerified.insert(elementAttr).second) {
3446 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3448 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3450 return op.emitOpError()
3451 <<
"nested attribute for sub-array in dimension " << dim
3452 <<
" at index " << idx
3453 <<
" must be a zero, or undef, or array attribute";
3467 auto structType = dyn_cast<LLVM::LLVMStructType>(arrayType.getElementType());
3469 return op.emitOpError() <<
"for array with an array attribute must have a "
3470 "struct element type";
3474 size_t numStructElements = structType.getBody().size();
3475 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3476 if (elementsVerified.insert(elementAttr).second) {
3477 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3479 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3481 return op.emitOpError()
3482 <<
"nested attribute for struct element at index " << idx
3483 <<
" must be a zero, or undef, or array attribute";
3484 if (subArrayAttr.size() != numStructElements)
3485 return op.emitOpError()
3486 <<
"nested array attribute size for struct element at index "
3487 << idx <<
" must match struct size: " << subArrayAttr.size()
3488 <<
" vs. " << numStructElements;
3495LogicalResult LLVM::ConstantOp::verify() {
3496 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3497 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3498 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3499 !arrayType.getElementType().isInteger(8)) {
3501 << sAttr.getValue().size()
3502 <<
" i8 elements for the string constant";
3506 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3507 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3509 return emitOpError() <<
"expected array attribute for struct type";
3512 if (arrayAttr.size() != elementTypes.size()) {
3513 return emitOpError() <<
"expected array attribute of size "
3514 << elementTypes.size();
3516 for (
auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3518 return emitOpError() <<
"expected struct element types to be floating "
3519 "point type or integer type";
3521 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3522 return emitOpError() <<
"expected element of array attribute to be "
3523 "floating point or integer";
3525 if (cast<TypedAttr>(attr).
getType() != type)
3527 <<
"struct element at index " << i <<
" is of wrong type";
3532 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3533 return emitOpError() <<
"does not support target extension type.";
3544 auto verifyFloatSemantics =
3545 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3546 Type constantElementType) -> LogicalResult {
3547 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3548 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3550 <<
"attribute and type have different float semantics";
3554 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3555 if (isa<IntegerType>(constantElementType)) {
3556 if (!constantElementType.isInteger(floatWidth))
3557 return emitOpError() <<
"expected integer type of width " << floatWidth;
3565 if (isa<IntegerAttr>(getValue())) {
3566 if (!llvm::isa<IntegerType>(
getType()))
3568 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3569 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3570 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3574 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3575 if (!splatElementsAttr)
3577 <<
"scalable vector type requires a splat attribute";
3580 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3581 return emitOpError() <<
"expected vector or array type";
3584 int64_t attrNumElements = elementsAttr.getNumElements();
3587 <<
"type and attribute have a different number of elements: "
3593 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3594 return verifyFloatSemantics(floatType.getFloatSemantics(), resultElmType);
3596 if (isa<IntegerType>(attrElmType) && !isa<IntegerType>(resultElmType)) {
3598 "expected integer element type for integer elements attribute");
3600 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3603 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3606 <<
"expected array or struct type for array attribute";
3613 <<
"only supports integer, float, string or elements attributes";
3619bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3621 auto typedAttr = dyn_cast<TypedAttr>(value);
3628 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3633 if (isBuildableWith(value, type))
3634 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3639OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3647 AtomicOrdering ordering, StringRef syncscope,
3648 unsigned alignment,
bool isVolatile) {
3649 build(builder, state, val.
getType(), binOp,
ptr, val, ordering,
3650 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3653 nullptr,
nullptr,
nullptr);
3656LogicalResult AtomicRMWOp::verify() {
3657 auto valType = getVal().getType();
3658 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3659 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3660 getBinOp() == AtomicBinOp::fminimum ||
3661 getBinOp() == AtomicBinOp::fmaximum) {
3664 return emitOpError(
"expected LLVM IR fixed vector type");
3665 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3668 "expected LLVM IR floating point type for vector element");
3670 return emitOpError(
"expected LLVM IR floating point type");
3672 }
else if (getBinOp() == AtomicBinOp::xchg) {
3675 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3677 auto intType = llvm::dyn_cast<IntegerType>(valType);
3678 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3679 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3681 return emitOpError(
"expected LLVM IR integer type");
3684 if (
static_cast<unsigned>(getOrdering()) <
3685 static_cast<unsigned>(AtomicOrdering::monotonic))
3687 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3699 auto boolType = IntegerType::get(valType.
getContext(), 1);
3700 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3705 AtomicOrdering successOrdering,
3706 AtomicOrdering failureOrdering, StringRef syncscope,
3707 unsigned alignment,
bool isWeak,
bool isVolatile) {
3709 successOrdering, failureOrdering,
3710 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3712 isVolatile,
nullptr,
3713 nullptr,
nullptr,
nullptr);
3716LogicalResult AtomicCmpXchgOp::verify() {
3717 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3719 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3720 auto valType = getVal().getType();
3724 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3725 getFailureOrdering() < AtomicOrdering::monotonic)
3726 return emitOpError(
"ordering must be at least 'monotonic'");
3727 if (getFailureOrdering() == AtomicOrdering::release ||
3728 getFailureOrdering() == AtomicOrdering::acq_rel)
3729 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3738 AtomicOrdering ordering, StringRef syncscope) {
3739 build(builder, state, ordering,
3740 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3743LogicalResult FenceOp::verify() {
3744 if (getOrdering() == AtomicOrdering::not_atomic ||
3745 getOrdering() == AtomicOrdering::unordered ||
3746 getOrdering() == AtomicOrdering::monotonic)
3747 return emitOpError(
"can be given only acquire, release, acq_rel, "
3748 "and seq_cst orderings");
3758template <
class ExtOp>
3760 IntegerType inputType, outputType;
3763 return op.emitError(
3764 "input type is a vector but output type is an integer");
3767 return op.emitError(
"input and output vectors are of incompatible shape");
3770 inputType = cast<IntegerType>(
3771 cast<VectorType>(op.getArg().getType()).getElementType());
3772 outputType = cast<IntegerType>(
3773 cast<VectorType>(op.getResult().getType()).getElementType());
3777 inputType = cast<IntegerType>(op.getArg().getType());
3778 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3780 return op.emitError(
3781 "input type is an integer but output type is a vector");
3784 if (outputType.getWidth() <= inputType.getWidth())
3785 return op.emitError(
"integer width of the output type is smaller or "
3786 "equal to the integer width of the input type");
3797 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3801 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3802 return IntegerAttr::get(
getType(), arg.getValue().zext(targetSize));
3816template <
typename T>
3818 typename T::FoldAdaptor adaptor) {
3820 if (castOp.getArg().getType() == castOp.getType())
3821 return castOp.getArg();
3822 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3824 if (prev.getArg().getType() == castOp.getType())
3825 return prev.getArg();
3827 castOp.getArgMutable().set(prev.getArg());
3828 return Value{castOp};
3833OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3837LogicalResult LLVM::BitcastOp::verify() {
3838 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3840 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3845 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3846 return emitOpError(
"can only cast pointers from and to pointers");
3851 auto isVector = llvm::IsaPred<VectorType>;
3855 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3856 return emitOpError(
"cannot cast pointer to vector of pointers");
3858 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3859 return emitOpError(
"cannot cast vector of pointers to pointer");
3863 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3864 return emitOpError(
"cannot cast pointers of different address spaces, "
3865 "use 'llvm.addrspacecast' instead");
3870LogicalResult LLVM::PtrToAddrOp::verify() {
3877 assert(width &&
"pointers always return an index bitwidth");
3878 if (width != integerType.getWidth())
3879 return emitOpError(
"bit-width of integer result type ")
3880 << integerType <<
" must match the pointer bitwidth (" << *width
3881 <<
") specified in the datalayout";
3890OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3894Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3902 adaptor.getDynamicIndices());
3906 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(
indices[0]))
3907 if (integer.getValue().isZero())
3911 bool changed =
false;
3913 for (
auto iter : llvm::enumerate(
indices)) {
3914 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3917 if (!
indices.isDynamicIndex(iter.index()) || !integer ||
3921 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3922 gepArgs.emplace_back(val);
3924 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3930 gepArgs.emplace_back(integer.getInt());
3938 getDynamicIndicesMutable().assign(dynamicIndices);
3939 setRawConstantIndices(rawConstantIndices);
3940 return Value{*
this};
3946Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3953 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3957 if (
rhs.getValue().getZExtValue() >=
3958 getLhs().
getType().getIntOrFloatBitWidth())
3961 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3965 return IntegerAttr::get(
getType(),
lhs.getValue().shl(
rhs.getValue()));
3973 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3977 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3981 return IntegerAttr::get(
getType(),
lhs.getValue() |
rhs.getValue());
3988LogicalResult CallIntrinsicOp::verify() {
3989 if (!getIntrin().starts_with(
"llvm."))
3990 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3998 build(builder, state,
TypeRange{}, intrin, args,
3999 FastmathFlagsAttr{},
4006 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4007 build(builder, state,
TypeRange{}, intrin, args,
4014 mlir::Type resultType, mlir::StringAttr intrin,
4016 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
4024 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4025 build(builder, state, resultTypes, intrin, args, fastMathFlags,
4030ParseResult CallIntrinsicOp::parse(
OpAsmParser &parser,
4032 StringAttr intrinAttr;
4042 result.addAttribute(CallIntrinsicOp::getIntrinAttrName(
result.name),
4050 return mlir::failure();
4053 return mlir::failure();
4058 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
4061 if (opBundleTags && !opBundleTags.empty())
4063 CallIntrinsicOp::getOpBundleTagsAttrName(
result.name).getValue(),
4067 return mlir::failure();
4072 operands, argAttrs, resultAttrs))
4076 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
4079 opBundleOperandTypes,
4080 getOpBundleSizesAttrName(
result.name)))
4083 int32_t numOpBundleOperands = 0;
4084 for (
const auto &operands : opBundleOperands)
4085 numOpBundleOperands += operands.size();
4088 CallIntrinsicOp::getOperandSegmentSizeAttr(),
4090 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
4092 return mlir::success();
4100 p <<
"(" << args <<
")";
4103 if (!getOpBundleOperands().empty()) {
4106 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
4110 {getOperandSegmentSizesAttrName(),
4111 getOpBundleSizesAttrName(), getIntrinAttrName(),
4112 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
4113 getResAttrsAttrName()});
4119 p, args.
getTypes(), getArgAttrsAttr(),
4120 false, getResultTypes(), getResAttrsAttr());
4127LogicalResult LinkerOptionsOp::verify() {
4130 return emitOpError(
"must appear at the module level");
4138LogicalResult ModuleFlagsOp::verify() {
4141 return emitOpError(
"must appear at the module level");
4143 if (!isa<ModuleFlagAttr>(flag))
4144 return emitOpError(
"expected a module flag attribute");
4152void InlineAsmOp::getEffects(
4155 if (getHasSideEffects()) {
4168 getBlockAddr().getFunction());
4169 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
4172 return emitOpError(
"must reference a function defined by 'llvm.func'");
4182BlockTagOp BlockAddressOp::getBlockTagOp() {
4187 auto funcOp = dyn_cast<LLVMFuncOp>(sym);
4190 BlockTagOp blockTagOp =
nullptr;
4191 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4192 if (labelOp.getTag() == getBlockAddr().getTag()) {
4193 blockTagOp = labelOp;
4201LogicalResult BlockAddressOp::verify() {
4202 if (!getBlockTagOp())
4204 "expects an existing block label target in the referenced function");
4211OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4218 assert(
index < getNumSuccessors() &&
"invalid successor index");
4230 rangeSegments.push_back(range.size());
4244 Block *destination = nullptr;
4245 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4246 SmallVector<Type> operandTypes;
4248 if (parser.parseSuccessor(destination).failed())
4251 if (succeeded(parser.parseOptionalLParen())) {
4252 if (failed(parser.parseOperandList(
4253 operands, OpAsmParser::Delimiter::None)) ||
4254 failed(parser.parseColonTypeList(operandTypes)) ||
4255 failed(parser.parseRParen()))
4258 succOperandBlocks.push_back(destination);
4259 succOperands.emplace_back(operands);
4260 succOperandsTypes.emplace_back(operandTypes);
4263 "successor blocks")))
4274 llvm::zip(succs, succOperands),
4280 if (!succOperands.empty())
4289LogicalResult LLVM::SincosOp::verify() {
4290 auto operandType = getOperand().getType();
4291 auto resultType = getResult().getType();
4292 auto resultStructType =
4293 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4294 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4295 resultStructType.getBody()[0] != operandType ||
4296 resultStructType.getBody()[1] != operandType) {
4297 return emitOpError(
"expected result type to be an homogeneous struct with "
4298 "two elements matching the operand type, but got ")
4310 return build(builder, state, cond, {},
4322 return build(builder, state, cond,
"align",
ValueRange{
ptr, align});
4328 return build(builder, state, cond,
"separate_storage",
4338LogicalResult LLVM::masked_gather::verify() {
4339 auto ptrsVectorType = getPtrs().getType();
4340 Type expectedPtrsVectorType =
4345 if (ptrsVectorType != expectedPtrsVectorType)
4346 return emitOpError(
"expected operand #1 type to be ")
4347 << expectedPtrsVectorType;
4355LogicalResult LLVM::masked_scatter::verify() {
4356 auto ptrsVectorType = getPtrs().getType();
4357 Type expectedPtrsVectorType =
4362 if (ptrsVectorType != expectedPtrsVectorType)
4363 return emitOpError(
"expected operand #2 type to be ")
4364 << expectedPtrsVectorType;
4377 build(builder, state, resTys,
ptr, mask, passthru, argAttrs,
4385void LLVM::masked_compressstore::build(
OpBuilder &builder,
4390 build(builder, state, value,
ptr, mask, argAttrs,
4398LogicalResult InlineAsmOp::verify() {
4399 if (!getTailCallKindAttr())
4402 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4404 "tail call kind 'musttail' is not supported by this operation");
4414 Value divisor = getRhs();
4429 Value divisor = getRhs();
4441void LLVMDialect::initialize() {
4442 registerAttributes();
4445 addTypes<LLVMVoidType,
4448 LLVMMetadataType>();
4454#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4458#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4463 allowUnknownOperations();
4464 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4468#define GET_OP_CLASSES
4469#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4471#define GET_OP_CLASSES
4472#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4474LogicalResult LLVMDialect::verifyDataLayoutString(
4477 llvm::DataLayout::parse(descr);
4478 if (maybeDataLayout)
4481 std::string message;
4482 llvm::raw_string_ostream messageStream(message);
4483 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4484 reportError(
"invalid data layout descriptor: " + message);
4489LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4495 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4497 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4498 return verifyDataLayoutString(
4499 stringAttr.getValue(),
4500 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4503 << LLVM::LLVMDialect::getDataLayoutAttrName()
4504 <<
"' to be a string attributes";
4507LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4515 StringAttr name = paramAttr.
getName();
4517 auto checkUnitAttrType = [&]() -> LogicalResult {
4518 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4519 return op->
emitError() << name <<
" should be a unit attribute";
4522 auto checkTypeAttrType = [&]() -> LogicalResult {
4523 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4524 return op->
emitError() << name <<
" should be a type attribute";
4527 auto checkIntegerAttrType = [&]() -> LogicalResult {
4528 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4529 return op->
emitError() << name <<
" should be an integer attribute";
4532 auto checkPointerType = [&]() -> LogicalResult {
4533 if (!llvm::isa<LLVMPointerType>(paramType))
4535 << name <<
" attribute attached to non-pointer LLVM type";
4538 auto checkIntegerType = [&]() -> LogicalResult {
4539 if (!llvm::isa<IntegerType>(paramType))
4541 << name <<
" attribute attached to non-integer LLVM type";
4544 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4545 if (
failed(checkPointerType()))
4552 if (name == LLVMDialect::getNoAliasAttrName() ||
4553 name == LLVMDialect::getReadonlyAttrName() ||
4554 name == LLVMDialect::getReadnoneAttrName() ||
4555 name == LLVMDialect::getWriteOnlyAttrName() ||
4556 name == LLVMDialect::getNestAttrName() ||
4557 name == LLVMDialect::getNoCaptureAttrName() ||
4558 name == LLVMDialect::getNoFreeAttrName() ||
4559 name == LLVMDialect::getNonNullAttrName()) {
4560 if (
failed(checkUnitAttrType()))
4562 if (verifyValueType &&
failed(checkPointerType()))
4568 if (name == LLVMDialect::getStructRetAttrName() ||
4569 name == LLVMDialect::getByValAttrName() ||
4570 name == LLVMDialect::getByRefAttrName() ||
4571 name == LLVMDialect::getElementTypeAttrName() ||
4572 name == LLVMDialect::getInAllocaAttrName() ||
4573 name == LLVMDialect::getPreallocatedAttrName()) {
4574 if (
failed(checkTypeAttrType()))
4576 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4582 if (name == LLVMDialect::getSExtAttrName() ||
4583 name == LLVMDialect::getZExtAttrName()) {
4584 if (
failed(checkUnitAttrType()))
4586 if (verifyValueType &&
failed(checkIntegerType()))
4592 if (name == LLVMDialect::getAlignAttrName() ||
4593 name == LLVMDialect::getDereferenceableAttrName() ||
4594 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4595 if (
failed(checkIntegerAttrType()))
4597 if (verifyValueType &&
failed(checkPointerType()))
4603 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4604 if (
failed(checkIntegerAttrType()))
4610 if (name == LLVMDialect::getNoUndefAttrName() ||
4611 name == LLVMDialect::getInRegAttrName() ||
4612 name == LLVMDialect::getReturnedAttrName())
4613 return checkUnitAttrType();
4619LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4623 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4626 Type argType = funcOp.getArgumentTypes()[argIdx];
4628 return verifyParameterAttribute(op, argType, argAttr);
4631LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4635 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4638 Type resType = funcOp.getResultTypes()[resIdx];
4642 if (llvm::isa<LLVMVoidType>(resType))
4643 return op->
emitError() <<
"cannot attach result attributes to functions "
4644 "with a void return";
4648 auto name = resAttr.
getName();
4649 if (name == LLVMDialect::getAllocAlignAttrName() ||
4650 name == LLVMDialect::getAllocatedPointerAttrName() ||
4651 name == LLVMDialect::getByValAttrName() ||
4652 name == LLVMDialect::getByRefAttrName() ||
4653 name == LLVMDialect::getInAllocaAttrName() ||
4654 name == LLVMDialect::getNestAttrName() ||
4655 name == LLVMDialect::getNoCaptureAttrName() ||
4656 name == LLVMDialect::getNoFreeAttrName() ||
4657 name == LLVMDialect::getPreallocatedAttrName() ||
4658 name == LLVMDialect::getReadnoneAttrName() ||
4659 name == LLVMDialect::getReadonlyAttrName() ||
4660 name == LLVMDialect::getReturnedAttrName() ||
4661 name == LLVMDialect::getStackAlignmentAttrName() ||
4662 name == LLVMDialect::getStructRetAttrName() ||
4663 name == LLVMDialect::getWriteOnlyAttrName())
4664 return op->
emitError() << name <<
" is not a valid result attribute";
4665 return verifyParameterAttribute(op, resType, resAttr);
4673 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4674 if (isa<LLVM::LLVMPointerType>(type))
4675 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4676 if (isa<LLVM::UndefAttr>(value))
4677 return LLVM::UndefOp::create(builder, loc, type);
4678 if (isa<LLVM::PoisonAttr>(value))
4679 return LLVM::PoisonOp::create(builder, loc, type);
4680 if (isa<LLVM::ZeroAttr>(value))
4681 return LLVM::ZeroOp::create(builder, loc, type);
4683 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4691 StringRef name, StringRef value,
4692 LLVM::Linkage linkage) {
4695 "expected builder to point to a block constrained in an op");
4697 builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4698 assert(module &&
"builder points to an op outside of a module");
4703 auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4704 auto global = LLVM::GlobalOp::create(
4705 moduleBuilder, loc, type,
true, linkage, name,
4708 LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4711 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4712 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4724 module = module->getParentOp();
4725 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) a properties of the provided type to be set on the operation on creation.
SmallVector< Value, 4 > operands
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addSuccessors(Block *successor)
Adds a successor to the operation sate. successor must not be null.