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,
1015 LLVMFunctionType calleeType, StringRef callee,
1017 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1021 LLVMFunctionType calleeType, StringAttr callee,
1023 build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
1041 nullptr,
nullptr,
nullptr,
1048 nullptr,
nullptr,
nullptr,
1054 LLVMFunctionType calleeType,
ValueRange args) {
1059 nullptr,
nullptr,
nullptr,
1060 nullptr,
nullptr,
nullptr,
1066 nullptr,
nullptr,
nullptr,
1080 auto calleeType =
func.getFunctionType();
1084 nullptr,
nullptr,
nullptr,
1085 nullptr,
nullptr,
nullptr,
1091 nullptr,
nullptr,
nullptr,
1108 return getOperand(0);
1114 auto symRef = cast<SymbolRefAttr>(callee);
1115 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1118 return setOperand(0, cast<Value>(callee));
1122 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1127 getCalleeOperands().size());
1134 if (callee.isExternal())
1136 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1140 auto hasSubprogram = [](
Operation *op) {
1145 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1147 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1149 return callOp.emitError()
1150 <<
"inlinable function call in a function with a DISubprogram "
1151 "location must have a debug location";
1157template <
typename OpTy>
1159 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1164 if (!varCalleeType->isVarArg())
1165 return callOp.emitOpError(
1166 "expected var_callee_type to be a variadic function type");
1170 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1171 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1172 << callOp.getArgOperands().size() <<
" parameters";
1175 for (
auto [paramType, operand] :
1176 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1177 if (paramType != operand.getType())
1178 return callOp.emitOpError()
1179 <<
"var_callee_type parameter type mismatch: " << paramType
1180 <<
" != " << operand.getType();
1183 if (!callOp.getNumResults()) {
1184 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1185 return callOp.emitOpError(
"expected var_callee_type to return void");
1187 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1188 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1189 << varCalleeType->getReturnType()
1190 <<
" != " << callOp.getResult().getType();
1195template <
typename OpType>
1198 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1200 auto isStringAttr = [](
Attribute tagAttr) {
1201 return isa<StringAttr>(tagAttr);
1203 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1204 return op.emitError(
"operand bundle tag must be a StringAttr");
1206 size_t numOpBundles = opBundleOperands.size();
1207 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1208 if (numOpBundles != numOpBundleTags)
1209 return op.emitError(
"expected ")
1210 << numOpBundles <<
" operand bundle tags, but actually got "
1226 bool isIndirect =
false;
1232 if (!getNumOperands())
1234 "must have either a `callee` attribute or at least an operand");
1235 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1237 return emitOpError(
"indirect call expects a pointer as callee: ")
1238 << getOperand(0).getType();
1247 <<
"' does not reference a symbol in the current scope";
1248 if (
auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1251 fnType = fn.getFunctionType();
1252 }
else if (
auto ifunc = dyn_cast<IFuncOp>(callee)) {
1253 fnType = ifunc.getIFuncType();
1257 <<
"' does not reference a valid LLVM function or IFunc";
1261 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1263 return emitOpError(
"callee does not have a functional type: ") << fnType;
1265 if (funcType.isVarArg() && !getVarCalleeType())
1266 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1270 if (!funcType.isVarArg() &&
1271 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1272 return emitOpError() <<
"incorrect number of operands ("
1273 << (getCalleeOperands().size() - isIndirect)
1274 <<
") for callee (expecting: "
1275 << funcType.getNumParams() <<
")";
1277 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1278 return emitOpError() <<
"incorrect number of operands ("
1279 << (getCalleeOperands().size() - isIndirect)
1280 <<
") for varargs callee (expecting at least: "
1281 << funcType.getNumParams() <<
")";
1283 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1284 if (getOperand(i + isIndirect).
getType() != funcType.getParamType(i))
1285 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1286 << getOperand(i + isIndirect).getType()
1287 <<
" != " << funcType.getParamType(i);
1289 if (getNumResults() == 0 &&
1290 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1291 return emitOpError() <<
"expected function call to produce a value";
1293 if (getNumResults() != 0 &&
1294 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1296 <<
"calling function with void result must not produce values";
1298 if (getNumResults() > 1)
1300 <<
"expected LLVM function call to produce 0 or 1 result";
1302 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1303 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1304 <<
" != " << funcType.getReturnType();
1310 auto callee = getCallee();
1311 bool isDirect = callee.has_value();
1316 if (getCConv() != LLVM::CConv::C)
1317 p << stringifyCConv(getCConv()) <<
' ';
1319 if (getTailCallKind() != LLVM::TailCallKind::None)
1320 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1329 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1330 p <<
'(' << args <<
')';
1333 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1334 p <<
" vararg(" << *varCalleeType <<
")";
1336 if (!getOpBundleOperands().empty()) {
1339 getOpBundleOperands().getTypes(), getOpBundleTags());
1343 {getCalleeAttrName(), getTailCallKindAttrName(),
1344 getVarCalleeTypeAttrName(), getCConvAttrName(),
1345 getOperandSegmentSizesAttrName(),
1346 getOpBundleSizesAttrName(),
1347 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1348 getResAttrsAttrName()});
1352 p << getOperand(0).getType() <<
", ";
1356 p, args.getTypes(), getArgAttrsAttr(),
1357 false, getResultTypes(), getResAttrsAttr());
1372 types.emplace_back();
1377 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1382 resTypes, resultAttrs)) {
1384 return parser.
emitError(trailingTypesLoc,
1385 "expected direct call to have 1 trailing types");
1386 return parser.
emitError(trailingTypesLoc,
1387 "expected trailing function type");
1390 if (resTypes.size() > 1)
1391 return parser.
emitError(trailingTypesLoc,
1392 "expected function with 0 or 1 result");
1393 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1394 return parser.
emitError(trailingTypesLoc,
1395 "expected a non-void result type");
1401 llvm::append_range(types, argTypes);
1405 if (!resTypes.empty())
1406 result.addTypes(resTypes);
1419 if (failed(*parseResult))
1420 return *parseResult;
1421 operands.push_back(funcPtrOperand);
1430 StringAttr opBundleSizesAttrName) {
1431 unsigned opBundleIndex = 0;
1432 for (
const auto &[operands, types] :
1433 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1434 if (operands.size() != types.size())
1435 return parser.
emitError(loc,
"expected ")
1437 <<
" types for operand bundle operands for operand bundle #"
1438 << opBundleIndex <<
", but actually got " << types.size();
1444 opBundleSizes.reserve(opBundleOperands.size());
1445 for (
const auto &operands : opBundleOperands)
1446 opBundleSizes.push_back(operands.size());
1449 opBundleSizesAttrName,
1461 SymbolRefAttr funcAttr;
1462 TypeAttr varCalleeType;
1470 getCConvAttrName(
result.name),
1475 getTailCallKindAttrName(
result.name),
1478 parser, LLVM::TailCallKind::None)));
1483 bool isDirect = operands.empty();
1496 StringAttr varCalleeTypeAttrName =
1497 CallOp::getVarCalleeTypeAttrName(
result.name);
1509 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1512 if (opBundleTags && !opBundleTags.empty())
1513 result.addAttribute(CallOp::getOpBundleTagsAttrName(
result.name).getValue(),
1523 argAttrs, resultAttrs))
1527 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1529 opBundleOperandTypes,
1530 getOpBundleSizesAttrName(
result.name)))
1533 int32_t numOpBundleOperands = 0;
1534 for (
const auto &operands : opBundleOperands)
1535 numOpBundleOperands += operands.size();
1538 CallOp::getOperandSegmentSizeAttr(),
1540 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1544LLVMFunctionType CallOp::getCalleeFunctionType() {
1545 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1546 return *varCalleeType;
1557 auto calleeType =
func.getFunctionType();
1560 nullptr,
nullptr, normalOps, unwindOps,
1561 nullptr,
nullptr, {}, {}, normal, unwind);
1568 build(builder, state, tys,
1569 nullptr, callee, ops,
nullptr,
1570 nullptr, normalOps, unwindOps,
nullptr,
nullptr, {}, {},
1580 nullptr,
nullptr, normalOps, unwindOps,
1581 nullptr,
nullptr, {}, {}, normal, unwind);
1585 assert(
index < getNumSuccessors() &&
"invalid successor index");
1587 : getUnwindDestOperandsMutable());
1595 return getOperand(0);
1601 auto symRef = cast<SymbolRefAttr>(callee);
1602 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1605 return setOperand(0, cast<Value>(callee));
1609 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1614 getCalleeOperands().size());
1617LogicalResult InvokeOp::verify() {
1621 Block *unwindDest = getUnwindDest();
1622 if (unwindDest->
empty())
1623 return emitError(
"must have at least one operation in unwind destination");
1626 if (!isa<LandingpadOp>(unwindDest->
front()))
1627 return emitError(
"first operation in unwind destination should be a "
1628 "llvm.landingpad operation");
1637 auto callee = getCallee();
1638 bool isDirect = callee.has_value();
1643 if (getCConv() != LLVM::CConv::C)
1644 p << stringifyCConv(getCConv()) <<
' ';
1652 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1659 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1660 p <<
" vararg(" << *varCalleeType <<
")";
1662 if (!getOpBundleOperands().empty()) {
1665 getOpBundleOperands().getTypes(), getOpBundleTags());
1669 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1670 getCConvAttrName(), getVarCalleeTypeAttrName(),
1671 getOpBundleSizesAttrName(),
1672 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1673 getResAttrsAttrName()});
1677 p << getOperand(0).getType() <<
", ";
1679 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1681 false, getResultTypes(), getResAttrsAttr());
1694 SymbolRefAttr funcAttr;
1695 TypeAttr varCalleeType;
1699 Block *normalDest, *unwindDest;
1705 getCConvAttrName(
result.name),
1712 bool isDirect = operands.empty();
1728 StringAttr varCalleeTypeAttrName =
1729 InvokeOp::getVarCalleeTypeAttrName(
result.name);
1741 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1744 if (opBundleTags && !opBundleTags.empty())
1746 InvokeOp::getOpBundleTagsAttrName(
result.name).getValue(),
1756 argAttrs, resultAttrs))
1760 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1763 opBundleOperandTypes,
1764 getOpBundleSizesAttrName(
result.name)))
1767 result.addSuccessors({normalDest, unwindDest});
1768 result.addOperands(normalOperands);
1769 result.addOperands(unwindOperands);
1771 int32_t numOpBundleOperands = 0;
1772 for (
const auto &operands : opBundleOperands)
1773 numOpBundleOperands += operands.size();
1776 InvokeOp::getOperandSegmentSizeAttr(),
1778 static_cast<int32_t>(normalOperands.size()),
1779 static_cast<int32_t>(unwindOperands.size()),
1780 numOpBundleOperands}));
1784LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1785 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1786 return *varCalleeType;
1794LogicalResult LandingpadOp::verify() {
1796 if (LLVMFuncOp
func = (*this)->getParentOfType<LLVMFuncOp>()) {
1797 if (!
func.getPersonality())
1799 "llvm.landingpad needs to be in a function with a personality");
1805 if (!getCleanup() && getOperands().empty())
1806 return emitError(
"landingpad instruction expects at least one clause or "
1807 "cleanup attribute");
1809 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1810 value = getOperand(idx);
1811 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1818 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1821 <<
"global addresses expected as operand to "
1822 "bitcast used in clauses for landingpad";
1830 << idx <<
" is not a known constant - null, addressof, bitcast";
1837 p << (getCleanup() ?
" cleanup " :
" ");
1840 for (
auto value : getOperands()) {
1843 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1844 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1891 Type llvmType = containerType;
1893 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1901 for (
int64_t idx : position) {
1902 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1903 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1904 emitError(
"position out of bounds: ") << idx;
1907 llvmType = arrayType.getElementType();
1908 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1910 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1911 emitError(
"position out of bounds: ") << idx;
1914 llvmType = structType.getBody()[idx];
1916 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1927 for (
int64_t idx : position) {
1928 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1929 llvmType = structType.getBody()[idx];
1931 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1942 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
1943 if (
index <
static_cast<size_t>(elementsAttr.getNumElements()))
1947 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
1948 if (
index < arrayAttr.getValue().size())
1949 return arrayAttr[
index];
1952 if (isa<ZeroAttr, UndefAttr, PoisonAttr>(attr))
1957OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1958 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
1960 newPos.append(getPosition().begin(), getPosition().end());
1961 setPosition(newPos);
1962 getContainerMutable().set(extractValueOp.getContainer());
1968 for (
int64_t pos : getPosition()) {
1973 return containerAttr;
1976 Value container = getContainer();
1978 while (
auto insertValueOp = container.
getDefiningOp<InsertValueOp>()) {
1980 auto extractPosSize = extractPos.size();
1981 auto insertPosSize = insertPos.size();
1984 if (extractPos == insertPos)
1985 return insertValueOp.getValue();
1999 if (extractPosSize > insertPosSize &&
2000 extractPos.take_front(insertPosSize) == insertPos) {
2001 container = insertValueOp.getValue();
2002 extractPos = extractPos.drop_front(insertPosSize);
2018 if (insertPosSize > extractPosSize &&
2019 extractPos == insertPos.take_front(extractPosSize))
2024 container = insertValueOp.getContainer();
2030 if (container == getContainer())
2032 setPosition(extractPos);
2033 getContainerMutable().assign(container);
2037LogicalResult ExtractValueOp::verify() {
2044 if (getRes().
getType() != valueType)
2045 return emitOpError() <<
"Type mismatch: extracting from "
2046 << getContainer().getType() <<
" should produce "
2047 << valueType <<
" but this op returns "
2048 << getRes().getType();
2054 build(builder, state,
2093 LogicalResult matchAndRewrite(InsertValueOp insertOp,
2094 PatternRewriter &rewriter)
const override {
2101 auto insertBaseIdx = insertOp.getPosition()[0];
2102 for (
auto &use : insertOp->getUses()) {
2103 if (
auto extractOp = dyn_cast<ExtractValueOp>(use.getOwner())) {
2104 auto baseIdx = extractOp.getPosition()[0];
2107 if (baseIdx == insertBaseIdx)
2109 posToExtractOps[baseIdx].push_back(extractOp);
2114 Value nextContainer = insertOp.getContainer();
2115 while (!posToExtractOps.empty()) {
2117 dyn_cast_or_null<InsertValueOp>(nextContainer.
getDefiningOp());
2120 nextContainer = curInsert.getContainer();
2123 auto curInsertBaseIdx = curInsert.getPosition()[0];
2124 auto it = posToExtractOps.find(curInsertBaseIdx);
2125 if (it == posToExtractOps.end())
2129 for (
auto &extractOp : it->second) {
2131 extractOp.getContainerMutable().assign(curInsert);
2136 assert(!it->second.empty());
2138 posToExtractOps.erase(it);
2142 for (
auto &[baseIdx, extracts] : posToExtractOps) {
2143 for (
auto &extractOp : extracts) {
2145 extractOp.getContainerMutable().assign(nextContainer);
2148 assert(!extracts.empty() &&
"Empty list in map");
2158 patterns.add<ResolveExtractValueSource>(context);
2167 [&](StringRef msg) {
2180LogicalResult InsertValueOp::verify() {
2187 if (getValue().
getType() != valueType)
2188 return emitOpError() <<
"Type mismatch: cannot insert "
2189 << getValue().getType() <<
" into "
2190 << getContainer().getType();
2199LogicalResult ReturnOp::verify() {
2200 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2204 Type expectedType = parent.getFunctionType().getReturnType();
2205 if (llvm::isa<LLVMVoidType>(expectedType)) {
2209 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2213 if (llvm::isa<LLVMVoidType>(expectedType))
2216 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2219 if (expectedType != getArg().
getType()) {
2221 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2232 return dyn_cast_or_null<GlobalOp>(
2237 return dyn_cast_or_null<LLVMFuncOp>(
2242 return dyn_cast_or_null<AliasOp>(
2247 return dyn_cast_or_null<IFuncOp>(
2256 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2257 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2258 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2259 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2261 if (!global && !function && !alias && !ifunc)
2262 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2263 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2265 LLVMPointerType type =
getType();
2266 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2267 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2268 return emitOpError(
"pointer address space must match address space of the "
2269 "referenced global or alias");
2276 return getGlobalNameAttr();
2297 getFunctionNameAttr());
2298 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2299 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2301 if (!function && !alias)
2303 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2306 if (alias.getInitializer()
2307 .walk([&](AddressOfOp addrOp) {
2308 if (addrOp.getGlobal(symbolTable))
2309 return WalkResult::interrupt();
2310 return WalkResult::advance();
2313 return emitOpError(
"must reference an alias to a function");
2316 if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2317 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2319 "target function with 'extern_weak' linkage not allowed");
2327 return DSOLocalEquivalentAttr::get(
getContext(), getFunctionNameAttr());
2335 StringRef symName) {
2338 Region *body =
result.addRegion();
2342LogicalResult ComdatOp::verifyRegions() {
2343 Region &body = getBody();
2344 for (Operation &op : body.
getOps())
2345 if (!isa<ComdatSelectorOp>(op))
2346 return op.emitError(
2347 "only comdat selector symbols can appear in a comdat region");
2357 bool isConstant, Linkage linkage, StringRef name,
2358 Attribute value, uint64_t alignment,
unsigned addrSpace,
2359 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2364 result.addAttribute(getGlobalTypeAttrName(
result.name), TypeAttr::get(type));
2369 result.addAttribute(getValueAttrName(
result.name), value);
2374 result.addAttribute(getThreadLocal_AttrName(
result.name),
2377 result.addAttribute(getComdatAttrName(
result.name), comdat);
2387 LinkageAttr::get(builder.
getContext(), linkage));
2391 result.attributes.append(attrs.begin(), attrs.end());
2393 if (!dbgExprs.empty())
2395 ArrayAttr::get(builder.
getContext(), dbgExprs));
2400template <
typename OpType>
2402 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2403 StringRef visibility = stringifyVisibility(op.getVisibility_());
2404 if (!visibility.empty())
2405 p << visibility <<
' ';
2406 if (op.getThreadLocal_())
2407 p <<
"thread_local ";
2408 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2409 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2421 if (
auto value = getValueOrNull())
2424 if (
auto comdat = getComdat())
2425 p <<
" comdat(" << *comdat <<
')';
2431 {SymbolTable::getSymbolAttrName(),
2432 getGlobalTypeAttrName(), getConstantAttrName(),
2433 getValueAttrName(), getLinkageAttrName(),
2434 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2435 getVisibility_AttrName(), getComdatAttrName()});
2438 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2442 Region &initializer = getInitializerRegion();
2443 if (!initializer.
empty()) {
2450 std::optional<SymbolRefAttr> attr) {
2455 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2456 return op->
emitError() <<
"expected comdat symbol";
2466 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2467 if (blockTags.contains(blockTagOp.getTag())) {
2468 blockTagOp.emitError()
2469 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2470 <<
"' in the same function: ";
2473 blockTags.insert(blockTagOp.getTag());
2482template <
typename OpType>
2488 OpType::getLinkageAttrName(
result.name),
2490 parser, LLVM::Linkage::External)));
2493 result.addAttribute(OpType::getVisibility_AttrName(
result.name),
2496 parser, LLVM::Visibility::Default)));
2499 result.addAttribute(OpType::getThreadLocal_AttrName(
result.name),
2503 result.addAttribute(OpType::getUnnamedAddrAttrName(
result.name),
2506 parser, LLVM::UnnamedAddr::None)));
2543 SymbolRefAttr comdat;
2548 result.addAttribute(getComdatAttrName(
result.name), comdat);
2556 if (types.size() > 1)
2560 if (types.empty()) {
2561 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2563 auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2564 strAttr.getValue().size());
2565 types.push_back(arrayType);
2568 "type can only be omitted for string globals");
2578 result.addAttribute(getGlobalTypeAttrName(
result.name),
2579 TypeAttr::get(types[0]));
2584 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2585 return intValue.getValue().isZero();
2586 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2587 return fpValue.getValue().isZero();
2588 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2590 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2592 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2597LogicalResult GlobalOp::verify() {
2599 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2600 LLVMMetadataType, LLVMLabelType>(
getType())
2601 :
llvm::isa<PointerElementTypeInterface>(
getType());
2604 "expects type to be a valid element type for an LLVM global");
2606 return emitOpError(
"must appear at the module level");
2608 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2609 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2610 IntegerType elementType =
2611 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) :
nullptr;
2612 if (!elementType || elementType.getWidth() != 8 ||
2613 type.getNumElements() != strAttr.getValue().size())
2615 "requires an i8 array type of the length equal to that of the string "
2619 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2620 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2622 <<
"this target extension type cannot be used in a global";
2625 return emitOpError() <<
"global with target extension type can only be "
2626 "initialized with zero-initializer";
2629 if (getLinkage() == Linkage::Common) {
2630 if (
Attribute value = getValueOrNull()) {
2633 <<
"expected zero value for '"
2634 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2639 if (getLinkage() == Linkage::Appending) {
2640 if (!llvm::isa<LLVMArrayType>(
getType())) {
2641 return emitOpError() <<
"expected array type for '"
2642 << stringifyLinkage(Linkage::Appending)
2650 std::optional<uint64_t> alignAttr = getAlignment();
2651 if (alignAttr.has_value()) {
2652 uint64_t value = alignAttr.value();
2653 if (!llvm::isPowerOf2_64(value))
2654 return emitError() <<
"alignment attribute is not a power of 2";
2660LogicalResult GlobalOp::verifyRegions() {
2661 if (
Block *
b = getInitializerBlock()) {
2662 ReturnOp ret = cast<ReturnOp>(
b->getTerminator());
2663 if (ret.operand_type_begin() == ret.operand_type_end())
2664 return emitOpError(
"initializer region cannot return void");
2665 if (*ret.operand_type_begin() !=
getType())
2667 << *ret.operand_type_begin() <<
" does not match global type "
2671 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2672 if (!iface || !iface.hasNoEffect())
2673 return op.emitError()
2674 <<
"ops with side effects not allowed in global initializers";
2677 if (getValueOrNull())
2678 return emitOpError(
"cannot have both initializer value and region");
2693 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2696 return op->
emitError(
"data element must be symbol or #llvm.zero");
2709LogicalResult GlobalCtorsOp::verify() {
2713 if (getCtors().size() == getPriorities().size() &&
2714 getCtors().size() == getData().size())
2717 "ctors, priorities, and data must have the same number of elements");
2734LogicalResult GlobalDtorsOp::verify() {
2738 if (getDtors().size() == getPriorities().size() &&
2739 getDtors().size() == getData().size())
2742 "dtors, priorities, and data must have the same number of elements");
2750 Linkage linkage, StringRef name,
bool dsoLocal,
2754 result.addAttribute(getAliasTypeAttrName(
result.name), TypeAttr::get(type));
2759 result.addAttribute(getThreadLocal_AttrName(
result.name),
2763 LinkageAttr::get(builder.
getContext(), linkage));
2764 result.attributes.append(attrs.begin(), attrs.end());
2774 {SymbolTable::getSymbolAttrName(),
2775 getAliasTypeAttrName(), getLinkageAttrName(),
2776 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2777 getVisibility_AttrName()});
2780 p <<
" : " <<
getType() <<
' ';
2806 if (types.size() > 1)
2814 TypeAttr::get(types[0]));
2818LogicalResult AliasOp::verify() {
2820 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2821 LLVMMetadataType, LLVMLabelType>(
getType())
2822 :
llvm::isa<PointerElementTypeInterface>(
getType());
2825 "expects type to be a valid element type for an LLVM global alias");
2828 switch (getLinkage()) {
2829 case Linkage::External:
2830 case Linkage::Internal:
2831 case Linkage::Private:
2833 case Linkage::WeakODR:
2834 case Linkage::Linkonce:
2835 case Linkage::LinkonceODR:
2836 case Linkage::AvailableExternally:
2840 <<
"'" << stringifyLinkage(getLinkage())
2841 <<
"' linkage not supported in aliases, available options: private, "
2842 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2843 "available_externally";
2849LogicalResult AliasOp::verifyRegions() {
2850 Block &
b = getInitializerBlock();
2851 auto ret = cast<ReturnOp>(
b.getTerminator());
2852 if (ret.getNumOperands() == 0 ||
2853 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2854 return emitOpError(
"initializer region must always return a pointer");
2857 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2858 if (!iface || !iface.hasNoEffect())
2859 return op.emitError()
2860 <<
"ops with side effects are not allowed in alias initializers";
2866unsigned AliasOp::getAddrSpace() {
2867 Block &initializer = getInitializerBlock();
2869 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2870 return ptrTy.getAddressSpace();
2878 Type iFuncType, StringRef resolverName,
Type resolverType,
2879 Linkage linkage, LLVM::Visibility visibility) {
2880 return build(builder,
result, name, iFuncType, resolverName, resolverType,
2882 UnnamedAddr::None, visibility);
2889 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2890 auto alias = dyn_cast<AliasOp>(symbol);
2892 Block &initBlock = alias.getInitializerBlock();
2894 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
2901 resolver = addrOp.getFunction(symbolTable);
2902 alias = addrOp.getAlias(symbolTable);
2905 return emitOpError(
"must have a function resolver");
2906 Linkage linkage = resolver.getLinkage();
2907 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
2908 return emitOpError(
"resolver must be a definition");
2909 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
2910 return emitOpError(
"resolver must return a pointer");
2911 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
2912 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
2913 return emitOpError(
"resolver has incorrect type");
2917LogicalResult IFuncOp::verify() {
2918 switch (getLinkage()) {
2919 case Linkage::External:
2920 case Linkage::Internal:
2921 case Linkage::Private:
2923 case Linkage::WeakODR:
2924 case Linkage::Linkonce:
2925 case Linkage::LinkonceODR:
2928 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
2929 <<
"' linkage not supported in ifuncs, available "
2930 "options: private, internal, linkonce, weak, "
2931 "linkonce_odr, weak_odr, or external linkage";
2943 auto containerType = v1.
getType();
2947 build(builder, state, vType, v1, v2, mask);
2961 "expected an LLVM compatible vector type");
2972LogicalResult ShuffleVectorOp::verify() {
2974 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2975 return emitOpError(
"expected a splat operation for scalable vectors");
2981OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
2983 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
2984 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
2988 if (getMask().size() != 1 || getMask()[0] != 0)
2999 assert(empty() &&
"function already has an entry block");
3004 LLVMFunctionType type = getFunctionType();
3005 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
3006 entry->
addArgument(type.getParamType(i), getLoc());
3011 StringRef name,
Type type, LLVM::Linkage linkage,
3012 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
3015 std::optional<uint64_t> functionEntryCount) {
3019 result.addAttribute(getFunctionTypeAttrName(
result.name),
3020 TypeAttr::get(type));
3022 LinkageAttr::get(builder.
getContext(), linkage));
3024 CConvAttr::get(builder.
getContext(), cconv));
3025 result.attributes.append(attrs.begin(), attrs.end());
3030 result.addAttribute(getComdatAttrName(
result.name), comdat);
3031 if (functionEntryCount)
3032 result.addAttribute(getFunctionEntryCountAttrName(
result.name),
3034 if (argAttrs.empty())
3037 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
3038 "expected as many argument attribute lists as arguments");
3040 builder,
result, argAttrs, {},
3041 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3052 if (outputs.size() > 1) {
3053 parser.
emitError(loc,
"failed to construct function type: expected zero or "
3054 "one function result");
3060 for (
auto t : inputs) {
3062 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3063 "type for function arguments");
3066 llvmInputs.push_back(t);
3071 outputs.empty() ? LLVMVoidType::get(
b.getContext()) : outputs.front();
3073 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3074 "type for function results")
3078 return LLVMFunctionType::get(llvmOutput, llvmInputs,
3094 parser, LLVM::Linkage::External)));
3097 result.addAttribute(getVisibility_AttrName(
result.name),
3100 parser, LLVM::Visibility::Default)));
3103 result.addAttribute(getUnnamedAddrAttrName(
result.name),
3106 parser, LLVM::UnnamedAddr::None)));
3110 getCConvAttrName(
result.name),
3114 StringAttr nameAttr;
3124 parser,
true, entryArgs, isVariadic, resultTypes,
3129 for (
auto &arg : entryArgs)
3130 argTypes.push_back(arg.type);
3136 result.addAttribute(getFunctionTypeAttrName(
result.name),
3137 TypeAttr::get(type));
3145 auto intTy = IntegerType::get(parser.
getContext(), 32);
3147 getVscaleRangeAttrName(
result.name),
3148 LLVM::VScaleRangeAttr::get(parser.
getContext(),
3149 IntegerAttr::get(intTy, minRange),
3150 IntegerAttr::get(intTy, maxRange)));
3154 SymbolRefAttr comdat;
3159 result.addAttribute(getComdatAttrName(
result.name), comdat);
3166 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3168 auto *body =
result.addRegion();
3179 if (getLinkage() != LLVM::Linkage::External)
3180 p << stringifyLinkage(getLinkage()) <<
' ';
3181 StringRef visibility = stringifyVisibility(getVisibility_());
3182 if (!visibility.empty())
3183 p << visibility <<
' ';
3184 if (
auto unnamedAddr = getUnnamedAddr()) {
3185 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3189 if (getCConv() != LLVM::CConv::C)
3190 p << stringifyCConv(getCConv()) <<
' ';
3194 LLVMFunctionType fnType = getFunctionType();
3197 argTypes.reserve(fnType.getNumParams());
3198 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3199 argTypes.push_back(fnType.getParamType(i));
3201 Type returnType = fnType.getReturnType();
3202 if (!llvm::isa<LLVMVoidType>(returnType))
3203 resTypes.push_back(returnType);
3206 isVarArg(), resTypes);
3209 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3210 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3211 << vscale->getMaxRange().getInt() <<
')';
3214 if (
auto comdat = getComdat())
3215 p <<
" comdat(" << *comdat <<
')';
3219 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3220 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3221 getComdatAttrName(), getUnnamedAddrAttrName(),
3222 getVscaleRangeAttrName()});
3225 Region &body = getBody();
3226 if (!body.empty()) {
3237LogicalResult LLVMFuncOp::verify() {
3238 if (getLinkage() == LLVM::Linkage::Common)
3240 << stringifyLinkage(LLVM::Linkage::Common)
3247 if (getLinkage() != LLVM::Linkage::External &&
3248 getLinkage() != LLVM::Linkage::ExternWeak)
3249 return emitOpError() <<
"external functions must have '"
3250 << stringifyLinkage(LLVM::Linkage::External)
3252 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3258 if (isNoInline() && isAlwaysInline())
3259 return emitError(
"no_inline and always_inline attributes are incompatible");
3261 if (isOptimizeNone() && !isNoInline())
3262 return emitOpError(
"with optimize_none must also be no_inline");
3264 Type landingpadResultTy;
3265 StringRef diagnosticMessage;
3266 bool isLandingpadTypeConsistent =
3268 const auto checkType = [&](
Type type, StringRef errorMessage) {
3269 if (!landingpadResultTy) {
3270 landingpadResultTy = type;
3273 if (landingpadResultTy != type) {
3274 diagnosticMessage = errorMessage;
3280 .Case([&](LandingpadOp landingpad) {
3281 constexpr StringLiteral errorMessage =
3282 "'llvm.landingpad' should have a consistent result type "
3283 "inside a function";
3284 return checkType(landingpad.getType(), errorMessage);
3286 .Case([&](ResumeOp resume) {
3287 constexpr StringLiteral errorMessage =
3288 "'llvm.resume' should have a consistent input type inside a "
3290 return checkType(resume.getValue().getType(), errorMessage);
3293 }).wasInterrupted();
3294 if (!isLandingpadTypeConsistent) {
3295 assert(!diagnosticMessage.empty() &&
3296 "Expecting a non-empty diagnostic message");
3308LogicalResult LLVMFuncOp::verifyRegions() {
3312 unsigned numArguments = getFunctionType().getNumParams();
3313 Block &entryBlock = front();
3314 for (
unsigned i = 0; i < numArguments; ++i) {
3318 << i <<
" is not of LLVM type";
3324Region *LLVMFuncOp::getCallableRegion() {
3352LogicalResult LLVM::ZeroOp::verify() {
3353 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3354 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3356 <<
"target extension type does not support zero-initializer";
3378 if (
auto vecType = dyn_cast<VectorType>(t)) {
3379 assert(!vecType.isScalable() &&
3380 "number of elements of a scalable vector type is unknown");
3381 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3383 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3384 return arrayType.getNumElements() *
3392 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3393 type = arrayType.getElementType();
3394 if (
auto vecType = dyn_cast<VectorType>(type))
3395 return vecType.getElementType();
3396 if (
auto tenType = dyn_cast<TensorType>(type))
3397 return tenType.getElementType();
3404 if (
auto vecType = dyn_cast<VectorType>(t)) {
3405 if (vecType.isScalable())
3409 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3417 LLVM::LLVMArrayType arrayType,
3419 if (arrayType.getNumElements() != arrayAttr.size())
3420 return op.emitOpError()
3421 <<
"array attribute size does not match array type size in "
3423 << dim <<
": " << arrayAttr.size() <<
" vs. "
3424 << arrayType.getNumElements();
3429 if (
auto subArrayType =
3430 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3431 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3432 if (elementsVerified.insert(elementAttr).second) {
3433 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3435 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3437 return op.emitOpError()
3438 <<
"nested attribute for sub-array in dimension " << dim
3439 <<
" at index " << idx
3440 <<
" must be a zero, or undef, or array attribute";
3454 auto structType = dyn_cast<LLVM::LLVMStructType>(arrayType.getElementType());
3456 return op.emitOpError() <<
"for array with an array attribute must have a "
3457 "struct element type";
3461 size_t numStructElements = structType.getBody().size();
3462 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3463 if (elementsVerified.insert(elementAttr).second) {
3464 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3466 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3468 return op.emitOpError()
3469 <<
"nested attribute for struct element at index " << idx
3470 <<
" must be a zero, or undef, or array attribute";
3471 if (subArrayAttr.size() != numStructElements)
3472 return op.emitOpError()
3473 <<
"nested array attribute size for struct element at index "
3474 << idx <<
" must match struct size: " << subArrayAttr.size()
3475 <<
" vs. " << numStructElements;
3482LogicalResult LLVM::ConstantOp::verify() {
3483 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3484 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3485 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3486 !arrayType.getElementType().isInteger(8)) {
3488 << sAttr.getValue().size()
3489 <<
" i8 elements for the string constant";
3493 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3494 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3496 return emitOpError() <<
"expected array attribute for struct type";
3499 if (arrayAttr.size() != elementTypes.size()) {
3500 return emitOpError() <<
"expected array attribute of size "
3501 << elementTypes.size();
3503 for (
auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3505 return emitOpError() <<
"expected struct element types to be floating "
3506 "point type or integer type";
3508 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3509 return emitOpError() <<
"expected element of array attribute to be "
3510 "floating point or integer";
3512 if (cast<TypedAttr>(attr).
getType() != type)
3514 <<
"struct element at index " << i <<
" is of wrong type";
3519 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3520 return emitOpError() <<
"does not support target extension type.";
3531 auto verifyFloatSemantics =
3532 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3533 Type constantElementType) -> LogicalResult {
3534 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3535 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3537 <<
"attribute and type have different float semantics";
3541 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3542 if (isa<IntegerType>(constantElementType)) {
3543 if (!constantElementType.isInteger(floatWidth))
3544 return emitOpError() <<
"expected integer type of width " << floatWidth;
3552 if (isa<IntegerAttr>(getValue())) {
3553 if (!llvm::isa<IntegerType>(
getType()))
3555 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3556 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3557 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3561 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3562 if (!splatElementsAttr)
3564 <<
"scalable vector type requires a splat attribute";
3567 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3568 return emitOpError() <<
"expected vector or array type";
3571 int64_t attrNumElements = elementsAttr.getNumElements();
3574 <<
"type and attribute have a different number of elements: "
3580 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3581 return verifyFloatSemantics(floatType.getFloatSemantics(), resultElmType);
3583 if (isa<IntegerType>(attrElmType) && !isa<IntegerType>(resultElmType)) {
3585 "expected integer element type for integer elements attribute");
3587 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3590 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3593 <<
"expected array or struct type for array attribute";
3600 <<
"only supports integer, float, string or elements attributes";
3606bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3608 auto typedAttr = dyn_cast<TypedAttr>(value);
3615 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3620 if (isBuildableWith(value, type))
3621 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3626OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3634 AtomicOrdering ordering, StringRef syncscope,
3635 unsigned alignment,
bool isVolatile) {
3636 build(builder, state, val.
getType(), binOp,
ptr, val, ordering,
3637 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3640 nullptr,
nullptr,
nullptr);
3643LogicalResult AtomicRMWOp::verify() {
3644 auto valType = getVal().getType();
3645 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3646 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3647 getBinOp() == AtomicBinOp::fminimum ||
3648 getBinOp() == AtomicBinOp::fmaximum) {
3651 return emitOpError(
"expected LLVM IR fixed vector type");
3652 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3655 "expected LLVM IR floating point type for vector element");
3657 return emitOpError(
"expected LLVM IR floating point type");
3659 }
else if (getBinOp() == AtomicBinOp::xchg) {
3662 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3664 auto intType = llvm::dyn_cast<IntegerType>(valType);
3665 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3666 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3668 return emitOpError(
"expected LLVM IR integer type");
3671 if (
static_cast<unsigned>(getOrdering()) <
3672 static_cast<unsigned>(AtomicOrdering::monotonic))
3674 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3686 auto boolType = IntegerType::get(valType.
getContext(), 1);
3687 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3692 AtomicOrdering successOrdering,
3693 AtomicOrdering failureOrdering, StringRef syncscope,
3694 unsigned alignment,
bool isWeak,
bool isVolatile) {
3696 successOrdering, failureOrdering,
3697 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3699 isVolatile,
nullptr,
3700 nullptr,
nullptr,
nullptr);
3703LogicalResult AtomicCmpXchgOp::verify() {
3704 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3706 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3707 auto valType = getVal().getType();
3711 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3712 getFailureOrdering() < AtomicOrdering::monotonic)
3713 return emitOpError(
"ordering must be at least 'monotonic'");
3714 if (getFailureOrdering() == AtomicOrdering::release ||
3715 getFailureOrdering() == AtomicOrdering::acq_rel)
3716 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3725 AtomicOrdering ordering, StringRef syncscope) {
3726 build(builder, state, ordering,
3727 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3730LogicalResult FenceOp::verify() {
3731 if (getOrdering() == AtomicOrdering::not_atomic ||
3732 getOrdering() == AtomicOrdering::unordered ||
3733 getOrdering() == AtomicOrdering::monotonic)
3734 return emitOpError(
"can be given only acquire, release, acq_rel, "
3735 "and seq_cst orderings");
3745template <
class ExtOp>
3747 IntegerType inputType, outputType;
3750 return op.emitError(
3751 "input type is a vector but output type is an integer");
3754 return op.emitError(
"input and output vectors are of incompatible shape");
3757 inputType = cast<IntegerType>(
3758 cast<VectorType>(op.getArg().getType()).getElementType());
3759 outputType = cast<IntegerType>(
3760 cast<VectorType>(op.getResult().getType()).getElementType());
3764 inputType = cast<IntegerType>(op.getArg().getType());
3765 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3767 return op.emitError(
3768 "input type is an integer but output type is a vector");
3771 if (outputType.getWidth() <= inputType.getWidth())
3772 return op.emitError(
"integer width of the output type is smaller or "
3773 "equal to the integer width of the input type");
3784 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3788 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3789 return IntegerAttr::get(
getType(), arg.getValue().zext(targetSize));
3803template <
typename T>
3805 typename T::FoldAdaptor adaptor) {
3807 if (castOp.getArg().getType() == castOp.getType())
3808 return castOp.getArg();
3809 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3811 if (prev.getArg().getType() == castOp.getType())
3812 return prev.getArg();
3814 castOp.getArgMutable().set(prev.getArg());
3815 return Value{castOp};
3820OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3824LogicalResult LLVM::BitcastOp::verify() {
3825 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3827 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3832 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3833 return emitOpError(
"can only cast pointers from and to pointers");
3838 auto isVector = llvm::IsaPred<VectorType>;
3842 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3843 return emitOpError(
"cannot cast pointer to vector of pointers");
3845 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3846 return emitOpError(
"cannot cast vector of pointers to pointer");
3850 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3851 return emitOpError(
"cannot cast pointers of different address spaces, "
3852 "use 'llvm.addrspacecast' instead");
3861OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3865Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3873 adaptor.getDynamicIndices());
3877 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(
indices[0]))
3878 if (integer.getValue().isZero())
3884 for (
auto iter : llvm::enumerate(
indices)) {
3885 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3888 if (!
indices.isDynamicIndex(iter.index()) || !integer ||
3892 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3893 gepArgs.emplace_back(val);
3895 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3901 gepArgs.emplace_back(integer.getInt());
3909 getDynamicIndicesMutable().assign(dynamicIndices);
3910 setRawConstantIndices(rawConstantIndices);
3911 return Value{*
this};
3917Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3924 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3928 if (
rhs.getValue().getZExtValue() >=
3929 getLhs().
getType().getIntOrFloatBitWidth())
3932 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3936 return IntegerAttr::get(
getType(),
lhs.getValue().shl(
rhs.getValue()));
3944 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3948 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3952 return IntegerAttr::get(
getType(),
lhs.getValue() |
rhs.getValue());
3959LogicalResult CallIntrinsicOp::verify() {
3960 if (!getIntrin().starts_with(
"llvm."))
3961 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3969 build(builder, state,
TypeRange{}, intrin, args,
3970 FastmathFlagsAttr{},
3977 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3978 build(builder, state,
TypeRange{}, intrin, args,
3985 mlir::Type resultType, mlir::StringAttr intrin,
3987 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
3995 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3996 build(builder, state, resultTypes, intrin, args, fastMathFlags,
4001ParseResult CallIntrinsicOp::parse(
OpAsmParser &parser,
4003 StringAttr intrinAttr;
4013 result.addAttribute(CallIntrinsicOp::getIntrinAttrName(
result.name),
4021 return mlir::failure();
4024 return mlir::failure();
4029 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
4032 if (opBundleTags && !opBundleTags.empty())
4034 CallIntrinsicOp::getOpBundleTagsAttrName(
result.name).getValue(),
4038 return mlir::failure();
4043 operands, argAttrs, resultAttrs))
4047 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
4050 opBundleOperandTypes,
4051 getOpBundleSizesAttrName(
result.name)))
4054 int32_t numOpBundleOperands = 0;
4055 for (
const auto &operands : opBundleOperands)
4056 numOpBundleOperands += operands.size();
4059 CallIntrinsicOp::getOperandSegmentSizeAttr(),
4061 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
4063 return mlir::success();
4071 p <<
"(" << args <<
")";
4074 if (!getOpBundleOperands().empty()) {
4077 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
4081 {getOperandSegmentSizesAttrName(),
4082 getOpBundleSizesAttrName(), getIntrinAttrName(),
4083 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
4084 getResAttrsAttrName()});
4090 p, args.
getTypes(), getArgAttrsAttr(),
4091 false, getResultTypes(), getResAttrsAttr());
4098LogicalResult LinkerOptionsOp::verify() {
4101 return emitOpError(
"must appear at the module level");
4109LogicalResult ModuleFlagsOp::verify() {
4112 return emitOpError(
"must appear at the module level");
4114 if (!isa<ModuleFlagAttr>(flag))
4115 return emitOpError(
"expected a module flag attribute");
4123void InlineAsmOp::getEffects(
4126 if (getHasSideEffects()) {
4139 getBlockAddr().getFunction());
4140 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
4143 return emitOpError(
"must reference a function defined by 'llvm.func'");
4153BlockTagOp BlockAddressOp::getBlockTagOp() {
4159 BlockTagOp blockTagOp =
nullptr;
4160 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4161 if (labelOp.getTag() == getBlockAddr().getTag()) {
4162 blockTagOp = labelOp;
4170LogicalResult BlockAddressOp::verify() {
4171 if (!getBlockTagOp())
4173 "expects an existing block label target in the referenced function");
4180OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4187 assert(
index < getNumSuccessors() &&
"invalid successor index");
4199 rangeSegments.push_back(range.size());
4213 Block *destination = nullptr;
4214 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4215 SmallVector<Type> operandTypes;
4217 if (parser.parseSuccessor(destination).failed())
4220 if (succeeded(parser.parseOptionalLParen())) {
4221 if (failed(parser.parseOperandList(
4222 operands, OpAsmParser::Delimiter::None)) ||
4223 failed(parser.parseColonTypeList(operandTypes)) ||
4224 failed(parser.parseRParen()))
4227 succOperandBlocks.push_back(destination);
4228 succOperands.emplace_back(operands);
4229 succOperandsTypes.emplace_back(operandTypes);
4232 "successor blocks")))
4243 llvm::zip(succs, succOperands),
4249 if (!succOperands.empty())
4258LogicalResult LLVM::SincosOp::verify() {
4259 auto operandType = getOperand().getType();
4260 auto resultType = getResult().getType();
4261 auto resultStructType =
4262 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4263 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4264 resultStructType.getBody()[0] != operandType ||
4265 resultStructType.getBody()[1] != operandType) {
4266 return emitOpError(
"expected result type to be an homogeneous struct with "
4267 "two elements matching the operand type, but got ")
4279 return build(builder, state, cond, {},
4291 return build(builder, state, cond,
"align",
ValueRange{
ptr, align});
4297 return build(builder, state, cond,
"separate_storage",
4307LogicalResult LLVM::masked_gather::verify() {
4308 auto ptrsVectorType = getPtrs().getType();
4309 Type expectedPtrsVectorType =
4314 if (ptrsVectorType != expectedPtrsVectorType)
4315 return emitOpError(
"expected operand #1 type to be ")
4316 << expectedPtrsVectorType;
4324LogicalResult LLVM::masked_scatter::verify() {
4325 auto ptrsVectorType = getPtrs().getType();
4326 Type expectedPtrsVectorType =
4331 if (ptrsVectorType != expectedPtrsVectorType)
4332 return emitOpError(
"expected operand #2 type to be ")
4333 << expectedPtrsVectorType;
4346 build(builder, state, resTys,
ptr, mask, passthru, argAttrs,
4354void LLVM::masked_compressstore::build(
OpBuilder &builder,
4359 build(builder, state, value,
ptr, mask, argAttrs,
4367LogicalResult InlineAsmOp::verify() {
4368 if (!getTailCallKindAttr())
4371 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4373 "tail call kind 'musttail' is not supported by this operation");
4383 Value divisor = getRhs();
4398 Value divisor = getRhs();
4410void LLVMDialect::initialize() {
4411 registerAttributes();
4414 addTypes<LLVMVoidType,
4417 LLVMMetadataType>();
4423#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4427#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4432 allowUnknownOperations();
4433 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4437#define GET_OP_CLASSES
4438#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4440#define GET_OP_CLASSES
4441#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4443LogicalResult LLVMDialect::verifyDataLayoutString(
4446 llvm::DataLayout::parse(descr);
4447 if (maybeDataLayout)
4450 std::string message;
4451 llvm::raw_string_ostream messageStream(message);
4452 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4453 reportError(
"invalid data layout descriptor: " + message);
4458LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4464 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4466 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4467 return verifyDataLayoutString(
4468 stringAttr.getValue(),
4469 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4472 << LLVM::LLVMDialect::getDataLayoutAttrName()
4473 <<
"' to be a string attributes";
4476LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4484 StringAttr name = paramAttr.
getName();
4486 auto checkUnitAttrType = [&]() -> LogicalResult {
4487 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4488 return op->
emitError() << name <<
" should be a unit attribute";
4491 auto checkTypeAttrType = [&]() -> LogicalResult {
4492 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4493 return op->
emitError() << name <<
" should be a type attribute";
4496 auto checkIntegerAttrType = [&]() -> LogicalResult {
4497 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4498 return op->
emitError() << name <<
" should be an integer attribute";
4501 auto checkPointerType = [&]() -> LogicalResult {
4502 if (!llvm::isa<LLVMPointerType>(paramType))
4504 << name <<
" attribute attached to non-pointer LLVM type";
4507 auto checkIntegerType = [&]() -> LogicalResult {
4508 if (!llvm::isa<IntegerType>(paramType))
4510 << name <<
" attribute attached to non-integer LLVM type";
4513 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4514 if (
failed(checkPointerType()))
4521 if (name == LLVMDialect::getNoAliasAttrName() ||
4522 name == LLVMDialect::getReadonlyAttrName() ||
4523 name == LLVMDialect::getReadnoneAttrName() ||
4524 name == LLVMDialect::getWriteOnlyAttrName() ||
4525 name == LLVMDialect::getNestAttrName() ||
4526 name == LLVMDialect::getNoCaptureAttrName() ||
4527 name == LLVMDialect::getNoFreeAttrName() ||
4528 name == LLVMDialect::getNonNullAttrName()) {
4529 if (
failed(checkUnitAttrType()))
4531 if (verifyValueType &&
failed(checkPointerType()))
4537 if (name == LLVMDialect::getStructRetAttrName() ||
4538 name == LLVMDialect::getByValAttrName() ||
4539 name == LLVMDialect::getByRefAttrName() ||
4540 name == LLVMDialect::getElementTypeAttrName() ||
4541 name == LLVMDialect::getInAllocaAttrName() ||
4542 name == LLVMDialect::getPreallocatedAttrName()) {
4543 if (
failed(checkTypeAttrType()))
4545 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4551 if (name == LLVMDialect::getSExtAttrName() ||
4552 name == LLVMDialect::getZExtAttrName()) {
4553 if (
failed(checkUnitAttrType()))
4555 if (verifyValueType &&
failed(checkIntegerType()))
4561 if (name == LLVMDialect::getAlignAttrName() ||
4562 name == LLVMDialect::getDereferenceableAttrName() ||
4563 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4564 if (
failed(checkIntegerAttrType()))
4566 if (verifyValueType &&
failed(checkPointerType()))
4572 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4573 if (
failed(checkIntegerAttrType()))
4579 if (name == LLVMDialect::getNoUndefAttrName() ||
4580 name == LLVMDialect::getInRegAttrName() ||
4581 name == LLVMDialect::getReturnedAttrName())
4582 return checkUnitAttrType();
4588LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4592 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4595 Type argType = funcOp.getArgumentTypes()[argIdx];
4597 return verifyParameterAttribute(op, argType, argAttr);
4600LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4604 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4607 Type resType = funcOp.getResultTypes()[resIdx];
4611 if (llvm::isa<LLVMVoidType>(resType))
4612 return op->
emitError() <<
"cannot attach result attributes to functions "
4613 "with a void return";
4617 auto name = resAttr.
getName();
4618 if (name == LLVMDialect::getAllocAlignAttrName() ||
4619 name == LLVMDialect::getAllocatedPointerAttrName() ||
4620 name == LLVMDialect::getByValAttrName() ||
4621 name == LLVMDialect::getByRefAttrName() ||
4622 name == LLVMDialect::getInAllocaAttrName() ||
4623 name == LLVMDialect::getNestAttrName() ||
4624 name == LLVMDialect::getNoCaptureAttrName() ||
4625 name == LLVMDialect::getNoFreeAttrName() ||
4626 name == LLVMDialect::getPreallocatedAttrName() ||
4627 name == LLVMDialect::getReadnoneAttrName() ||
4628 name == LLVMDialect::getReadonlyAttrName() ||
4629 name == LLVMDialect::getReturnedAttrName() ||
4630 name == LLVMDialect::getStackAlignmentAttrName() ||
4631 name == LLVMDialect::getStructRetAttrName() ||
4632 name == LLVMDialect::getWriteOnlyAttrName())
4633 return op->
emitError() << name <<
" is not a valid result attribute";
4634 return verifyParameterAttribute(op, resType, resAttr);
4642 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4643 if (isa<LLVM::LLVMPointerType>(type))
4644 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4645 if (isa<LLVM::UndefAttr>(value))
4646 return LLVM::UndefOp::create(builder, loc, type);
4647 if (isa<LLVM::PoisonAttr>(value))
4648 return LLVM::PoisonOp::create(builder, loc, type);
4649 if (isa<LLVM::ZeroAttr>(value))
4650 return LLVM::ZeroOp::create(builder, loc, type);
4652 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4660 StringRef name, StringRef value,
4661 LLVM::Linkage linkage) {
4664 "expected builder to point to a block constrained in an op");
4666 builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4667 assert(module &&
"builder points to an op outside of a module");
4672 auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4673 auto global = LLVM::GlobalOp::create(
4674 moduleBuilder, loc, type,
true, linkage, name,
4677 LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4680 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4681 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4693 module = module->getParentOp();
4694 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.
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()
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
const FrozenRewritePatternSet GreedyRewriteConfig bool * changed
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.
const FrozenRewritePatternSet & patterns
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.