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>([&](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,
1007 LLVMFunctionType calleeType, StringRef callee,
1009 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1013 LLVMFunctionType calleeType, StringAttr callee,
1015 build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
1031 nullptr,
nullptr,
nullptr,
1037 LLVMFunctionType calleeType,
ValueRange args) {
1042 nullptr,
nullptr,
nullptr,
1043 nullptr,
nullptr,
nullptr,
1054 auto calleeType =
func.getFunctionType();
1058 nullptr,
nullptr,
nullptr,
1059 nullptr,
nullptr,
nullptr,
1073 return getOperand(0);
1079 auto symRef = cast<SymbolRefAttr>(callee);
1080 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1083 return setOperand(0, cast<Value>(callee));
1087 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1092 getCalleeOperands().size());
1099 if (callee.isExternal())
1101 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1105 auto hasSubprogram = [](
Operation *op) {
1110 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1112 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1114 return callOp.emitError()
1115 <<
"inlinable function call in a function with a DISubprogram "
1116 "location must have a debug location";
1122template <
typename OpTy>
1124 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1129 if (!varCalleeType->isVarArg())
1130 return callOp.emitOpError(
1131 "expected var_callee_type to be a variadic function type");
1135 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1136 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1137 << callOp.getArgOperands().size() <<
" parameters";
1140 for (
auto [paramType, operand] :
1141 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1142 if (paramType != operand.getType())
1143 return callOp.emitOpError()
1144 <<
"var_callee_type parameter type mismatch: " << paramType
1145 <<
" != " << operand.getType();
1148 if (!callOp.getNumResults()) {
1149 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1150 return callOp.emitOpError(
"expected var_callee_type to return void");
1152 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1153 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1154 << varCalleeType->getReturnType()
1155 <<
" != " << callOp.getResult().getType();
1160template <
typename OpType>
1163 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1165 auto isStringAttr = [](
Attribute tagAttr) {
1166 return isa<StringAttr>(tagAttr);
1168 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1169 return op.emitError(
"operand bundle tag must be a StringAttr");
1171 size_t numOpBundles = opBundleOperands.size();
1172 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1173 if (numOpBundles != numOpBundleTags)
1174 return op.emitError(
"expected ")
1175 << numOpBundles <<
" operand bundle tags, but actually got "
1191 bool isIndirect =
false;
1197 if (!getNumOperands())
1199 "must have either a `callee` attribute or at least an operand");
1200 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1202 return emitOpError(
"indirect call expects a pointer as callee: ")
1203 << getOperand(0).getType();
1212 <<
"' does not reference a symbol in the current scope";
1213 if (
auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1216 fnType = fn.getFunctionType();
1217 }
else if (
auto ifunc = dyn_cast<IFuncOp>(callee)) {
1218 fnType = ifunc.getIFuncType();
1222 <<
"' does not reference a valid LLVM function or IFunc";
1226 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1228 return emitOpError(
"callee does not have a functional type: ") << fnType;
1230 if (funcType.isVarArg() && !getVarCalleeType())
1231 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1235 if (!funcType.isVarArg() &&
1236 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1237 return emitOpError() <<
"incorrect number of operands ("
1238 << (getCalleeOperands().size() - isIndirect)
1239 <<
") for callee (expecting: "
1240 << funcType.getNumParams() <<
")";
1242 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1243 return emitOpError() <<
"incorrect number of operands ("
1244 << (getCalleeOperands().size() - isIndirect)
1245 <<
") for varargs callee (expecting at least: "
1246 << funcType.getNumParams() <<
")";
1248 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1249 if (getOperand(i + isIndirect).
getType() != funcType.getParamType(i))
1250 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1251 << getOperand(i + isIndirect).getType()
1252 <<
" != " << funcType.getParamType(i);
1254 if (getNumResults() == 0 &&
1255 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1256 return emitOpError() <<
"expected function call to produce a value";
1258 if (getNumResults() != 0 &&
1259 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1261 <<
"calling function with void result must not produce values";
1263 if (getNumResults() > 1)
1265 <<
"expected LLVM function call to produce 0 or 1 result";
1267 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1268 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1269 <<
" != " << funcType.getReturnType();
1275 auto callee = getCallee();
1276 bool isDirect = callee.has_value();
1281 if (getCConv() != LLVM::CConv::C)
1282 p << stringifyCConv(getCConv()) <<
' ';
1284 if (getTailCallKind() != LLVM::TailCallKind::None)
1285 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1294 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1295 p <<
'(' << args <<
')';
1298 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1299 p <<
" vararg(" << *varCalleeType <<
")";
1301 if (!getOpBundleOperands().empty()) {
1304 getOpBundleOperands().getTypes(), getOpBundleTags());
1308 {getCalleeAttrName(), getTailCallKindAttrName(),
1309 getVarCalleeTypeAttrName(), getCConvAttrName(),
1310 getOperandSegmentSizesAttrName(),
1311 getOpBundleSizesAttrName(),
1312 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1313 getResAttrsAttrName()});
1317 p << getOperand(0).getType() <<
", ";
1321 p, args.getTypes(), getArgAttrsAttr(),
1322 false, getResultTypes(), getResAttrsAttr());
1337 types.emplace_back();
1342 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1347 resTypes, resultAttrs)) {
1349 return parser.
emitError(trailingTypesLoc,
1350 "expected direct call to have 1 trailing types");
1351 return parser.
emitError(trailingTypesLoc,
1352 "expected trailing function type");
1355 if (resTypes.size() > 1)
1356 return parser.
emitError(trailingTypesLoc,
1357 "expected function with 0 or 1 result");
1358 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1359 return parser.
emitError(trailingTypesLoc,
1360 "expected a non-void result type");
1366 llvm::append_range(types, argTypes);
1370 if (!resTypes.empty())
1371 result.addTypes(resTypes);
1384 if (failed(*parseResult))
1385 return *parseResult;
1386 operands.push_back(funcPtrOperand);
1395 StringAttr opBundleSizesAttrName) {
1396 unsigned opBundleIndex = 0;
1397 for (
const auto &[operands, types] :
1398 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1399 if (operands.size() != types.size())
1400 return parser.
emitError(loc,
"expected ")
1402 <<
" types for operand bundle operands for operand bundle #"
1403 << opBundleIndex <<
", but actually got " << types.size();
1409 opBundleSizes.reserve(opBundleOperands.size());
1410 for (
const auto &operands : opBundleOperands)
1411 opBundleSizes.push_back(operands.size());
1414 opBundleSizesAttrName,
1426 SymbolRefAttr funcAttr;
1427 TypeAttr varCalleeType;
1435 getCConvAttrName(
result.name),
1440 getTailCallKindAttrName(
result.name),
1443 parser, LLVM::TailCallKind::None)));
1448 bool isDirect = operands.empty();
1461 StringAttr varCalleeTypeAttrName =
1462 CallOp::getVarCalleeTypeAttrName(
result.name);
1474 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1477 if (opBundleTags && !opBundleTags.empty())
1478 result.addAttribute(CallOp::getOpBundleTagsAttrName(
result.name).getValue(),
1488 argAttrs, resultAttrs))
1492 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1494 opBundleOperandTypes,
1495 getOpBundleSizesAttrName(
result.name)))
1498 int32_t numOpBundleOperands = 0;
1499 for (
const auto &operands : opBundleOperands)
1500 numOpBundleOperands += operands.size();
1503 CallOp::getOperandSegmentSizeAttr(),
1505 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1509LLVMFunctionType CallOp::getCalleeFunctionType() {
1510 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1511 return *varCalleeType;
1522 auto calleeType =
func.getFunctionType();
1525 nullptr,
nullptr, normalOps, unwindOps,
1526 nullptr,
nullptr, {}, {}, normal, unwind);
1533 build(builder, state, tys,
1534 nullptr, callee, ops,
nullptr,
1535 nullptr, normalOps, unwindOps,
nullptr,
nullptr, {}, {},
1545 nullptr,
nullptr, normalOps, unwindOps,
1546 nullptr,
nullptr, {}, {}, normal, unwind);
1550 assert(
index < getNumSuccessors() &&
"invalid successor index");
1552 : getUnwindDestOperandsMutable());
1560 return getOperand(0);
1566 auto symRef = cast<SymbolRefAttr>(callee);
1567 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1570 return setOperand(0, cast<Value>(callee));
1574 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1579 getCalleeOperands().size());
1582LogicalResult InvokeOp::verify() {
1586 Block *unwindDest = getUnwindDest();
1587 if (unwindDest->
empty())
1588 return emitError(
"must have at least one operation in unwind destination");
1591 if (!isa<LandingpadOp>(unwindDest->
front()))
1592 return emitError(
"first operation in unwind destination should be a "
1593 "llvm.landingpad operation");
1602 auto callee = getCallee();
1603 bool isDirect = callee.has_value();
1608 if (getCConv() != LLVM::CConv::C)
1609 p << stringifyCConv(getCConv()) <<
' ';
1617 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1624 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1625 p <<
" vararg(" << *varCalleeType <<
")";
1627 if (!getOpBundleOperands().empty()) {
1630 getOpBundleOperands().getTypes(), getOpBundleTags());
1634 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1635 getCConvAttrName(), getVarCalleeTypeAttrName(),
1636 getOpBundleSizesAttrName(),
1637 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1638 getResAttrsAttrName()});
1642 p << getOperand(0).getType() <<
", ";
1644 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1646 false, getResultTypes(), getResAttrsAttr());
1659 SymbolRefAttr funcAttr;
1660 TypeAttr varCalleeType;
1664 Block *normalDest, *unwindDest;
1670 getCConvAttrName(
result.name),
1677 bool isDirect = operands.empty();
1693 StringAttr varCalleeTypeAttrName =
1694 InvokeOp::getVarCalleeTypeAttrName(
result.name);
1706 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1709 if (opBundleTags && !opBundleTags.empty())
1711 InvokeOp::getOpBundleTagsAttrName(
result.name).getValue(),
1721 argAttrs, resultAttrs))
1725 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1728 opBundleOperandTypes,
1729 getOpBundleSizesAttrName(
result.name)))
1732 result.addSuccessors({normalDest, unwindDest});
1733 result.addOperands(normalOperands);
1734 result.addOperands(unwindOperands);
1736 int32_t numOpBundleOperands = 0;
1737 for (
const auto &operands : opBundleOperands)
1738 numOpBundleOperands += operands.size();
1741 InvokeOp::getOperandSegmentSizeAttr(),
1743 static_cast<int32_t>(normalOperands.size()),
1744 static_cast<int32_t>(unwindOperands.size()),
1745 numOpBundleOperands}));
1749LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1750 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1751 return *varCalleeType;
1759LogicalResult LandingpadOp::verify() {
1761 if (LLVMFuncOp
func = (*this)->getParentOfType<LLVMFuncOp>()) {
1762 if (!
func.getPersonality())
1764 "llvm.landingpad needs to be in a function with a personality");
1770 if (!getCleanup() && getOperands().empty())
1771 return emitError(
"landingpad instruction expects at least one clause or "
1772 "cleanup attribute");
1774 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1775 value = getOperand(idx);
1776 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1783 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1786 <<
"global addresses expected as operand to "
1787 "bitcast used in clauses for landingpad";
1795 << idx <<
" is not a known constant - null, addressof, bitcast";
1802 p << (getCleanup() ?
" cleanup " :
" ");
1805 for (
auto value : getOperands()) {
1808 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1809 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1856 Type llvmType = containerType;
1858 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1866 for (
int64_t idx : position) {
1867 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1868 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1869 emitError(
"position out of bounds: ") << idx;
1872 llvmType = arrayType.getElementType();
1873 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1875 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1876 emitError(
"position out of bounds: ") << idx;
1879 llvmType = structType.getBody()[idx];
1881 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1892 for (
int64_t idx : position) {
1893 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1894 llvmType = structType.getBody()[idx];
1896 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1907 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
1908 if (
index <
static_cast<size_t>(elementsAttr.getNumElements()))
1912 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
1913 if (
index < arrayAttr.getValue().size())
1914 return arrayAttr[
index];
1917 if (isa<ZeroAttr, UndefAttr, PoisonAttr>(attr))
1922OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1923 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
1925 newPos.append(getPosition().begin(), getPosition().end());
1926 setPosition(newPos);
1927 getContainerMutable().set(extractValueOp.getContainer());
1933 for (
int64_t pos : getPosition()) {
1938 return containerAttr;
1941 Value container = getContainer();
1943 while (
auto insertValueOp = container.
getDefiningOp<InsertValueOp>()) {
1945 auto extractPosSize = extractPos.size();
1946 auto insertPosSize = insertPos.size();
1949 if (extractPos == insertPos)
1950 return insertValueOp.getValue();
1964 if (extractPosSize > insertPosSize &&
1965 extractPos.take_front(insertPosSize) == insertPos) {
1966 container = insertValueOp.getValue();
1967 extractPos = extractPos.drop_front(insertPosSize);
1983 if (insertPosSize > extractPosSize &&
1984 extractPos == insertPos.take_front(extractPosSize))
1989 container = insertValueOp.getContainer();
1995 if (container == getContainer())
1997 setPosition(extractPos);
1998 getContainerMutable().assign(container);
2002LogicalResult ExtractValueOp::verify() {
2009 if (getRes().
getType() != valueType)
2010 return emitOpError() <<
"Type mismatch: extracting from "
2011 << getContainer().getType() <<
" should produce "
2012 << valueType <<
" but this op returns "
2013 << getRes().getType();
2019 build(builder, state,
2058 LogicalResult matchAndRewrite(InsertValueOp insertOp,
2059 PatternRewriter &rewriter)
const override {
2066 auto insertBaseIdx = insertOp.getPosition()[0];
2067 for (
auto &use : insertOp->getUses()) {
2068 if (
auto extractOp = dyn_cast<ExtractValueOp>(use.getOwner())) {
2069 auto baseIdx = extractOp.getPosition()[0];
2072 if (baseIdx == insertBaseIdx)
2074 posToExtractOps[baseIdx].push_back(extractOp);
2079 Value nextContainer = insertOp.getContainer();
2080 while (!posToExtractOps.empty()) {
2082 dyn_cast_or_null<InsertValueOp>(nextContainer.
getDefiningOp());
2085 nextContainer = curInsert.getContainer();
2088 auto curInsertBaseIdx = curInsert.getPosition()[0];
2089 auto it = posToExtractOps.find(curInsertBaseIdx);
2090 if (it == posToExtractOps.end())
2094 for (
auto &extractOp : it->second) {
2096 extractOp.getContainerMutable().assign(curInsert);
2101 assert(!it->second.empty());
2103 posToExtractOps.erase(it);
2107 for (
auto &[baseIdx, extracts] : posToExtractOps) {
2108 for (
auto &extractOp : extracts) {
2110 extractOp.getContainerMutable().assign(nextContainer);
2113 assert(!extracts.empty() &&
"Empty list in map");
2123 patterns.add<ResolveExtractValueSource>(context);
2132 [&](StringRef msg) {
2145LogicalResult InsertValueOp::verify() {
2152 if (getValue().
getType() != valueType)
2153 return emitOpError() <<
"Type mismatch: cannot insert "
2154 << getValue().getType() <<
" into "
2155 << getContainer().getType();
2164LogicalResult ReturnOp::verify() {
2165 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2169 Type expectedType = parent.getFunctionType().getReturnType();
2170 if (llvm::isa<LLVMVoidType>(expectedType)) {
2174 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2178 if (llvm::isa<LLVMVoidType>(expectedType))
2181 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2184 if (expectedType != getArg().
getType()) {
2186 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2197 return dyn_cast_or_null<GlobalOp>(
2202 return dyn_cast_or_null<LLVMFuncOp>(
2207 return dyn_cast_or_null<AliasOp>(
2212 return dyn_cast_or_null<IFuncOp>(
2221 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2222 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2223 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2224 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2226 if (!global && !function && !alias && !ifunc)
2227 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2228 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2230 LLVMPointerType type =
getType();
2231 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2232 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2233 return emitOpError(
"pointer address space must match address space of the "
2234 "referenced global or alias");
2241 return getGlobalNameAttr();
2262 getFunctionNameAttr());
2263 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2264 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2266 if (!function && !alias)
2268 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2271 if (alias.getInitializer()
2272 .walk([&](AddressOfOp addrOp) {
2273 if (addrOp.getGlobal(symbolTable))
2274 return WalkResult::interrupt();
2275 return WalkResult::advance();
2278 return emitOpError(
"must reference an alias to a function");
2281 if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2282 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2284 "target function with 'extern_weak' linkage not allowed");
2292 return DSOLocalEquivalentAttr::get(
getContext(), getFunctionNameAttr());
2300 StringRef symName) {
2303 Region *body =
result.addRegion();
2307LogicalResult ComdatOp::verifyRegions() {
2308 Region &body = getBody();
2309 for (Operation &op : body.
getOps())
2310 if (!isa<ComdatSelectorOp>(op))
2311 return op.emitError(
2312 "only comdat selector symbols can appear in a comdat region");
2322 bool isConstant, Linkage linkage, StringRef name,
2323 Attribute value, uint64_t alignment,
unsigned addrSpace,
2324 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2329 result.addAttribute(getGlobalTypeAttrName(
result.name), TypeAttr::get(type));
2334 result.addAttribute(getValueAttrName(
result.name), value);
2339 result.addAttribute(getThreadLocal_AttrName(
result.name),
2342 result.addAttribute(getComdatAttrName(
result.name), comdat);
2352 LinkageAttr::get(builder.
getContext(), linkage));
2356 result.attributes.append(attrs.begin(), attrs.end());
2358 if (!dbgExprs.empty())
2360 ArrayAttr::get(builder.
getContext(), dbgExprs));
2365template <
typename OpType>
2367 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2368 StringRef visibility = stringifyVisibility(op.getVisibility_());
2369 if (!visibility.empty())
2370 p << visibility <<
' ';
2371 if (op.getThreadLocal_())
2372 p <<
"thread_local ";
2373 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2374 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2386 if (
auto value = getValueOrNull())
2389 if (
auto comdat = getComdat())
2390 p <<
" comdat(" << *comdat <<
')';
2396 {SymbolTable::getSymbolAttrName(),
2397 getGlobalTypeAttrName(), getConstantAttrName(),
2398 getValueAttrName(), getLinkageAttrName(),
2399 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2400 getVisibility_AttrName(), getComdatAttrName()});
2403 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2407 Region &initializer = getInitializerRegion();
2408 if (!initializer.
empty()) {
2415 std::optional<SymbolRefAttr> attr) {
2420 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2421 return op->
emitError() <<
"expected comdat symbol";
2431 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2432 if (blockTags.contains(blockTagOp.getTag())) {
2433 blockTagOp.emitError()
2434 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2435 <<
"' in the same function: ";
2438 blockTags.insert(blockTagOp.getTag());
2447template <
typename OpType>
2453 OpType::getLinkageAttrName(
result.name),
2455 parser, LLVM::Linkage::External)));
2458 result.addAttribute(OpType::getVisibility_AttrName(
result.name),
2461 parser, LLVM::Visibility::Default)));
2464 result.addAttribute(OpType::getThreadLocal_AttrName(
result.name),
2468 result.addAttribute(OpType::getUnnamedAddrAttrName(
result.name),
2471 parser, LLVM::UnnamedAddr::None)));
2508 SymbolRefAttr comdat;
2513 result.addAttribute(getComdatAttrName(
result.name), comdat);
2521 if (types.size() > 1)
2525 if (types.empty()) {
2526 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2528 auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2529 strAttr.getValue().size());
2530 types.push_back(arrayType);
2533 "type can only be omitted for string globals");
2543 result.addAttribute(getGlobalTypeAttrName(
result.name),
2544 TypeAttr::get(types[0]));
2549 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2550 return intValue.getValue().isZero();
2551 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2552 return fpValue.getValue().isZero();
2553 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2555 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2557 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2562LogicalResult GlobalOp::verify() {
2564 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2565 LLVMMetadataType, LLVMLabelType>(
getType())
2566 :
llvm::isa<PointerElementTypeInterface>(
getType());
2569 "expects type to be a valid element type for an LLVM global");
2571 return emitOpError(
"must appear at the module level");
2573 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2574 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2575 IntegerType elementType =
2576 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) :
nullptr;
2577 if (!elementType || elementType.getWidth() != 8 ||
2578 type.getNumElements() != strAttr.getValue().size())
2580 "requires an i8 array type of the length equal to that of the string "
2584 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2585 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2587 <<
"this target extension type cannot be used in a global";
2590 return emitOpError() <<
"global with target extension type can only be "
2591 "initialized with zero-initializer";
2594 if (getLinkage() == Linkage::Common) {
2595 if (
Attribute value = getValueOrNull()) {
2598 <<
"expected zero value for '"
2599 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2604 if (getLinkage() == Linkage::Appending) {
2605 if (!llvm::isa<LLVMArrayType>(
getType())) {
2606 return emitOpError() <<
"expected array type for '"
2607 << stringifyLinkage(Linkage::Appending)
2615 std::optional<uint64_t> alignAttr = getAlignment();
2616 if (alignAttr.has_value()) {
2617 uint64_t value = alignAttr.value();
2618 if (!llvm::isPowerOf2_64(value))
2619 return emitError() <<
"alignment attribute is not a power of 2";
2625LogicalResult GlobalOp::verifyRegions() {
2626 if (
Block *
b = getInitializerBlock()) {
2627 ReturnOp ret = cast<ReturnOp>(
b->getTerminator());
2628 if (ret.operand_type_begin() == ret.operand_type_end())
2629 return emitOpError(
"initializer region cannot return void");
2630 if (*ret.operand_type_begin() !=
getType())
2632 << *ret.operand_type_begin() <<
" does not match global type "
2636 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2637 if (!iface || !iface.hasNoEffect())
2638 return op.emitError()
2639 <<
"ops with side effects not allowed in global initializers";
2642 if (getValueOrNull())
2643 return emitOpError(
"cannot have both initializer value and region");
2658 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2661 return op->
emitError(
"data element must be symbol or #llvm.zero");
2674LogicalResult GlobalCtorsOp::verify() {
2678 if (getCtors().size() == getPriorities().size() &&
2679 getCtors().size() == getData().size())
2682 "ctors, priorities, and data must have the same number of elements");
2699LogicalResult GlobalDtorsOp::verify() {
2703 if (getDtors().size() == getPriorities().size() &&
2704 getDtors().size() == getData().size())
2707 "dtors, priorities, and data must have the same number of elements");
2715 Linkage linkage, StringRef name,
bool dsoLocal,
2719 result.addAttribute(getAliasTypeAttrName(
result.name), TypeAttr::get(type));
2724 result.addAttribute(getThreadLocal_AttrName(
result.name),
2728 LinkageAttr::get(builder.
getContext(), linkage));
2729 result.attributes.append(attrs.begin(), attrs.end());
2739 {SymbolTable::getSymbolAttrName(),
2740 getAliasTypeAttrName(), getLinkageAttrName(),
2741 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2742 getVisibility_AttrName()});
2745 p <<
" : " <<
getType() <<
' ';
2771 if (types.size() > 1)
2779 TypeAttr::get(types[0]));
2783LogicalResult AliasOp::verify() {
2785 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2786 LLVMMetadataType, LLVMLabelType>(
getType())
2787 :
llvm::isa<PointerElementTypeInterface>(
getType());
2790 "expects type to be a valid element type for an LLVM global alias");
2793 switch (getLinkage()) {
2794 case Linkage::External:
2795 case Linkage::Internal:
2796 case Linkage::Private:
2798 case Linkage::WeakODR:
2799 case Linkage::Linkonce:
2800 case Linkage::LinkonceODR:
2801 case Linkage::AvailableExternally:
2805 <<
"'" << stringifyLinkage(getLinkage())
2806 <<
"' linkage not supported in aliases, available options: private, "
2807 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2808 "available_externally";
2814LogicalResult AliasOp::verifyRegions() {
2815 Block &
b = getInitializerBlock();
2816 auto ret = cast<ReturnOp>(
b.getTerminator());
2817 if (ret.getNumOperands() == 0 ||
2818 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2819 return emitOpError(
"initializer region must always return a pointer");
2822 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2823 if (!iface || !iface.hasNoEffect())
2824 return op.emitError()
2825 <<
"ops with side effects are not allowed in alias initializers";
2831unsigned AliasOp::getAddrSpace() {
2832 Block &initializer = getInitializerBlock();
2834 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2835 return ptrTy.getAddressSpace();
2843 Type iFuncType, StringRef resolverName,
Type resolverType,
2844 Linkage linkage, LLVM::Visibility visibility) {
2845 return build(builder,
result, name, iFuncType, resolverName, resolverType,
2847 UnnamedAddr::None, visibility);
2854 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2855 auto alias = dyn_cast<AliasOp>(symbol);
2857 Block &initBlock = alias.getInitializerBlock();
2859 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
2866 resolver = addrOp.getFunction(symbolTable);
2867 alias = addrOp.getAlias(symbolTable);
2870 return emitOpError(
"must have a function resolver");
2871 Linkage linkage = resolver.getLinkage();
2872 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
2873 return emitOpError(
"resolver must be a definition");
2874 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
2875 return emitOpError(
"resolver must return a pointer");
2876 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
2877 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
2878 return emitOpError(
"resolver has incorrect type");
2882LogicalResult IFuncOp::verify() {
2883 switch (getLinkage()) {
2884 case Linkage::External:
2885 case Linkage::Internal:
2886 case Linkage::Private:
2888 case Linkage::WeakODR:
2889 case Linkage::Linkonce:
2890 case Linkage::LinkonceODR:
2893 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
2894 <<
"' linkage not supported in ifuncs, available "
2895 "options: private, internal, linkonce, weak, "
2896 "linkonce_odr, weak_odr, or external linkage";
2908 auto containerType = v1.
getType();
2912 build(builder, state, vType, v1, v2, mask);
2926 "expected an LLVM compatible vector type");
2937LogicalResult ShuffleVectorOp::verify() {
2939 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2940 return emitOpError(
"expected a splat operation for scalable vectors");
2946OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
2948 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
2949 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
2953 if (getMask().size() != 1 || getMask()[0] != 0)
2964 assert(empty() &&
"function already has an entry block");
2969 LLVMFunctionType type = getFunctionType();
2970 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2971 entry->
addArgument(type.getParamType(i), getLoc());
2976 StringRef name,
Type type, LLVM::Linkage linkage,
2977 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2980 std::optional<uint64_t> functionEntryCount) {
2984 result.addAttribute(getFunctionTypeAttrName(
result.name),
2985 TypeAttr::get(type));
2987 LinkageAttr::get(builder.
getContext(), linkage));
2989 CConvAttr::get(builder.
getContext(), cconv));
2990 result.attributes.append(attrs.begin(), attrs.end());
2995 result.addAttribute(getComdatAttrName(
result.name), comdat);
2996 if (functionEntryCount)
2997 result.addAttribute(getFunctionEntryCountAttrName(
result.name),
2999 if (argAttrs.empty())
3002 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
3003 "expected as many argument attribute lists as arguments");
3005 builder,
result, argAttrs, {},
3006 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3017 if (outputs.size() > 1) {
3018 parser.
emitError(loc,
"failed to construct function type: expected zero or "
3019 "one function result");
3025 for (
auto t : inputs) {
3027 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3028 "type for function arguments");
3031 llvmInputs.push_back(t);
3036 outputs.empty() ? LLVMVoidType::get(
b.getContext()) : outputs.front();
3038 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3039 "type for function results")
3043 return LLVMFunctionType::get(llvmOutput, llvmInputs,
3059 parser, LLVM::Linkage::External)));
3062 result.addAttribute(getVisibility_AttrName(
result.name),
3065 parser, LLVM::Visibility::Default)));
3068 result.addAttribute(getUnnamedAddrAttrName(
result.name),
3071 parser, LLVM::UnnamedAddr::None)));
3075 getCConvAttrName(
result.name),
3079 StringAttr nameAttr;
3089 parser,
true, entryArgs, isVariadic, resultTypes,
3094 for (
auto &arg : entryArgs)
3095 argTypes.push_back(arg.type);
3101 result.addAttribute(getFunctionTypeAttrName(
result.name),
3102 TypeAttr::get(type));
3110 auto intTy = IntegerType::get(parser.
getContext(), 32);
3112 getVscaleRangeAttrName(
result.name),
3113 LLVM::VScaleRangeAttr::get(parser.
getContext(),
3114 IntegerAttr::get(intTy, minRange),
3115 IntegerAttr::get(intTy, maxRange)));
3119 SymbolRefAttr comdat;
3124 result.addAttribute(getComdatAttrName(
result.name), comdat);
3131 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3133 auto *body =
result.addRegion();
3144 if (getLinkage() != LLVM::Linkage::External)
3145 p << stringifyLinkage(getLinkage()) <<
' ';
3146 StringRef visibility = stringifyVisibility(getVisibility_());
3147 if (!visibility.empty())
3148 p << visibility <<
' ';
3149 if (
auto unnamedAddr = getUnnamedAddr()) {
3150 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3154 if (getCConv() != LLVM::CConv::C)
3155 p << stringifyCConv(getCConv()) <<
' ';
3159 LLVMFunctionType fnType = getFunctionType();
3162 argTypes.reserve(fnType.getNumParams());
3163 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3164 argTypes.push_back(fnType.getParamType(i));
3166 Type returnType = fnType.getReturnType();
3167 if (!llvm::isa<LLVMVoidType>(returnType))
3168 resTypes.push_back(returnType);
3171 isVarArg(), resTypes);
3174 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3175 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3176 << vscale->getMaxRange().getInt() <<
')';
3179 if (
auto comdat = getComdat())
3180 p <<
" comdat(" << *comdat <<
')';
3184 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3185 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3186 getComdatAttrName(), getUnnamedAddrAttrName(),
3187 getVscaleRangeAttrName()});
3190 Region &body = getBody();
3191 if (!body.empty()) {
3202LogicalResult LLVMFuncOp::verify() {
3203 if (getLinkage() == LLVM::Linkage::Common)
3205 << stringifyLinkage(LLVM::Linkage::Common)
3212 if (getLinkage() != LLVM::Linkage::External &&
3213 getLinkage() != LLVM::Linkage::ExternWeak)
3214 return emitOpError() <<
"external functions must have '"
3215 << stringifyLinkage(LLVM::Linkage::External)
3217 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3223 if (isNoInline() && isAlwaysInline())
3224 return emitError(
"no_inline and always_inline attributes are incompatible");
3226 if (isOptimizeNone() && !isNoInline())
3227 return emitOpError(
"with optimize_none must also be no_inline");
3229 Type landingpadResultTy;
3230 StringRef diagnosticMessage;
3231 bool isLandingpadTypeConsistent =
3233 const auto checkType = [&](
Type type, StringRef errorMessage) {
3234 if (!landingpadResultTy) {
3235 landingpadResultTy = type;
3238 if (landingpadResultTy != type) {
3239 diagnosticMessage = errorMessage;
3245 .Case<LandingpadOp>([&](
auto landingpad) {
3246 constexpr StringLiteral errorMessage =
3247 "'llvm.landingpad' should have a consistent result type "
3248 "inside a function";
3249 return checkType(landingpad.getType(), errorMessage);
3251 .Case<ResumeOp>([&](
auto resume) {
3252 constexpr StringLiteral errorMessage =
3253 "'llvm.resume' should have a consistent input type inside a "
3255 return checkType(resume.getValue().getType(), errorMessage);
3258 }).wasInterrupted();
3259 if (!isLandingpadTypeConsistent) {
3260 assert(!diagnosticMessage.empty() &&
3261 "Expecting a non-empty diagnostic message");
3273LogicalResult LLVMFuncOp::verifyRegions() {
3277 unsigned numArguments = getFunctionType().getNumParams();
3278 Block &entryBlock = front();
3279 for (
unsigned i = 0; i < numArguments; ++i) {
3283 << i <<
" is not of LLVM type";
3289Region *LLVMFuncOp::getCallableRegion() {
3317LogicalResult LLVM::ZeroOp::verify() {
3318 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3319 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3321 <<
"target extension type does not support zero-initializer";
3343 if (
auto vecType = dyn_cast<VectorType>(t)) {
3344 assert(!vecType.isScalable() &&
3345 "number of elements of a scalable vector type is unknown");
3346 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3348 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3349 return arrayType.getNumElements() *
3357 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3358 type = arrayType.getElementType();
3359 if (
auto vecType = dyn_cast<VectorType>(type))
3360 return vecType.getElementType();
3361 if (
auto tenType = dyn_cast<TensorType>(type))
3362 return tenType.getElementType();
3369 if (
auto vecType = dyn_cast<VectorType>(t)) {
3370 if (vecType.isScalable())
3374 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3382 LLVM::LLVMArrayType arrayType,
3384 if (arrayType.getNumElements() != arrayAttr.size())
3385 return op.emitOpError()
3386 <<
"array attribute size does not match array type size in "
3388 << dim <<
": " << arrayAttr.size() <<
" vs. "
3389 << arrayType.getNumElements();
3394 if (
auto subArrayType =
3395 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3396 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3397 if (elementsVerified.insert(elementAttr).second) {
3398 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3400 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3402 return op.emitOpError()
3403 <<
"nested attribute for sub-array in dimension " << dim
3404 <<
" at index " << idx
3405 <<
" must be a zero, or undef, or array attribute";
3419 auto structType = dyn_cast<LLVM::LLVMStructType>(arrayType.getElementType());
3421 return op.emitOpError() <<
"for array with an array attribute must have a "
3422 "struct element type";
3426 size_t numStructElements = structType.getBody().size();
3427 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3428 if (elementsVerified.insert(elementAttr).second) {
3429 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3431 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3433 return op.emitOpError()
3434 <<
"nested attribute for struct element at index " << idx
3435 <<
" must be a zero, or undef, or array attribute";
3436 if (subArrayAttr.size() != numStructElements)
3437 return op.emitOpError()
3438 <<
"nested array attribute size for struct element at index "
3439 << idx <<
" must match struct size: " << subArrayAttr.size()
3440 <<
" vs. " << numStructElements;
3447LogicalResult LLVM::ConstantOp::verify() {
3448 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3449 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3450 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3451 !arrayType.getElementType().isInteger(8)) {
3453 << sAttr.getValue().size()
3454 <<
" i8 elements for the string constant";
3458 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3459 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3461 return emitOpError() <<
"expected array attribute for struct type";
3464 if (arrayAttr.size() != elementTypes.size()) {
3465 return emitOpError() <<
"expected array attribute of size "
3466 << elementTypes.size();
3468 for (
auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3470 return emitOpError() <<
"expected struct element types to be floating "
3471 "point type or integer type";
3473 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3474 return emitOpError() <<
"expected element of array attribute to be "
3475 "floating point or integer";
3477 if (cast<TypedAttr>(attr).
getType() != type)
3479 <<
"struct element at index " << i <<
" is of wrong type";
3484 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3485 return emitOpError() <<
"does not support target extension type.";
3496 auto verifyFloatSemantics =
3497 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3498 Type constantElementType) -> LogicalResult {
3499 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3500 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3502 <<
"attribute and type have different float semantics";
3506 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3507 if (isa<IntegerType>(constantElementType)) {
3508 if (!constantElementType.isInteger(floatWidth))
3509 return emitOpError() <<
"expected integer type of width " << floatWidth;
3517 if (isa<IntegerAttr>(getValue())) {
3518 if (!llvm::isa<IntegerType>(
getType()))
3520 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3521 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3522 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3526 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3527 if (!splatElementsAttr)
3529 <<
"scalable vector type requires a splat attribute";
3532 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3533 return emitOpError() <<
"expected vector or array type";
3536 int64_t attrNumElements = elementsAttr.getNumElements();
3539 <<
"type and attribute have a different number of elements: "
3545 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3546 return verifyFloatSemantics(floatType.getFloatSemantics(), resultElmType);
3548 if (isa<IntegerType>(attrElmType) && !isa<IntegerType>(resultElmType)) {
3550 "expected integer element type for integer elements attribute");
3552 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3555 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3558 <<
"expected array or struct type for array attribute";
3565 <<
"only supports integer, float, string or elements attributes";
3571bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3573 auto typedAttr = dyn_cast<TypedAttr>(value);
3580 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3585 if (isBuildableWith(value, type))
3586 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3591OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3599 AtomicOrdering ordering, StringRef syncscope,
3600 unsigned alignment,
bool isVolatile) {
3601 build(builder, state, val.
getType(), binOp,
ptr, val, ordering,
3602 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3605 nullptr,
nullptr,
nullptr);
3608LogicalResult AtomicRMWOp::verify() {
3609 auto valType = getVal().getType();
3610 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3611 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3612 getBinOp() == AtomicBinOp::fminimum ||
3613 getBinOp() == AtomicBinOp::fmaximum) {
3616 return emitOpError(
"expected LLVM IR fixed vector type");
3617 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3620 "expected LLVM IR floating point type for vector element");
3622 return emitOpError(
"expected LLVM IR floating point type");
3624 }
else if (getBinOp() == AtomicBinOp::xchg) {
3627 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3629 auto intType = llvm::dyn_cast<IntegerType>(valType);
3630 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3631 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3633 return emitOpError(
"expected LLVM IR integer type");
3636 if (
static_cast<unsigned>(getOrdering()) <
3637 static_cast<unsigned>(AtomicOrdering::monotonic))
3639 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3651 auto boolType = IntegerType::get(valType.
getContext(), 1);
3652 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3657 AtomicOrdering successOrdering,
3658 AtomicOrdering failureOrdering, StringRef syncscope,
3659 unsigned alignment,
bool isWeak,
bool isVolatile) {
3661 successOrdering, failureOrdering,
3662 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3664 isVolatile,
nullptr,
3665 nullptr,
nullptr,
nullptr);
3668LogicalResult AtomicCmpXchgOp::verify() {
3669 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3671 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3672 auto valType = getVal().getType();
3676 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3677 getFailureOrdering() < AtomicOrdering::monotonic)
3678 return emitOpError(
"ordering must be at least 'monotonic'");
3679 if (getFailureOrdering() == AtomicOrdering::release ||
3680 getFailureOrdering() == AtomicOrdering::acq_rel)
3681 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3690 AtomicOrdering ordering, StringRef syncscope) {
3691 build(builder, state, ordering,
3692 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3695LogicalResult FenceOp::verify() {
3696 if (getOrdering() == AtomicOrdering::not_atomic ||
3697 getOrdering() == AtomicOrdering::unordered ||
3698 getOrdering() == AtomicOrdering::monotonic)
3699 return emitOpError(
"can be given only acquire, release, acq_rel, "
3700 "and seq_cst orderings");
3710template <
class ExtOp>
3712 IntegerType inputType, outputType;
3715 return op.emitError(
3716 "input type is a vector but output type is an integer");
3719 return op.emitError(
"input and output vectors are of incompatible shape");
3722 inputType = cast<IntegerType>(
3723 cast<VectorType>(op.getArg().getType()).getElementType());
3724 outputType = cast<IntegerType>(
3725 cast<VectorType>(op.getResult().getType()).getElementType());
3729 inputType = cast<IntegerType>(op.getArg().getType());
3730 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3732 return op.emitError(
3733 "input type is an integer but output type is a vector");
3736 if (outputType.getWidth() <= inputType.getWidth())
3737 return op.emitError(
"integer width of the output type is smaller or "
3738 "equal to the integer width of the input type");
3749 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3753 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3754 return IntegerAttr::get(
getType(), arg.getValue().zext(targetSize));
3768template <
typename T>
3770 typename T::FoldAdaptor adaptor) {
3772 if (castOp.getArg().getType() == castOp.getType())
3773 return castOp.getArg();
3774 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3776 if (prev.getArg().getType() == castOp.getType())
3777 return prev.getArg();
3779 castOp.getArgMutable().set(prev.getArg());
3780 return Value{castOp};
3785OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3789LogicalResult LLVM::BitcastOp::verify() {
3790 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3792 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3797 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3798 return emitOpError(
"can only cast pointers from and to pointers");
3803 auto isVector = llvm::IsaPred<VectorType>;
3807 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3808 return emitOpError(
"cannot cast pointer to vector of pointers");
3810 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3811 return emitOpError(
"cannot cast vector of pointers to pointer");
3815 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3816 return emitOpError(
"cannot cast pointers of different address spaces, "
3817 "use 'llvm.addrspacecast' instead");
3826OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3830Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3838 adaptor.getDynamicIndices());
3842 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(
indices[0]))
3843 if (integer.getValue().isZero())
3849 for (
auto iter : llvm::enumerate(
indices)) {
3850 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3853 if (!
indices.isDynamicIndex(iter.index()) || !integer ||
3857 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3858 gepArgs.emplace_back(val);
3860 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3866 gepArgs.emplace_back(integer.getInt());
3874 getDynamicIndicesMutable().assign(dynamicIndices);
3875 setRawConstantIndices(rawConstantIndices);
3876 return Value{*
this};
3882Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3889 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3893 if (
rhs.getValue().getZExtValue() >=
3894 getLhs().
getType().getIntOrFloatBitWidth())
3897 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3901 return IntegerAttr::get(
getType(),
lhs.getValue().shl(
rhs.getValue()));
3909 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3913 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3917 return IntegerAttr::get(
getType(),
lhs.getValue() |
rhs.getValue());
3924LogicalResult CallIntrinsicOp::verify() {
3925 if (!getIntrin().starts_with(
"llvm."))
3926 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3934 build(builder, state,
TypeRange{}, intrin, args,
3935 FastmathFlagsAttr{},
3942 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3943 build(builder, state,
TypeRange{}, intrin, args,
3950 mlir::Type resultType, mlir::StringAttr intrin,
3952 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
3960 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3961 build(builder, state, resultTypes, intrin, args, fastMathFlags,
3966ParseResult CallIntrinsicOp::parse(
OpAsmParser &parser,
3968 StringAttr intrinAttr;
3978 result.addAttribute(CallIntrinsicOp::getIntrinAttrName(
result.name),
3986 return mlir::failure();
3989 return mlir::failure();
3994 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
3997 if (opBundleTags && !opBundleTags.empty())
3999 CallIntrinsicOp::getOpBundleTagsAttrName(
result.name).getValue(),
4003 return mlir::failure();
4008 operands, argAttrs, resultAttrs))
4012 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
4015 opBundleOperandTypes,
4016 getOpBundleSizesAttrName(
result.name)))
4019 int32_t numOpBundleOperands = 0;
4020 for (
const auto &operands : opBundleOperands)
4021 numOpBundleOperands += operands.size();
4024 CallIntrinsicOp::getOperandSegmentSizeAttr(),
4026 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
4028 return mlir::success();
4036 p <<
"(" << args <<
")";
4039 if (!getOpBundleOperands().empty()) {
4042 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
4046 {getOperandSegmentSizesAttrName(),
4047 getOpBundleSizesAttrName(), getIntrinAttrName(),
4048 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
4049 getResAttrsAttrName()});
4055 p, args.
getTypes(), getArgAttrsAttr(),
4056 false, getResultTypes(), getResAttrsAttr());
4063LogicalResult LinkerOptionsOp::verify() {
4066 return emitOpError(
"must appear at the module level");
4074LogicalResult ModuleFlagsOp::verify() {
4077 return emitOpError(
"must appear at the module level");
4079 if (!isa<ModuleFlagAttr>(flag))
4080 return emitOpError(
"expected a module flag attribute");
4088void InlineAsmOp::getEffects(
4091 if (getHasSideEffects()) {
4104 getBlockAddr().getFunction());
4105 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
4108 return emitOpError(
"must reference a function defined by 'llvm.func'");
4118BlockTagOp BlockAddressOp::getBlockTagOp() {
4124 BlockTagOp blockTagOp =
nullptr;
4125 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4126 if (labelOp.getTag() == getBlockAddr().getTag()) {
4127 blockTagOp = labelOp;
4135LogicalResult BlockAddressOp::verify() {
4136 if (!getBlockTagOp())
4138 "expects an existing block label target in the referenced function");
4145OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4152 assert(
index < getNumSuccessors() &&
"invalid successor index");
4164 rangeSegments.push_back(range.size());
4178 Block *destination = nullptr;
4179 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4180 SmallVector<Type> operandTypes;
4182 if (parser.parseSuccessor(destination).failed())
4185 if (succeeded(parser.parseOptionalLParen())) {
4186 if (failed(parser.parseOperandList(
4187 operands, OpAsmParser::Delimiter::None)) ||
4188 failed(parser.parseColonTypeList(operandTypes)) ||
4189 failed(parser.parseRParen()))
4192 succOperandBlocks.push_back(destination);
4193 succOperands.emplace_back(operands);
4194 succOperandsTypes.emplace_back(operandTypes);
4197 "successor blocks")))
4208 llvm::zip(succs, succOperands),
4214 if (!succOperands.empty())
4223LogicalResult LLVM::SincosOp::verify() {
4224 auto operandType = getOperand().getType();
4225 auto resultType = getResult().getType();
4226 auto resultStructType =
4227 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4228 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4229 resultStructType.getBody()[0] != operandType ||
4230 resultStructType.getBody()[1] != operandType) {
4231 return emitOpError(
"expected result type to be an homogeneous struct with "
4232 "two elements matching the operand type, but got ")
4244 return build(builder, state, cond, {},
4256 return build(builder, state, cond,
"align",
ValueRange{
ptr, align});
4262 return build(builder, state, cond,
"separate_storage",
4272LogicalResult LLVM::masked_gather::verify() {
4273 auto ptrsVectorType = getPtrs().getType();
4274 Type expectedPtrsVectorType =
4279 if (ptrsVectorType != expectedPtrsVectorType)
4280 return emitOpError(
"expected operand #1 type to be ")
4281 << expectedPtrsVectorType;
4289LogicalResult LLVM::masked_scatter::verify() {
4290 auto ptrsVectorType = getPtrs().getType();
4291 Type expectedPtrsVectorType =
4296 if (ptrsVectorType != expectedPtrsVectorType)
4297 return emitOpError(
"expected operand #2 type to be ")
4298 << expectedPtrsVectorType;
4311 build(builder, state, resTys,
ptr, mask, passthru, argAttrs,
4319void LLVM::masked_compressstore::build(
OpBuilder &builder,
4324 build(builder, state, value,
ptr, mask, argAttrs,
4332LogicalResult InlineAsmOp::verify() {
4333 if (!getTailCallKindAttr())
4336 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4338 "tail call kind 'musttail' is not supported by this operation");
4348 Value divisor = getRhs();
4363 Value divisor = getRhs();
4375void LLVMDialect::initialize() {
4376 registerAttributes();
4379 addTypes<LLVMVoidType,
4382 LLVMMetadataType>();
4388#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4392#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4397 allowUnknownOperations();
4398 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4402#define GET_OP_CLASSES
4403#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4405#define GET_OP_CLASSES
4406#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4408LogicalResult LLVMDialect::verifyDataLayoutString(
4411 llvm::DataLayout::parse(descr);
4412 if (maybeDataLayout)
4415 std::string message;
4416 llvm::raw_string_ostream messageStream(message);
4417 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4418 reportError(
"invalid data layout descriptor: " + message);
4423LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4429 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4431 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4432 return verifyDataLayoutString(
4433 stringAttr.getValue(),
4434 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4437 << LLVM::LLVMDialect::getDataLayoutAttrName()
4438 <<
"' to be a string attributes";
4441LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4449 StringAttr name = paramAttr.
getName();
4451 auto checkUnitAttrType = [&]() -> LogicalResult {
4452 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4453 return op->
emitError() << name <<
" should be a unit attribute";
4456 auto checkTypeAttrType = [&]() -> LogicalResult {
4457 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4458 return op->
emitError() << name <<
" should be a type attribute";
4461 auto checkIntegerAttrType = [&]() -> LogicalResult {
4462 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4463 return op->
emitError() << name <<
" should be an integer attribute";
4466 auto checkPointerType = [&]() -> LogicalResult {
4467 if (!llvm::isa<LLVMPointerType>(paramType))
4469 << name <<
" attribute attached to non-pointer LLVM type";
4472 auto checkIntegerType = [&]() -> LogicalResult {
4473 if (!llvm::isa<IntegerType>(paramType))
4475 << name <<
" attribute attached to non-integer LLVM type";
4478 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4479 if (
failed(checkPointerType()))
4486 if (name == LLVMDialect::getNoAliasAttrName() ||
4487 name == LLVMDialect::getReadonlyAttrName() ||
4488 name == LLVMDialect::getReadnoneAttrName() ||
4489 name == LLVMDialect::getWriteOnlyAttrName() ||
4490 name == LLVMDialect::getNestAttrName() ||
4491 name == LLVMDialect::getNoCaptureAttrName() ||
4492 name == LLVMDialect::getNoFreeAttrName() ||
4493 name == LLVMDialect::getNonNullAttrName()) {
4494 if (
failed(checkUnitAttrType()))
4496 if (verifyValueType &&
failed(checkPointerType()))
4502 if (name == LLVMDialect::getStructRetAttrName() ||
4503 name == LLVMDialect::getByValAttrName() ||
4504 name == LLVMDialect::getByRefAttrName() ||
4505 name == LLVMDialect::getElementTypeAttrName() ||
4506 name == LLVMDialect::getInAllocaAttrName() ||
4507 name == LLVMDialect::getPreallocatedAttrName()) {
4508 if (
failed(checkTypeAttrType()))
4510 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4516 if (name == LLVMDialect::getSExtAttrName() ||
4517 name == LLVMDialect::getZExtAttrName()) {
4518 if (
failed(checkUnitAttrType()))
4520 if (verifyValueType &&
failed(checkIntegerType()))
4526 if (name == LLVMDialect::getAlignAttrName() ||
4527 name == LLVMDialect::getDereferenceableAttrName() ||
4528 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4529 if (
failed(checkIntegerAttrType()))
4531 if (verifyValueType &&
failed(checkPointerType()))
4537 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4538 if (
failed(checkIntegerAttrType()))
4544 if (name == LLVMDialect::getNoUndefAttrName() ||
4545 name == LLVMDialect::getInRegAttrName() ||
4546 name == LLVMDialect::getReturnedAttrName())
4547 return checkUnitAttrType();
4553LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4557 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4560 Type argType = funcOp.getArgumentTypes()[argIdx];
4562 return verifyParameterAttribute(op, argType, argAttr);
4565LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4569 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4572 Type resType = funcOp.getResultTypes()[resIdx];
4576 if (llvm::isa<LLVMVoidType>(resType))
4577 return op->
emitError() <<
"cannot attach result attributes to functions "
4578 "with a void return";
4582 auto name = resAttr.
getName();
4583 if (name == LLVMDialect::getAllocAlignAttrName() ||
4584 name == LLVMDialect::getAllocatedPointerAttrName() ||
4585 name == LLVMDialect::getByValAttrName() ||
4586 name == LLVMDialect::getByRefAttrName() ||
4587 name == LLVMDialect::getInAllocaAttrName() ||
4588 name == LLVMDialect::getNestAttrName() ||
4589 name == LLVMDialect::getNoCaptureAttrName() ||
4590 name == LLVMDialect::getNoFreeAttrName() ||
4591 name == LLVMDialect::getPreallocatedAttrName() ||
4592 name == LLVMDialect::getReadnoneAttrName() ||
4593 name == LLVMDialect::getReadonlyAttrName() ||
4594 name == LLVMDialect::getReturnedAttrName() ||
4595 name == LLVMDialect::getStackAlignmentAttrName() ||
4596 name == LLVMDialect::getStructRetAttrName() ||
4597 name == LLVMDialect::getWriteOnlyAttrName())
4598 return op->
emitError() << name <<
" is not a valid result attribute";
4599 return verifyParameterAttribute(op, resType, resAttr);
4607 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4608 if (isa<LLVM::LLVMPointerType>(type))
4609 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4610 if (isa<LLVM::UndefAttr>(value))
4611 return LLVM::UndefOp::create(builder, loc, type);
4612 if (isa<LLVM::PoisonAttr>(value))
4613 return LLVM::PoisonOp::create(builder, loc, type);
4614 if (isa<LLVM::ZeroAttr>(value))
4615 return LLVM::ZeroOp::create(builder, loc, type);
4617 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4625 StringRef name, StringRef value,
4626 LLVM::Linkage linkage) {
4629 "expected builder to point to a block constrained in an op");
4631 builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4632 assert(module &&
"builder points to an op outside of a module");
4637 auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4638 auto global = LLVM::GlobalOp::create(
4639 moduleBuilder, loc, type,
true, linkage, name,
4642 LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4645 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4646 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4658 module = module->getParentOp();
4659 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.