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());
1931 Operation *container = getContainer().getDefiningOp();
1934 bool switchedToInsertedValue =
false;
1935 while (
auto insertValueOp = dyn_cast_if_present<InsertValueOp>(container)) {
1937 auto extractPosSize = extractPos.size();
1938 auto insertPosSize = insertPos.size();
1941 if (extractPos == insertPos)
1942 return insertValueOp.getValue();
1956 if (extractPosSize > insertPosSize &&
1957 extractPos.take_front(insertPosSize) == insertPos) {
1958 container = insertValueOp.getValue().getDefiningOp();
1959 extractPos = extractPos.drop_front(insertPosSize);
1960 switchedToInsertedValue =
true;
1965 unsigned min = std::min(extractPosSize, insertPosSize);
1977 if (extractPos.take_front(
min) == insertPos.take_front(
min))
1982 if (!switchedToInsertedValue) {
1985 getContainerMutable().assign(insertValueOp.getContainer());
1988 container = insertValueOp.getContainer().getDefiningOp();
1996 for (
int64_t pos : extractPos) {
2001 return containerAttr;
2004LogicalResult ExtractValueOp::verify() {
2011 if (getRes().
getType() != valueType)
2012 return emitOpError() <<
"Type mismatch: extracting from "
2013 << getContainer().getType() <<
" should produce "
2014 << valueType <<
" but this op returns "
2015 << getRes().getType();
2021 build(builder, state,
2036 [&](StringRef msg) {
2049LogicalResult InsertValueOp::verify() {
2056 if (getValue().
getType() != valueType)
2057 return emitOpError() <<
"Type mismatch: cannot insert "
2058 << getValue().getType() <<
" into "
2059 << getContainer().getType();
2068LogicalResult ReturnOp::verify() {
2069 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2073 Type expectedType = parent.getFunctionType().getReturnType();
2074 if (llvm::isa<LLVMVoidType>(expectedType)) {
2078 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2082 if (llvm::isa<LLVMVoidType>(expectedType))
2085 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2088 if (expectedType != getArg().
getType()) {
2090 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2101 return dyn_cast_or_null<GlobalOp>(
2106 return dyn_cast_or_null<LLVMFuncOp>(
2111 return dyn_cast_or_null<AliasOp>(
2116 return dyn_cast_or_null<IFuncOp>(
2125 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2126 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2127 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2128 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2130 if (!global && !function && !alias && !ifunc)
2131 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2132 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2134 LLVMPointerType type =
getType();
2135 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2136 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2137 return emitOpError(
"pointer address space must match address space of the "
2138 "referenced global or alias");
2145 return getGlobalNameAttr();
2166 getFunctionNameAttr());
2167 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2168 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2170 if (!function && !alias)
2172 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2175 if (alias.getInitializer()
2176 .walk([&](AddressOfOp addrOp) {
2177 if (addrOp.getGlobal(symbolTable))
2178 return WalkResult::interrupt();
2179 return WalkResult::advance();
2182 return emitOpError(
"must reference an alias to a function");
2185 if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2186 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2188 "target function with 'extern_weak' linkage not allowed");
2196 return DSOLocalEquivalentAttr::get(
getContext(), getFunctionNameAttr());
2204 StringRef symName) {
2207 Region *body =
result.addRegion();
2211LogicalResult ComdatOp::verifyRegions() {
2212 Region &body = getBody();
2213 for (Operation &op : body.
getOps())
2214 if (!isa<ComdatSelectorOp>(op))
2215 return op.emitError(
2216 "only comdat selector symbols can appear in a comdat region");
2226 bool isConstant, Linkage linkage, StringRef name,
2227 Attribute value, uint64_t alignment,
unsigned addrSpace,
2228 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2233 result.addAttribute(getGlobalTypeAttrName(
result.name), TypeAttr::get(type));
2238 result.addAttribute(getValueAttrName(
result.name), value);
2243 result.addAttribute(getThreadLocal_AttrName(
result.name),
2246 result.addAttribute(getComdatAttrName(
result.name), comdat);
2256 LinkageAttr::get(builder.
getContext(), linkage));
2260 result.attributes.append(attrs.begin(), attrs.end());
2262 if (!dbgExprs.empty())
2264 ArrayAttr::get(builder.
getContext(), dbgExprs));
2269template <
typename OpType>
2271 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2272 StringRef visibility = stringifyVisibility(op.getVisibility_());
2273 if (!visibility.empty())
2274 p << visibility <<
' ';
2275 if (op.getThreadLocal_())
2276 p <<
"thread_local ";
2277 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2278 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2290 if (
auto value = getValueOrNull())
2293 if (
auto comdat = getComdat())
2294 p <<
" comdat(" << *comdat <<
')';
2300 {SymbolTable::getSymbolAttrName(),
2301 getGlobalTypeAttrName(), getConstantAttrName(),
2302 getValueAttrName(), getLinkageAttrName(),
2303 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2304 getVisibility_AttrName(), getComdatAttrName()});
2307 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2311 Region &initializer = getInitializerRegion();
2312 if (!initializer.
empty()) {
2319 std::optional<SymbolRefAttr> attr) {
2324 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2325 return op->
emitError() <<
"expected comdat symbol";
2335 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2336 if (blockTags.contains(blockTagOp.getTag())) {
2337 blockTagOp.emitError()
2338 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2339 <<
"' in the same function: ";
2342 blockTags.insert(blockTagOp.getTag());
2351template <
typename OpType>
2357 OpType::getLinkageAttrName(
result.name),
2359 parser, LLVM::Linkage::External)));
2362 result.addAttribute(OpType::getVisibility_AttrName(
result.name),
2365 parser, LLVM::Visibility::Default)));
2368 result.addAttribute(OpType::getThreadLocal_AttrName(
result.name),
2372 result.addAttribute(OpType::getUnnamedAddrAttrName(
result.name),
2375 parser, LLVM::UnnamedAddr::None)));
2412 SymbolRefAttr comdat;
2417 result.addAttribute(getComdatAttrName(
result.name), comdat);
2425 if (types.size() > 1)
2429 if (types.empty()) {
2430 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2432 auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2433 strAttr.getValue().size());
2434 types.push_back(arrayType);
2437 "type can only be omitted for string globals");
2447 result.addAttribute(getGlobalTypeAttrName(
result.name),
2448 TypeAttr::get(types[0]));
2453 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2454 return intValue.getValue().isZero();
2455 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2456 return fpValue.getValue().isZero();
2457 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2459 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2461 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2466LogicalResult GlobalOp::verify() {
2468 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2469 LLVMMetadataType, LLVMLabelType>(
getType())
2470 :
llvm::isa<PointerElementTypeInterface>(
getType());
2473 "expects type to be a valid element type for an LLVM global");
2475 return emitOpError(
"must appear at the module level");
2477 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2478 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2479 IntegerType elementType =
2480 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) :
nullptr;
2481 if (!elementType || elementType.getWidth() != 8 ||
2482 type.getNumElements() != strAttr.getValue().size())
2484 "requires an i8 array type of the length equal to that of the string "
2488 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2489 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2491 <<
"this target extension type cannot be used in a global";
2494 return emitOpError() <<
"global with target extension type can only be "
2495 "initialized with zero-initializer";
2498 if (getLinkage() == Linkage::Common) {
2499 if (
Attribute value = getValueOrNull()) {
2502 <<
"expected zero value for '"
2503 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2508 if (getLinkage() == Linkage::Appending) {
2509 if (!llvm::isa<LLVMArrayType>(
getType())) {
2510 return emitOpError() <<
"expected array type for '"
2511 << stringifyLinkage(Linkage::Appending)
2519 std::optional<uint64_t> alignAttr = getAlignment();
2520 if (alignAttr.has_value()) {
2521 uint64_t value = alignAttr.value();
2522 if (!llvm::isPowerOf2_64(value))
2523 return emitError() <<
"alignment attribute is not a power of 2";
2529LogicalResult GlobalOp::verifyRegions() {
2530 if (
Block *
b = getInitializerBlock()) {
2531 ReturnOp ret = cast<ReturnOp>(
b->getTerminator());
2532 if (ret.operand_type_begin() == ret.operand_type_end())
2533 return emitOpError(
"initializer region cannot return void");
2534 if (*ret.operand_type_begin() !=
getType())
2536 << *ret.operand_type_begin() <<
" does not match global type "
2540 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2541 if (!iface || !iface.hasNoEffect())
2542 return op.emitError()
2543 <<
"ops with side effects not allowed in global initializers";
2546 if (getValueOrNull())
2547 return emitOpError(
"cannot have both initializer value and region");
2562 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2565 return op->
emitError(
"data element must be symbol or #llvm.zero");
2578LogicalResult GlobalCtorsOp::verify() {
2582 if (getCtors().size() == getPriorities().size() &&
2583 getCtors().size() == getData().size())
2586 "ctors, priorities, and data must have the same number of elements");
2603LogicalResult GlobalDtorsOp::verify() {
2607 if (getDtors().size() == getPriorities().size() &&
2608 getDtors().size() == getData().size())
2611 "dtors, priorities, and data must have the same number of elements");
2619 Linkage linkage, StringRef name,
bool dsoLocal,
2623 result.addAttribute(getAliasTypeAttrName(
result.name), TypeAttr::get(type));
2628 result.addAttribute(getThreadLocal_AttrName(
result.name),
2632 LinkageAttr::get(builder.
getContext(), linkage));
2633 result.attributes.append(attrs.begin(), attrs.end());
2643 {SymbolTable::getSymbolAttrName(),
2644 getAliasTypeAttrName(), getLinkageAttrName(),
2645 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2646 getVisibility_AttrName()});
2649 p <<
" : " <<
getType() <<
' ';
2675 if (types.size() > 1)
2683 TypeAttr::get(types[0]));
2687LogicalResult AliasOp::verify() {
2689 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2690 LLVMMetadataType, LLVMLabelType>(
getType())
2691 :
llvm::isa<PointerElementTypeInterface>(
getType());
2694 "expects type to be a valid element type for an LLVM global alias");
2697 switch (getLinkage()) {
2698 case Linkage::External:
2699 case Linkage::Internal:
2700 case Linkage::Private:
2702 case Linkage::WeakODR:
2703 case Linkage::Linkonce:
2704 case Linkage::LinkonceODR:
2705 case Linkage::AvailableExternally:
2709 <<
"'" << stringifyLinkage(getLinkage())
2710 <<
"' linkage not supported in aliases, available options: private, "
2711 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2712 "available_externally";
2718LogicalResult AliasOp::verifyRegions() {
2719 Block &
b = getInitializerBlock();
2720 auto ret = cast<ReturnOp>(
b.getTerminator());
2721 if (ret.getNumOperands() == 0 ||
2722 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2723 return emitOpError(
"initializer region must always return a pointer");
2726 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2727 if (!iface || !iface.hasNoEffect())
2728 return op.emitError()
2729 <<
"ops with side effects are not allowed in alias initializers";
2735unsigned AliasOp::getAddrSpace() {
2736 Block &initializer = getInitializerBlock();
2738 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2739 return ptrTy.getAddressSpace();
2747 Type iFuncType, StringRef resolverName,
Type resolverType,
2748 Linkage linkage, LLVM::Visibility visibility) {
2749 return build(builder,
result, name, iFuncType, resolverName, resolverType,
2751 UnnamedAddr::None, visibility);
2758 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2759 auto alias = dyn_cast<AliasOp>(symbol);
2761 Block &initBlock = alias.getInitializerBlock();
2763 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
2770 resolver = addrOp.getFunction(symbolTable);
2771 alias = addrOp.getAlias(symbolTable);
2774 return emitOpError(
"must have a function resolver");
2775 Linkage linkage = resolver.getLinkage();
2776 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
2777 return emitOpError(
"resolver must be a definition");
2778 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
2779 return emitOpError(
"resolver must return a pointer");
2780 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
2781 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
2782 return emitOpError(
"resolver has incorrect type");
2786LogicalResult IFuncOp::verify() {
2787 switch (getLinkage()) {
2788 case Linkage::External:
2789 case Linkage::Internal:
2790 case Linkage::Private:
2792 case Linkage::WeakODR:
2793 case Linkage::Linkonce:
2794 case Linkage::LinkonceODR:
2797 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
2798 <<
"' linkage not supported in ifuncs, available "
2799 "options: private, internal, linkonce, weak, "
2800 "linkonce_odr, weak_odr, or external linkage";
2812 auto containerType = v1.
getType();
2816 build(builder, state, vType, v1, v2, mask);
2830 "expected an LLVM compatible vector type");
2841LogicalResult ShuffleVectorOp::verify() {
2843 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2844 return emitOpError(
"expected a splat operation for scalable vectors");
2850OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
2852 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
2853 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
2857 if (getMask().size() != 1 || getMask()[0] != 0)
2868 assert(empty() &&
"function already has an entry block");
2873 LLVMFunctionType type = getFunctionType();
2874 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2875 entry->
addArgument(type.getParamType(i), getLoc());
2880 StringRef name,
Type type, LLVM::Linkage linkage,
2881 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2884 std::optional<uint64_t> functionEntryCount) {
2888 result.addAttribute(getFunctionTypeAttrName(
result.name),
2889 TypeAttr::get(type));
2891 LinkageAttr::get(builder.
getContext(), linkage));
2893 CConvAttr::get(builder.
getContext(), cconv));
2894 result.attributes.append(attrs.begin(), attrs.end());
2899 result.addAttribute(getComdatAttrName(
result.name), comdat);
2900 if (functionEntryCount)
2901 result.addAttribute(getFunctionEntryCountAttrName(
result.name),
2903 if (argAttrs.empty())
2906 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2907 "expected as many argument attribute lists as arguments");
2909 builder,
result, argAttrs, {},
2910 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
2921 if (outputs.size() > 1) {
2922 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2923 "one function result");
2929 for (
auto t : inputs) {
2931 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2932 "type for function arguments");
2935 llvmInputs.push_back(t);
2940 outputs.empty() ? LLVMVoidType::get(
b.getContext()) : outputs.front();
2942 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2943 "type for function results")
2947 return LLVMFunctionType::get(llvmOutput, llvmInputs,
2963 parser, LLVM::Linkage::External)));
2966 result.addAttribute(getVisibility_AttrName(
result.name),
2969 parser, LLVM::Visibility::Default)));
2972 result.addAttribute(getUnnamedAddrAttrName(
result.name),
2975 parser, LLVM::UnnamedAddr::None)));
2979 getCConvAttrName(
result.name),
2983 StringAttr nameAttr;
2993 parser,
true, entryArgs, isVariadic, resultTypes,
2998 for (
auto &arg : entryArgs)
2999 argTypes.push_back(arg.type);
3005 result.addAttribute(getFunctionTypeAttrName(
result.name),
3006 TypeAttr::get(type));
3014 auto intTy = IntegerType::get(parser.
getContext(), 32);
3016 getVscaleRangeAttrName(
result.name),
3017 LLVM::VScaleRangeAttr::get(parser.
getContext(),
3018 IntegerAttr::get(intTy, minRange),
3019 IntegerAttr::get(intTy, maxRange)));
3023 SymbolRefAttr comdat;
3028 result.addAttribute(getComdatAttrName(
result.name), comdat);
3035 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3037 auto *body =
result.addRegion();
3048 if (getLinkage() != LLVM::Linkage::External)
3049 p << stringifyLinkage(getLinkage()) <<
' ';
3050 StringRef visibility = stringifyVisibility(getVisibility_());
3051 if (!visibility.empty())
3052 p << visibility <<
' ';
3053 if (
auto unnamedAddr = getUnnamedAddr()) {
3054 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3058 if (getCConv() != LLVM::CConv::C)
3059 p << stringifyCConv(getCConv()) <<
' ';
3063 LLVMFunctionType fnType = getFunctionType();
3066 argTypes.reserve(fnType.getNumParams());
3067 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3068 argTypes.push_back(fnType.getParamType(i));
3070 Type returnType = fnType.getReturnType();
3071 if (!llvm::isa<LLVMVoidType>(returnType))
3072 resTypes.push_back(returnType);
3075 isVarArg(), resTypes);
3078 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3079 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3080 << vscale->getMaxRange().getInt() <<
')';
3083 if (
auto comdat = getComdat())
3084 p <<
" comdat(" << *comdat <<
')';
3088 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3089 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3090 getComdatAttrName(), getUnnamedAddrAttrName(),
3091 getVscaleRangeAttrName()});
3094 Region &body = getBody();
3095 if (!body.empty()) {
3106LogicalResult LLVMFuncOp::verify() {
3107 if (getLinkage() == LLVM::Linkage::Common)
3109 << stringifyLinkage(LLVM::Linkage::Common)
3116 if (getLinkage() != LLVM::Linkage::External &&
3117 getLinkage() != LLVM::Linkage::ExternWeak)
3118 return emitOpError() <<
"external functions must have '"
3119 << stringifyLinkage(LLVM::Linkage::External)
3121 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3127 if (isNoInline() && isAlwaysInline())
3128 return emitError(
"no_inline and always_inline attributes are incompatible");
3130 if (isOptimizeNone() && !isNoInline())
3131 return emitOpError(
"with optimize_none must also be no_inline");
3133 Type landingpadResultTy;
3134 StringRef diagnosticMessage;
3135 bool isLandingpadTypeConsistent =
3137 const auto checkType = [&](
Type type, StringRef errorMessage) {
3138 if (!landingpadResultTy) {
3139 landingpadResultTy = type;
3142 if (landingpadResultTy != type) {
3143 diagnosticMessage = errorMessage;
3149 .Case<LandingpadOp>([&](
auto landingpad) {
3150 constexpr StringLiteral errorMessage =
3151 "'llvm.landingpad' should have a consistent result type "
3152 "inside a function";
3153 return checkType(landingpad.getType(), errorMessage);
3155 .Case<ResumeOp>([&](
auto resume) {
3156 constexpr StringLiteral errorMessage =
3157 "'llvm.resume' should have a consistent input type inside a "
3159 return checkType(resume.getValue().getType(), errorMessage);
3162 }).wasInterrupted();
3163 if (!isLandingpadTypeConsistent) {
3164 assert(!diagnosticMessage.empty() &&
3165 "Expecting a non-empty diagnostic message");
3177LogicalResult LLVMFuncOp::verifyRegions() {
3181 unsigned numArguments = getFunctionType().getNumParams();
3182 Block &entryBlock = front();
3183 for (
unsigned i = 0; i < numArguments; ++i) {
3187 << i <<
" is not of LLVM type";
3193Region *LLVMFuncOp::getCallableRegion() {
3221LogicalResult LLVM::ZeroOp::verify() {
3222 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3223 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3225 <<
"target extension type does not support zero-initializer";
3247 if (
auto vecType = dyn_cast<VectorType>(t)) {
3248 assert(!vecType.isScalable() &&
3249 "number of elements of a scalable vector type is unknown");
3250 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3252 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3253 return arrayType.getNumElements() *
3261 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3262 type = arrayType.getElementType();
3263 if (
auto vecType = dyn_cast<VectorType>(type))
3264 return vecType.getElementType();
3265 if (
auto tenType = dyn_cast<TensorType>(type))
3266 return tenType.getElementType();
3273 if (
auto vecType = dyn_cast<VectorType>(t)) {
3274 if (vecType.isScalable())
3278 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3286 LLVM::LLVMArrayType arrayType,
3288 if (arrayType.getNumElements() != arrayAttr.size())
3289 return op.emitOpError()
3290 <<
"array attribute size does not match array type size in "
3292 << dim <<
": " << arrayAttr.size() <<
" vs. "
3293 << arrayType.getNumElements();
3298 if (
auto subArrayType =
3299 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3300 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3301 if (elementsVerified.insert(elementAttr).second) {
3302 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3304 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3306 return op.emitOpError()
3307 <<
"nested attribute for sub-array in dimension " << dim
3308 <<
" at index " << idx
3309 <<
" must be a zero, or undef, or array attribute";
3323 auto structType = dyn_cast<LLVM::LLVMStructType>(arrayType.getElementType());
3325 return op.emitOpError() <<
"for array with an array attribute must have a "
3326 "struct element type";
3330 size_t numStructElements = structType.getBody().size();
3331 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3332 if (elementsVerified.insert(elementAttr).second) {
3333 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3335 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3337 return op.emitOpError()
3338 <<
"nested attribute for struct element at index " << idx
3339 <<
" must be a zero, or undef, or array attribute";
3340 if (subArrayAttr.size() != numStructElements)
3341 return op.emitOpError()
3342 <<
"nested array attribute size for struct element at index "
3343 << idx <<
" must match struct size: " << subArrayAttr.size()
3344 <<
" vs. " << numStructElements;
3351LogicalResult LLVM::ConstantOp::verify() {
3352 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3353 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3354 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3355 !arrayType.getElementType().isInteger(8)) {
3357 << sAttr.getValue().size()
3358 <<
" i8 elements for the string constant";
3362 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3363 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3365 return emitOpError() <<
"expected array attribute for struct type";
3368 if (arrayAttr.size() != elementTypes.size()) {
3369 return emitOpError() <<
"expected array attribute of size "
3370 << elementTypes.size();
3372 for (
auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3374 return emitOpError() <<
"expected struct element types to be floating "
3375 "point type or integer type";
3377 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3378 return emitOpError() <<
"expected element of array attribute to be "
3379 "floating point or integer";
3381 if (cast<TypedAttr>(attr).
getType() != type)
3383 <<
"struct element at index " << i <<
" is of wrong type";
3388 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3389 return emitOpError() <<
"does not support target extension type.";
3400 auto verifyFloatSemantics =
3401 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3402 Type constantElementType) -> LogicalResult {
3403 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3404 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3406 <<
"attribute and type have different float semantics";
3410 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3411 if (isa<IntegerType>(constantElementType)) {
3412 if (!constantElementType.isInteger(floatWidth))
3413 return emitOpError() <<
"expected integer type of width " << floatWidth;
3421 if (isa<IntegerAttr>(getValue())) {
3422 if (!llvm::isa<IntegerType>(
getType()))
3424 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3425 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3426 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3430 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3431 if (!splatElementsAttr)
3433 <<
"scalable vector type requires a splat attribute";
3436 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3437 return emitOpError() <<
"expected vector or array type";
3440 int64_t attrNumElements = elementsAttr.getNumElements();
3443 <<
"type and attribute have a different number of elements: "
3449 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3450 return verifyFloatSemantics(floatType.getFloatSemantics(), resultElmType);
3452 if (isa<IntegerType>(attrElmType) && !isa<IntegerType>(resultElmType)) {
3454 "expected integer element type for integer elements attribute");
3456 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3459 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3462 <<
"expected array or struct type for array attribute";
3469 <<
"only supports integer, float, string or elements attributes";
3475bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3477 auto typedAttr = dyn_cast<TypedAttr>(value);
3484 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3489 if (isBuildableWith(value, type))
3490 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3495OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3503 AtomicOrdering ordering, StringRef syncscope,
3504 unsigned alignment,
bool isVolatile) {
3505 build(builder, state, val.
getType(), binOp,
ptr, val, ordering,
3506 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3509 nullptr,
nullptr,
nullptr);
3512LogicalResult AtomicRMWOp::verify() {
3513 auto valType = getVal().getType();
3514 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3515 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3516 getBinOp() == AtomicBinOp::fminimum ||
3517 getBinOp() == AtomicBinOp::fmaximum) {
3520 return emitOpError(
"expected LLVM IR fixed vector type");
3521 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3524 "expected LLVM IR floating point type for vector element");
3526 return emitOpError(
"expected LLVM IR floating point type");
3528 }
else if (getBinOp() == AtomicBinOp::xchg) {
3531 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3533 auto intType = llvm::dyn_cast<IntegerType>(valType);
3534 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3535 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3537 return emitOpError(
"expected LLVM IR integer type");
3540 if (
static_cast<unsigned>(getOrdering()) <
3541 static_cast<unsigned>(AtomicOrdering::monotonic))
3543 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3555 auto boolType = IntegerType::get(valType.
getContext(), 1);
3556 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3561 AtomicOrdering successOrdering,
3562 AtomicOrdering failureOrdering, StringRef syncscope,
3563 unsigned alignment,
bool isWeak,
bool isVolatile) {
3565 successOrdering, failureOrdering,
3566 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3568 isVolatile,
nullptr,
3569 nullptr,
nullptr,
nullptr);
3572LogicalResult AtomicCmpXchgOp::verify() {
3573 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3575 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3576 auto valType = getVal().getType();
3580 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3581 getFailureOrdering() < AtomicOrdering::monotonic)
3582 return emitOpError(
"ordering must be at least 'monotonic'");
3583 if (getFailureOrdering() == AtomicOrdering::release ||
3584 getFailureOrdering() == AtomicOrdering::acq_rel)
3585 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3594 AtomicOrdering ordering, StringRef syncscope) {
3595 build(builder, state, ordering,
3596 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3599LogicalResult FenceOp::verify() {
3600 if (getOrdering() == AtomicOrdering::not_atomic ||
3601 getOrdering() == AtomicOrdering::unordered ||
3602 getOrdering() == AtomicOrdering::monotonic)
3603 return emitOpError(
"can be given only acquire, release, acq_rel, "
3604 "and seq_cst orderings");
3614template <
class ExtOp>
3616 IntegerType inputType, outputType;
3619 return op.emitError(
3620 "input type is a vector but output type is an integer");
3623 return op.emitError(
"input and output vectors are of incompatible shape");
3626 inputType = cast<IntegerType>(
3627 cast<VectorType>(op.getArg().getType()).getElementType());
3628 outputType = cast<IntegerType>(
3629 cast<VectorType>(op.getResult().getType()).getElementType());
3633 inputType = cast<IntegerType>(op.getArg().getType());
3634 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3636 return op.emitError(
3637 "input type is an integer but output type is a vector");
3640 if (outputType.getWidth() <= inputType.getWidth())
3641 return op.emitError(
"integer width of the output type is smaller or "
3642 "equal to the integer width of the input type");
3653 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3657 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3658 return IntegerAttr::get(
getType(), arg.getValue().zext(targetSize));
3672template <
typename T>
3674 typename T::FoldAdaptor adaptor) {
3676 if (castOp.getArg().getType() == castOp.getType())
3677 return castOp.getArg();
3678 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3680 if (prev.getArg().getType() == castOp.getType())
3681 return prev.getArg();
3683 castOp.getArgMutable().set(prev.getArg());
3684 return Value{castOp};
3689OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3693LogicalResult LLVM::BitcastOp::verify() {
3694 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3696 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3701 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3702 return emitOpError(
"can only cast pointers from and to pointers");
3707 auto isVector = llvm::IsaPred<VectorType>;
3711 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3712 return emitOpError(
"cannot cast pointer to vector of pointers");
3714 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3715 return emitOpError(
"cannot cast vector of pointers to pointer");
3719 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3720 return emitOpError(
"cannot cast pointers of different address spaces, "
3721 "use 'llvm.addrspacecast' instead");
3730OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3734Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3742 adaptor.getDynamicIndices());
3746 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(
indices[0]))
3747 if (integer.getValue().isZero())
3753 for (
auto iter : llvm::enumerate(
indices)) {
3754 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3757 if (!
indices.isDynamicIndex(iter.index()) || !integer ||
3761 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3762 gepArgs.emplace_back(val);
3764 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3770 gepArgs.emplace_back(integer.getInt());
3778 getDynamicIndicesMutable().assign(dynamicIndices);
3779 setRawConstantIndices(rawConstantIndices);
3780 return Value{*
this};
3786Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3793 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3797 if (
rhs.getValue().getZExtValue() >=
3798 getLhs().
getType().getIntOrFloatBitWidth())
3801 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3805 return IntegerAttr::get(
getType(),
lhs.getValue().shl(
rhs.getValue()));
3813 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3817 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3821 return IntegerAttr::get(
getType(),
lhs.getValue() |
rhs.getValue());
3828LogicalResult CallIntrinsicOp::verify() {
3829 if (!getIntrin().starts_with(
"llvm."))
3830 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3838 build(builder, state,
TypeRange{}, intrin, args,
3839 FastmathFlagsAttr{},
3846 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3847 build(builder, state,
TypeRange{}, intrin, args,
3854 mlir::Type resultType, mlir::StringAttr intrin,
3856 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
3864 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3865 build(builder, state, resultTypes, intrin, args, fastMathFlags,
3870ParseResult CallIntrinsicOp::parse(
OpAsmParser &parser,
3872 StringAttr intrinAttr;
3882 result.addAttribute(CallIntrinsicOp::getIntrinAttrName(
result.name),
3890 return mlir::failure();
3893 return mlir::failure();
3898 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
3901 if (opBundleTags && !opBundleTags.empty())
3903 CallIntrinsicOp::getOpBundleTagsAttrName(
result.name).getValue(),
3907 return mlir::failure();
3912 operands, argAttrs, resultAttrs))
3916 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3919 opBundleOperandTypes,
3920 getOpBundleSizesAttrName(
result.name)))
3923 int32_t numOpBundleOperands = 0;
3924 for (
const auto &operands : opBundleOperands)
3925 numOpBundleOperands += operands.size();
3928 CallIntrinsicOp::getOperandSegmentSizeAttr(),
3930 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
3932 return mlir::success();
3940 p <<
"(" << args <<
")";
3943 if (!getOpBundleOperands().empty()) {
3946 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
3950 {getOperandSegmentSizesAttrName(),
3951 getOpBundleSizesAttrName(), getIntrinAttrName(),
3952 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
3953 getResAttrsAttrName()});
3959 p, args.
getTypes(), getArgAttrsAttr(),
3960 false, getResultTypes(), getResAttrsAttr());
3967LogicalResult LinkerOptionsOp::verify() {
3970 return emitOpError(
"must appear at the module level");
3978LogicalResult ModuleFlagsOp::verify() {
3981 return emitOpError(
"must appear at the module level");
3983 if (!isa<ModuleFlagAttr>(flag))
3984 return emitOpError(
"expected a module flag attribute");
3992void InlineAsmOp::getEffects(
3995 if (getHasSideEffects()) {
4008 getBlockAddr().getFunction());
4009 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
4012 return emitOpError(
"must reference a function defined by 'llvm.func'");
4022BlockTagOp BlockAddressOp::getBlockTagOp() {
4028 BlockTagOp blockTagOp =
nullptr;
4029 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4030 if (labelOp.getTag() == getBlockAddr().getTag()) {
4031 blockTagOp = labelOp;
4039LogicalResult BlockAddressOp::verify() {
4040 if (!getBlockTagOp())
4042 "expects an existing block label target in the referenced function");
4049OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4056 assert(
index < getNumSuccessors() &&
"invalid successor index");
4068 rangeSegments.push_back(range.size());
4082 Block *destination = nullptr;
4083 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4084 SmallVector<Type> operandTypes;
4086 if (parser.parseSuccessor(destination).failed())
4089 if (succeeded(parser.parseOptionalLParen())) {
4090 if (failed(parser.parseOperandList(
4091 operands, OpAsmParser::Delimiter::None)) ||
4092 failed(parser.parseColonTypeList(operandTypes)) ||
4093 failed(parser.parseRParen()))
4096 succOperandBlocks.push_back(destination);
4097 succOperands.emplace_back(operands);
4098 succOperandsTypes.emplace_back(operandTypes);
4101 "successor blocks")))
4112 llvm::zip(succs, succOperands),
4118 if (!succOperands.empty())
4127LogicalResult LLVM::SincosOp::verify() {
4128 auto operandType = getOperand().getType();
4129 auto resultType = getResult().getType();
4130 auto resultStructType =
4131 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4132 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4133 resultStructType.getBody()[0] != operandType ||
4134 resultStructType.getBody()[1] != operandType) {
4135 return emitOpError(
"expected result type to be an homogeneous struct with "
4136 "two elements matching the operand type, but got ")
4148 return build(builder, state, cond, {},
4160 return build(builder, state, cond,
"align",
ValueRange{
ptr, align});
4166 return build(builder, state, cond,
"separate_storage",
4176LogicalResult LLVM::masked_gather::verify() {
4177 auto ptrsVectorType = getPtrs().getType();
4178 Type expectedPtrsVectorType =
4183 if (ptrsVectorType != expectedPtrsVectorType)
4184 return emitOpError(
"expected operand #1 type to be ")
4185 << expectedPtrsVectorType;
4193LogicalResult LLVM::masked_scatter::verify() {
4194 auto ptrsVectorType = getPtrs().getType();
4195 Type expectedPtrsVectorType =
4200 if (ptrsVectorType != expectedPtrsVectorType)
4201 return emitOpError(
"expected operand #2 type to be ")
4202 << expectedPtrsVectorType;
4215 build(builder, state, resTys,
ptr, mask, passthru, argAttrs,
4223void LLVM::masked_compressstore::build(
OpBuilder &builder,
4228 build(builder, state, value,
ptr, mask, argAttrs,
4236LogicalResult InlineAsmOp::verify() {
4237 if (!getTailCallKindAttr())
4240 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4242 "tail call kind 'musttail' is not supported by this operation");
4252 Value divisor = getRhs();
4267 Value divisor = getRhs();
4279void LLVMDialect::initialize() {
4280 registerAttributes();
4283 addTypes<LLVMVoidType,
4286 LLVMMetadataType>();
4292#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4296#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4301 allowUnknownOperations();
4302 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4306#define GET_OP_CLASSES
4307#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4309#define GET_OP_CLASSES
4310#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4312LogicalResult LLVMDialect::verifyDataLayoutString(
4315 llvm::DataLayout::parse(descr);
4316 if (maybeDataLayout)
4319 std::string message;
4320 llvm::raw_string_ostream messageStream(message);
4321 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4322 reportError(
"invalid data layout descriptor: " + message);
4327LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4333 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4335 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4336 return verifyDataLayoutString(
4337 stringAttr.getValue(),
4338 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4341 << LLVM::LLVMDialect::getDataLayoutAttrName()
4342 <<
"' to be a string attributes";
4345LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4353 StringAttr name = paramAttr.
getName();
4355 auto checkUnitAttrType = [&]() -> LogicalResult {
4356 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4357 return op->
emitError() << name <<
" should be a unit attribute";
4360 auto checkTypeAttrType = [&]() -> LogicalResult {
4361 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4362 return op->
emitError() << name <<
" should be a type attribute";
4365 auto checkIntegerAttrType = [&]() -> LogicalResult {
4366 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4367 return op->
emitError() << name <<
" should be an integer attribute";
4370 auto checkPointerType = [&]() -> LogicalResult {
4371 if (!llvm::isa<LLVMPointerType>(paramType))
4373 << name <<
" attribute attached to non-pointer LLVM type";
4376 auto checkIntegerType = [&]() -> LogicalResult {
4377 if (!llvm::isa<IntegerType>(paramType))
4379 << name <<
" attribute attached to non-integer LLVM type";
4382 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4383 if (
failed(checkPointerType()))
4390 if (name == LLVMDialect::getNoAliasAttrName() ||
4391 name == LLVMDialect::getReadonlyAttrName() ||
4392 name == LLVMDialect::getReadnoneAttrName() ||
4393 name == LLVMDialect::getWriteOnlyAttrName() ||
4394 name == LLVMDialect::getNestAttrName() ||
4395 name == LLVMDialect::getNoCaptureAttrName() ||
4396 name == LLVMDialect::getNoFreeAttrName() ||
4397 name == LLVMDialect::getNonNullAttrName()) {
4398 if (
failed(checkUnitAttrType()))
4400 if (verifyValueType &&
failed(checkPointerType()))
4406 if (name == LLVMDialect::getStructRetAttrName() ||
4407 name == LLVMDialect::getByValAttrName() ||
4408 name == LLVMDialect::getByRefAttrName() ||
4409 name == LLVMDialect::getElementTypeAttrName() ||
4410 name == LLVMDialect::getInAllocaAttrName() ||
4411 name == LLVMDialect::getPreallocatedAttrName()) {
4412 if (
failed(checkTypeAttrType()))
4414 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4420 if (name == LLVMDialect::getSExtAttrName() ||
4421 name == LLVMDialect::getZExtAttrName()) {
4422 if (
failed(checkUnitAttrType()))
4424 if (verifyValueType &&
failed(checkIntegerType()))
4430 if (name == LLVMDialect::getAlignAttrName() ||
4431 name == LLVMDialect::getDereferenceableAttrName() ||
4432 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4433 if (
failed(checkIntegerAttrType()))
4435 if (verifyValueType &&
failed(checkPointerType()))
4441 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4442 if (
failed(checkIntegerAttrType()))
4448 if (name == LLVMDialect::getNoUndefAttrName() ||
4449 name == LLVMDialect::getInRegAttrName() ||
4450 name == LLVMDialect::getReturnedAttrName())
4451 return checkUnitAttrType();
4457LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4461 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4464 Type argType = funcOp.getArgumentTypes()[argIdx];
4466 return verifyParameterAttribute(op, argType, argAttr);
4469LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4473 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4476 Type resType = funcOp.getResultTypes()[resIdx];
4480 if (llvm::isa<LLVMVoidType>(resType))
4481 return op->
emitError() <<
"cannot attach result attributes to functions "
4482 "with a void return";
4486 auto name = resAttr.
getName();
4487 if (name == LLVMDialect::getAllocAlignAttrName() ||
4488 name == LLVMDialect::getAllocatedPointerAttrName() ||
4489 name == LLVMDialect::getByValAttrName() ||
4490 name == LLVMDialect::getByRefAttrName() ||
4491 name == LLVMDialect::getInAllocaAttrName() ||
4492 name == LLVMDialect::getNestAttrName() ||
4493 name == LLVMDialect::getNoCaptureAttrName() ||
4494 name == LLVMDialect::getNoFreeAttrName() ||
4495 name == LLVMDialect::getPreallocatedAttrName() ||
4496 name == LLVMDialect::getReadnoneAttrName() ||
4497 name == LLVMDialect::getReadonlyAttrName() ||
4498 name == LLVMDialect::getReturnedAttrName() ||
4499 name == LLVMDialect::getStackAlignmentAttrName() ||
4500 name == LLVMDialect::getStructRetAttrName() ||
4501 name == LLVMDialect::getWriteOnlyAttrName())
4502 return op->
emitError() << name <<
" is not a valid result attribute";
4503 return verifyParameterAttribute(op, resType, resAttr);
4511 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4512 if (isa<LLVM::LLVMPointerType>(type))
4513 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4514 if (isa<LLVM::UndefAttr>(value))
4515 return LLVM::UndefOp::create(builder, loc, type);
4516 if (isa<LLVM::PoisonAttr>(value))
4517 return LLVM::PoisonOp::create(builder, loc, type);
4518 if (isa<LLVM::ZeroAttr>(value))
4519 return LLVM::ZeroOp::create(builder, loc, type);
4521 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4529 StringRef name, StringRef value,
4530 LLVM::Linkage linkage) {
4533 "expected builder to point to a block constrained in an op");
4535 builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4536 assert(module &&
"builder points to an op outside of a module");
4541 auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4542 auto global = LLVM::GlobalOp::create(
4543 moduleBuilder, loc, type,
true, linkage, name,
4546 LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4549 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4550 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4562 module = module->getParentOp();
4563 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)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
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)
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 printNewline()=0
Print a newline and indent the printer to the start of the current operation.
virtual void printSuccessorAndUseList(Block *successor, ValueRange succOperands)=0
Print the successor and its operands.
void printOperands(const ContainerType &container)
Print a comma separated list of operands.
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
This class represents a single result from folding an operation.
This class provides the API for ops that are known to be isolated from above.
A trait used to provide symbol table functionalities to a region operation.
This class represents a contiguous range of operand ranges, e.g.
This class implements the operand iterators for the Operation class.
type_range getTypes() const
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
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()
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.
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...
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.
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.