29#include "llvm/ADT/APFloat.h"
30#include "llvm/ADT/DenseSet.h"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/ADT/TypeSwitch.h"
33#include "llvm/IR/DataLayout.h"
34#include "llvm/Support/Error.h"
43using mlir::LLVM::cconv::getMaxEnumValForCConv;
44using mlir::LLVM::linkage::getMaxEnumValForLinkage;
45using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
47#include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
58 op, [&](StringRef name,
Attribute &attr) { attrs.
set(name, attr); });
65 if (attr.
getName() ==
"fastmathFlags") {
85 << name <<
"' does not reference a valid LLVM function";
86 if (
func.isExternal())
87 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
105 for (
const auto &en : llvm::enumerate(keywords)) {
113template <
typename Ty>
116#define REGISTER_ENUM_TYPE(Ty) \
118 struct EnumTraits<Ty> { \
119 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
120 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
134template <
typename EnumTy,
typename RetTy = EnumTy>
136 EnumTy defaultValue) {
138 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
139 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
143 return static_cast<RetTy
>(defaultValue);
144 return static_cast<RetTy
>(
index);
149 p << stringifyLinkage(val.getLinkage());
153 val = LinkageAttr::get(
161 uint64_t alignment = 1) {
167 if (alignment == 1) {
174 builder.
getNamedAttr(LLVMDialect::getAlignAttrName(), alignmentAttr);
184 int pos = isExpandLoad ? 0 : 1;
186 {alignDictAttr, emptyDictAttr, emptyDictAttr})
188 {emptyDictAttr, alignDictAttr, emptyDictAttr});
200 if (!operands.empty()) {
203 llvm::interleaveComma(operandTypes, p);
212 std::optional<ArrayAttr> opBundleTags) {
213 if (opBundleOperands.empty())
215 assert(opBundleTags &&
"expect operand bundle tags");
218 llvm::interleaveComma(
219 llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
221 auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
239 return p.
emitError(currentParserLoc,
"expect operand bundle tag");
250 opBundleOperands.push_back(std::move(operands));
251 opBundleOperandTypes.push_back(std::move(types));
252 opBundleTags.push_back(StringAttr::get(p.
getContext(), tag));
269 auto bundleParser = [&] {
279 opBundleTags = ArrayAttr::get(p.
getContext(), opBundleTagAttrs);
288template <
typename PredicateAttr,
typename Predicate>
291 function_ref<std::optional<Predicate>(StringRef)> symbolize) {
292 std::string spelling;
296 std::optional<Predicate> value = symbolize(spelling);
300 <<
"' is an incorrect value of the 'predicate' attribute";
301 predicate = PredicateAttr::get(parser.
getContext(), *value);
306 ICmpPredicateAttr &predicate) {
309 [](StringRef spelling) {
return symbolizeICmpPredicate(spelling); });
313 FCmpPredicateAttr &predicate) {
316 [](StringRef spelling) {
return symbolizeFCmpPredicate(spelling); });
320 ICmpPredicateAttr predicate) {
321 printer <<
'"' << stringifyICmpPredicate(predicate.getValue()) <<
'"';
325 FCmpPredicateAttr predicate) {
326 printer <<
'"' << stringifyFCmpPredicate(predicate.getValue()) <<
'"';
332 ShapedType shapedType = dyn_cast<ShapedType>(type);
339 if (getPredicate() != ICmpPredicate::eq &&
340 getPredicate() != ICmpPredicate::ne)
344 if (getLhs() == getRhs())
346 getPredicate() == ICmpPredicate::eq);
349 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
351 getPredicate() == ICmpPredicate::ne);
354 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
355 Value lhs = getLhs();
356 Value rhs = getRhs();
357 getLhsMutable().assign(rhs);
358 getRhsMutable().assign(lhs);
376 p <<
' ' << getArraySize() <<
" x " << getElemType();
377 NamedAttrList attrs((*this)->getDiscardableAttrDictionary().getValue());
378 if (getAlignment() && *getAlignment() != 0)
379 attrs.append(getAlignmentAttrName(), getAlignmentAttr());
381 p <<
" : " << funcTy;
389 SMLoc trailingTypeLoc;
401 std::optional<NamedAttribute> alignmentAttr =
402 result.attributes.getNamed(
"alignment");
403 if (alignmentAttr.has_value()) {
404 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
407 "expected integer alignment");
408 if (alignmentInt.getValue().isZero())
409 result.attributes.erase(
"alignment");
413 auto funcType = llvm::dyn_cast<FunctionType>(type);
414 if (!funcType || funcType.getNumInputs() != 1 ||
415 funcType.getNumResults() != 1)
418 "expected trailing function type with one argument and one result");
423 Type resultType = funcType.getResult(0);
424 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
427 result.addTypes({funcType.getResult(0)});
431LogicalResult AllocaOp::verify() {
433 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
434 targetExtType && !targetExtType.supportsMemOps())
436 <<
"this target extension type cannot be used in alloca";
441LogicalResult AllocaOp::canonicalize(AllocaOp op,
PatternRewriter &rewriter) {
445 numElements.isOne() || numElements.getActiveBits() > 64)
449 LLVMArrayType::get(op.getElemType(), numElements.getZExtValue());
450 Value one = ConstantOp::create(rewriter, op.getLoc(), rewriter.
getI32Type(),
453 AllocaOp::create(rewriter, op.getLoc(), op.getType(), one,
454 op.getAlignmentAttr(), arrayType, op.getInalloca());
455 newAlloca->setDiscardableAttrs(op->getDiscardableAttrDictionary());
465 assert(
index == 0 &&
"invalid successor index");
474 assert(
index < getNumSuccessors() &&
"invalid successor index");
476 : getFalseDestOperandsMutable());
482 std::optional<std::pair<uint32_t, uint32_t>> weights) {
487 static_cast<int32_t
>(weights->second)});
489 build(builder,
result, condition, trueOperands, falseOperands, weightsAttr,
490 {}, trueDest, falseDest);
504 if (!branchWeights.empty())
507 build(builder,
result, value, defaultOperands, caseOperands, caseValues,
508 weightsAttr, defaultDestination, caseDestinations);
517 if (!caseValues.empty()) {
518 ShapedType caseValueType = VectorType::get(
523 build(builder,
result, value, defaultDestination, defaultOperands,
524 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
533 if (!caseValues.empty()) {
534 ShapedType caseValueType = VectorType::get(
539 build(builder,
result, value, defaultDestination, defaultOperands,
540 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
556 auto parseCase = [&]() {
560 values.push_back(APInt(bitWidth, value,
true));
573 caseDestinations.push_back(destination);
574 caseOperands.emplace_back(operands);
575 caseOperandTypes.emplace_back(operandTypes);
581 ShapedType caseValueType =
582 VectorType::get(
static_cast<int64_t>(values.size()), flagType);
601 llvm::zip(caseValues, caseDestinations),
616LogicalResult SwitchOp::verify() {
617 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
619 getCaseValues()->size() !=
620 static_cast<int64_t>(getCaseDestinations().size())))
621 return emitOpError(
"expects number of case values to match number of "
622 "case destinations");
623 if (getCaseValues() &&
625 return emitError(
"expects case value type to match condition value type");
630 assert(
index < getNumSuccessors() &&
"invalid successor index");
632 : getCaseOperandsMutable(
index - 1));
641 getDynamicIndices());
646 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
647 return vectorType.getElementType();
664 bool requiresConst = !rawConstantIndices.empty() &&
665 isa_and_nonnull<LLVMStructType>(currType);
666 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
670 rawConstantIndices.push_back(intC.getSExtValue());
672 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
673 dynamicIndices.push_back(val);
676 rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
681 if (rawConstantIndices.size() == 1 || !currType)
685 .Case<VectorType, LLVMArrayType>([](
auto containerType) {
686 return containerType.getElementType();
688 .Case([&](LLVMStructType structType) ->
Type {
689 int64_t memberIndex = rawConstantIndices.back();
690 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
691 structType.getBody().size())
692 return structType.getBody()[memberIndex];
701 GEPNoWrapFlags noWrapFlags,
707 result.addTypes(resultType);
708 result.addAttributes(attributes);
709 result.getOrAddProperties<Properties>().rawConstantIndices =
711 result.getOrAddProperties<Properties>().noWrapFlags = noWrapFlags;
712 result.getOrAddProperties<Properties>().elem_type =
713 TypeAttr::get(elementType);
714 result.addOperands(basePtr);
715 result.addOperands(dynamicIndices);
720 GEPNoWrapFlags noWrapFlags,
722 build(builder,
result, resultType, elementType, basePtr,
732 auto idxParser = [&]() -> ParseResult {
733 int32_t constantIndex;
737 if (failed(parsedInteger.
value()))
739 constantIndices.push_back(constantIndex);
743 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
757 llvm::interleaveComma(
760 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
763 printer << cast<IntegerAttr>(cst).getInt();
773 if (indexPos >=
indices.size())
778 .Case([&](LLVMStructType structType) -> LogicalResult {
779 auto attr = dyn_cast<IntegerAttr>(
indices[indexPos]);
781 return emitOpError() <<
"expected index " << indexPos
782 <<
" indexing a struct to be constant";
784 int32_t gepIndex = attr.getInt();
787 static_cast<size_t>(gepIndex) >= elementTypes.size())
788 return emitOpError() <<
"index " << indexPos
789 <<
" indexing a struct is out of bounds";
796 .Case<VectorType, LLVMArrayType>(
797 [&](
auto containerType) -> LogicalResult {
799 indexPos + 1,
indices, emitOpError);
801 .Default([&](
auto otherType) -> LogicalResult {
803 <<
"type " << otherType <<
" cannot be indexed (index #"
815LogicalResult LLVM::GEPOp::verify() {
816 if (
static_cast<size_t>(
817 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
818 getDynamicIndices().size())
819 return emitOpError(
"expected as many dynamic indices as specified in '")
820 << getRawConstantIndicesAttrName().getValue() <<
"'";
822 if (getNoWrapFlags() == GEPNoWrapFlags::inboundsFlag)
823 return emitOpError(
"'inbounds_flag' cannot be used directly.");
826 [&] {
return emitOpError(); });
833void LoadOp::getEffects(
842 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
843 getOrdering() != AtomicOrdering::unordered)) {
854 if (!isa<IntegerType, LLVMPointerType>(type))
859 if (bitWidth.isScalable())
862 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
866template <
typename OpTy>
870 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
873 return memOp.emitOpError(
"unsupported type ")
874 << valueType <<
" for atomic access";
875 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
876 return memOp.emitOpError(
"unsupported ordering '")
877 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
878 if (!memOp.getAlignment())
879 return memOp.emitOpError(
"expected alignment for atomic access");
882 if (memOp.getSyncscope())
883 return memOp.emitOpError(
884 "expected syncscope to be null for non-atomic access");
888LogicalResult LoadOp::verify() {
889 Type valueType = getResult().getType();
891 {AtomicOrdering::release, AtomicOrdering::acq_rel});
895 Value addr,
unsigned alignment,
bool isVolatile,
896 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
897 AtomicOrdering ordering, StringRef syncscope) {
898 build(builder, state, type, addr,
900 isNonTemporal, isInvariant, isInvariantGroup, ordering,
901 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
912void StoreOp::getEffects(
921 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
922 getOrdering() != AtomicOrdering::unordered)) {
928LogicalResult StoreOp::verify() {
929 Type valueType = getValue().getType();
931 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
935 Value addr,
unsigned alignment,
bool isVolatile,
936 bool isNonTemporal,
bool isInvariantGroup,
937 AtomicOrdering ordering, StringRef syncscope) {
938 build(builder, state, value, addr,
940 isNonTemporal, isInvariantGroup, ordering,
941 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
943 nullptr,
nullptr,
nullptr);
953 Type resultType = calleeType.getReturnType();
954 if (!isa<LLVM::LLVMVoidType>(resultType))
955 results.push_back(resultType);
961 return calleeType.isVarArg() ? TypeAttr::get(calleeType) :
nullptr;
969 resultType = LLVMVoidType::get(context);
971 resultType = results.front();
972 return LLVMFunctionType::get(resultType, llvm::to_vector(args.
getTypes()),
978 build(builder, state, results, builder.
getStringAttr(callee), args);
983 build(builder, state, results, SymbolRefAttr::get(callee), args);
988 assert(callee &&
"expected non-null callee in direct call builder");
989 build(builder, state, results,
990 nullptr, callee, args,
nullptr,
993 nullptr,
nullptr,
nullptr,
994 nullptr,
nullptr,
nullptr,
998 nullptr,
nullptr,
nullptr,
1013 LLVMFunctionType calleeType, StringRef callee,
1015 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1019 LLVMFunctionType calleeType, StringAttr callee,
1021 build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
1039 nullptr,
nullptr,
nullptr,
1048 nullptr,
nullptr,
nullptr,
1054 LLVMFunctionType calleeType,
ValueRange args) {
1059 nullptr,
nullptr,
nullptr,
1060 nullptr,
nullptr,
nullptr,
1066 nullptr,
nullptr,
nullptr,
1082 auto calleeType =
func.getFunctionType();
1086 nullptr,
nullptr,
nullptr,
1087 nullptr,
nullptr,
nullptr,
1093 nullptr,
nullptr,
nullptr,
1112 return getOperand(0);
1118 auto symRef = cast<SymbolRefAttr>(callee);
1119 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1122 return setOperand(0, cast<Value>(callee));
1127template <
typename OpTy>
1130 if (callOp.getCallee().has_value())
1137template <
typename OpTy>
1139 return callOp.getCalleeOperands().drop_front(
1151template <
typename OpTy>
1154 if (std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType())
1155 return operands.take_front(varCalleeType->getNumParams());
1172 if (callee.isExternal())
1174 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1178 auto hasSubprogram = [](
Operation *op) {
1183 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1185 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1187 return callOp.emitError()
1188 <<
"inlinable function call in a function with a DISubprogram "
1189 "location must have a debug location";
1195template <
typename OpTy>
1198 if (!callOp.getCallee().has_value() && callOp.getCalleeOperands().empty())
1199 return callOp.emitOpError(
1200 "must have either a `callee` attribute or at least an operand");
1202 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1207 if (!varCalleeType->isVarArg())
1208 return callOp.emitOpError(
1209 "expected var_callee_type to be a variadic function type");
1217 if (varCalleeType->getNumParams() > passedOperands.size())
1218 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1219 << passedOperands.size() <<
" parameters";
1222 for (
auto [paramType, operand] :
1223 llvm::zip(varCalleeType->getParams(), passedOperands))
1224 if (paramType != operand.getType())
1225 return callOp.emitOpError()
1226 <<
"var_callee_type parameter type mismatch: " << paramType
1227 <<
" != " << operand.getType();
1230 if (!callOp.getNumResults()) {
1231 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1232 return callOp.emitOpError(
"expected var_callee_type to return void");
1234 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1235 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1236 << varCalleeType->getReturnType()
1237 <<
" != " << callOp.getResult().getType();
1242template <
typename OpType>
1245 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1247 auto isStringAttr = [](
Attribute tagAttr) {
1248 return isa<StringAttr>(tagAttr);
1250 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1251 return op.emitError(
"operand bundle tag must be a StringAttr");
1253 size_t numOpBundles = opBundleOperands.size();
1254 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1255 if (numOpBundles != numOpBundleTags)
1256 return op.emitError(
"expected ")
1257 << numOpBundles <<
" operand bundle tags, but actually got "
1278 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1280 return emitOpError(
"indirect call expects a pointer as callee: ")
1281 << getOperand(0).getType();
1289 return emitOpError()
1291 <<
"' does not reference a symbol in the current scope";
1292 if (
auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1295 fnType = fn.getFunctionType();
1296 }
else if (
auto ifunc = dyn_cast<IFuncOp>(callee)) {
1297 fnType = ifunc.getIFuncType();
1298 }
else if (isa<AliasOp>(callee)) {
1302 fnType = getCalleeFunctionType();
1304 return emitOpError()
1306 <<
"' does not reference a valid LLVM function, IFunc, or alias";
1310 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1312 return emitOpError(
"callee does not have a functional type: ") << fnType;
1314 if (funcType.isVarArg() && !getVarCalleeType())
1315 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1319 if (getNumResults() == 0 &&
1320 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1321 return emitOpError() <<
"expected function call to produce a value";
1323 if (getNumResults() != 0 &&
1324 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1325 return emitOpError()
1326 <<
"calling function with void result must not produce values";
1328 if (getNumResults() > 1)
1329 return emitOpError()
1330 <<
"expected LLVM function call to produce 0 or 1 result";
1332 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1333 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1334 <<
" != " << funcType.getReturnType();
1340 if (!llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1341 calleeResultTypes.push_back(funcType.getReturnType());
1347 auto callee = getCallee();
1348 bool isDirect = callee.has_value();
1353 if (getCConv() != LLVM::CConv::C)
1354 p << stringifyCConv(getCConv()) <<
' ';
1356 if (getTailCallKind() != LLVM::TailCallKind::None)
1357 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1366 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1367 p <<
'(' << args <<
')';
1370 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1371 p <<
" vararg(" << *varCalleeType <<
")";
1373 if (!getOpBundleOperands().empty()) {
1376 getOpBundleOperands().getTypes(), getOpBundleTags());
1380 {getCalleeAttrName(), getTailCallKindAttrName(),
1381 getVarCalleeTypeAttrName(), getCConvAttrName(),
1382 getOperandSegmentSizesAttrName(),
1383 getOpBundleSizesAttrName(),
1384 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1385 getResAttrsAttrName()});
1389 p << getOperand(0).getType() <<
", ";
1393 p, args.getTypes(), getArgAttrsAttr(),
1394 false, getResultTypes(), getResAttrsAttr());
1409 types.emplace_back();
1414 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1419 resTypes, resultAttrs)) {
1421 return parser.
emitError(trailingTypesLoc,
1422 "expected direct call to have 1 trailing types");
1423 return parser.
emitError(trailingTypesLoc,
1424 "expected trailing function type");
1427 if (resTypes.size() > 1)
1428 return parser.
emitError(trailingTypesLoc,
1429 "expected function with 0 or 1 result");
1430 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1431 return parser.
emitError(trailingTypesLoc,
1432 "expected a non-void result type");
1438 llvm::append_range(types, argTypes);
1442 if (!resTypes.empty())
1443 result.addTypes(resTypes);
1456 if (failed(*parseResult))
1457 return *parseResult;
1458 operands.push_back(funcPtrOperand);
1467 StringAttr opBundleSizesAttrName) {
1468 unsigned opBundleIndex = 0;
1469 for (
const auto &[operands, types] :
1470 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1471 if (operands.size() != types.size())
1472 return parser.
emitError(loc,
"expected ")
1474 <<
" types for operand bundle operands for operand bundle #"
1475 << opBundleIndex <<
", but actually got " << types.size();
1481 opBundleSizes.reserve(opBundleOperands.size());
1482 for (
const auto &operands : opBundleOperands)
1483 opBundleSizes.push_back(operands.size());
1486 opBundleSizesAttrName,
1498 SymbolRefAttr funcAttr;
1499 TypeAttr varCalleeType;
1507 getCConvAttrName(
result.name),
1512 getTailCallKindAttrName(
result.name),
1515 parser, LLVM::TailCallKind::None)));
1520 bool isDirect = operands.empty();
1533 StringAttr varCalleeTypeAttrName =
1534 CallOp::getVarCalleeTypeAttrName(
result.name);
1546 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1549 if (opBundleTags && !opBundleTags.empty())
1550 result.addAttribute(CallOp::getOpBundleTagsAttrName(
result.name).getValue(),
1560 argAttrs, resultAttrs))
1564 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1566 opBundleOperandTypes,
1567 getOpBundleSizesAttrName(
result.name)))
1570 int32_t numOpBundleOperands = 0;
1571 for (
const auto &operands : opBundleOperands)
1572 numOpBundleOperands += operands.size();
1575 CallOp::getOperandSegmentSizeAttr(),
1577 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1581LLVMFunctionType CallOp::getCalleeFunctionType() {
1582 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1583 return *varCalleeType;
1594 auto calleeType =
func.getFunctionType();
1597 nullptr,
nullptr, normalOps, unwindOps,
1598 nullptr,
nullptr,
nullptr,
1599 nullptr, {}, {}, normal, unwind);
1606 build(builder, state, tys,
1607 nullptr, callee, ops,
nullptr,
1608 nullptr, normalOps, unwindOps,
nullptr,
nullptr,
1610 nullptr, {}, {}, normal, unwind);
1619 nullptr,
nullptr, normalOps, unwindOps,
1620 nullptr,
nullptr,
nullptr,
1621 nullptr, {}, {}, normal, unwind);
1625 assert(
index < getNumSuccessors() &&
"invalid successor index");
1627 : getUnwindDestOperandsMutable());
1635 return getOperand(0);
1641 auto symRef = cast<SymbolRefAttr>(callee);
1642 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1645 return setOperand(0, cast<Value>(callee));
1657LogicalResult InvokeOp::verify() {
1661 Block *unwindDest = getUnwindDest();
1662 if (unwindDest->
empty())
1663 return emitError(
"must have at least one operation in unwind destination");
1666 if (!isa<LandingpadOp>(unwindDest->
front()))
1667 return emitError(
"first operation in unwind destination should be a "
1668 "llvm.landingpad operation");
1677 auto callee = getCallee();
1678 bool isDirect = callee.has_value();
1683 if (getCConv() != LLVM::CConv::C)
1684 p << stringifyCConv(getCConv()) <<
' ';
1692 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1699 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1700 p <<
" vararg(" << *varCalleeType <<
")";
1702 if (!getOpBundleOperands().empty()) {
1705 getOpBundleOperands().getTypes(), getOpBundleTags());
1709 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1710 getCConvAttrName(), getVarCalleeTypeAttrName(),
1711 getOpBundleSizesAttrName(),
1712 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1713 getResAttrsAttrName()});
1717 p << getOperand(0).getType() <<
", ";
1719 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1721 false, getResultTypes(), getResAttrsAttr());
1734 SymbolRefAttr funcAttr;
1735 TypeAttr varCalleeType;
1739 Block *normalDest, *unwindDest;
1745 getCConvAttrName(
result.name),
1752 bool isDirect = operands.empty();
1768 StringAttr varCalleeTypeAttrName =
1769 InvokeOp::getVarCalleeTypeAttrName(
result.name);
1781 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1784 if (opBundleTags && !opBundleTags.empty())
1786 InvokeOp::getOpBundleTagsAttrName(
result.name).getValue(),
1796 argAttrs, resultAttrs))
1800 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1803 opBundleOperandTypes,
1804 getOpBundleSizesAttrName(
result.name)))
1807 result.addSuccessors({normalDest, unwindDest});
1808 result.addOperands(normalOperands);
1809 result.addOperands(unwindOperands);
1811 int32_t numOpBundleOperands = 0;
1812 for (
const auto &operands : opBundleOperands)
1813 numOpBundleOperands += operands.size();
1816 InvokeOp::getOperandSegmentSizeAttr(),
1818 static_cast<int32_t>(normalOperands.size()),
1819 static_cast<int32_t>(unwindOperands.size()),
1820 numOpBundleOperands}));
1824LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1825 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1826 return *varCalleeType;
1834LogicalResult LandingpadOp::verify() {
1836 if (LLVMFuncOp
func = (*this)->getParentOfType<LLVMFuncOp>()) {
1837 if (!
func.getPersonality())
1839 "llvm.landingpad needs to be in a function with a personality");
1845 if (!getCleanup() && getOperands().empty())
1846 return emitError(
"landingpad instruction expects at least one clause or "
1847 "cleanup attribute");
1850 value = getOperand(idx);
1851 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1858 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1861 <<
"global addresses expected as operand to "
1862 "bitcast used in clauses for landingpad";
1870 << idx <<
" is not a known constant - null, addressof, bitcast";
1877 p << (getCleanup() ?
" cleanup " :
" ");
1880 for (
auto value : getOperands()) {
1883 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1884 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1931 Type llvmType = containerType;
1933 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1941 for (
int64_t idx : position) {
1942 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1943 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1944 emitError(
"position out of bounds: ") << idx;
1947 llvmType = arrayType.getElementType();
1948 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1950 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1951 emitError(
"position out of bounds: ") << idx;
1954 llvmType = structType.getBody()[idx];
1956 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1967 for (
int64_t idx : position) {
1968 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1969 llvmType = structType.getBody()[idx];
1971 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1983 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
1984 ShapedType shapedType = elementsAttr.getShapedType();
1985 if (!shapedType.hasRank() || shapedType.getRank() != 1)
1987 if (
index <
static_cast<size_t>(elementsAttr.getNumElements()))
1991 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
1992 if (
index < arrayAttr.getValue().size())
1993 return arrayAttr[
index];
1996 if (isa<ZeroAttr, UndefAttr, PoisonAttr>(attr))
2001OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
2002 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
2004 newPos.append(getPosition().begin(), getPosition().end());
2005 setPosition(newPos);
2006 getContainerMutable().set(extractValueOp.getContainer());
2012 for (
int64_t pos : getPosition()) {
2017 return containerAttr;
2020 Value container = getContainer();
2022 while (
auto insertValueOp = container.
getDefiningOp<InsertValueOp>()) {
2024 auto extractPosSize = extractPos.size();
2025 auto insertPosSize = insertPos.size();
2028 if (extractPos == insertPos)
2029 return insertValueOp.getValue();
2043 if (extractPosSize > insertPosSize &&
2044 extractPos.take_front(insertPosSize) == insertPos) {
2045 container = insertValueOp.getValue();
2046 extractPos = extractPos.drop_front(insertPosSize);
2062 if (insertPosSize > extractPosSize &&
2063 extractPos == insertPos.take_front(extractPosSize))
2068 container = insertValueOp.getContainer();
2074 if (container == getContainer())
2076 setPosition(extractPos);
2077 getContainerMutable().assign(container);
2081LogicalResult ExtractValueOp::verify() {
2082 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
2088 if (getRes().
getType() != valueType)
2089 return emitOpError() <<
"Type mismatch: extracting from "
2090 << getContainer().getType() <<
" should produce "
2091 << valueType <<
" but this op returns "
2092 << getRes().getType();
2098 build(builder, state,
2137 LogicalResult matchAndRewrite(InsertValueOp insertOp,
2138 PatternRewriter &rewriter)
const override {
2139 bool changed =
false;
2145 auto insertBaseIdx = insertOp.getPosition()[0];
2146 for (
auto &use : insertOp->getUses()) {
2147 if (
auto extractOp = dyn_cast<ExtractValueOp>(use.getOwner())) {
2148 auto baseIdx = extractOp.getPosition()[0];
2151 if (baseIdx == insertBaseIdx)
2153 posToExtractOps[baseIdx].push_back(extractOp);
2158 Value nextContainer = insertOp.getContainer();
2159 while (!posToExtractOps.empty()) {
2161 dyn_cast_or_null<InsertValueOp>(nextContainer.
getDefiningOp());
2164 nextContainer = curInsert.getContainer();
2167 auto curInsertBaseIdx = curInsert.getPosition()[0];
2168 auto it = posToExtractOps.find(curInsertBaseIdx);
2169 if (it == posToExtractOps.end())
2173 for (
auto &extractOp : it->second) {
2175 extractOp.getContainerMutable().assign(curInsert);
2180 assert(!it->second.empty());
2182 posToExtractOps.erase(it);
2186 for (
auto &[baseIdx, extracts] : posToExtractOps) {
2187 for (
auto &extractOp : extracts) {
2189 extractOp.getContainerMutable().assign(nextContainer);
2192 assert(!extracts.empty() &&
"Empty list in map");
2202 patterns.
add<ResolveExtractValueSource>(context);
2210 [&](StringRef msg) {
2222LogicalResult InsertValueOp::verify() {
2223 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
2229 if (getValue().
getType() != valueType)
2230 return emitOpError() <<
"Type mismatch: cannot insert "
2231 << getValue().getType() <<
" into "
2232 << getContainer().getType();
2241LogicalResult ReturnOp::verify() {
2242 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2246 Type expectedType = parent.getFunctionType().getReturnType();
2247 if (llvm::isa<LLVMVoidType>(expectedType)) {
2251 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2255 if (llvm::isa<LLVMVoidType>(expectedType))
2258 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2261 if (expectedType != getArg().
getType()) {
2263 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2274 return dyn_cast_or_null<GlobalOp>(
2279 return dyn_cast_or_null<LLVMFuncOp>(
2284 return dyn_cast_or_null<AliasOp>(
2289 return dyn_cast_or_null<IFuncOp>(
2298 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2299 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2300 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2301 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2303 if (!global && !function && !alias && !ifunc)
2304 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2305 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2307 LLVMPointerType type =
getType();
2308 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2309 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2310 return emitOpError(
"pointer address space must match address space of the "
2311 "referenced global or alias");
2318 return getGlobalNameAttr();
2339 getFunctionNameAttr());
2340 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2341 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2343 if (!function && !alias)
2345 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2348 if (alias.getInitializer()
2349 .walk([&](AddressOfOp addrOp) {
2350 if (addrOp.getGlobal(symbolTable))
2351 return WalkResult::interrupt();
2352 return WalkResult::advance();
2355 return emitOpError(
"must reference an alias to a function");
2358 if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2359 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2361 "target function with 'extern_weak' linkage not allowed");
2369 return DSOLocalEquivalentAttr::get(
getContext(), getFunctionNameAttr());
2377 StringRef symName) {
2380 Region *body =
result.addRegion();
2384LogicalResult ComdatOp::verifyRegions() {
2385 Region &body = getBody();
2386 for (Operation &op : body.
getOps())
2387 if (!isa<ComdatSelectorOp>(op))
2388 return op.emitError(
2389 "only comdat selector symbols can appear in a comdat region");
2399 bool isConstant, Linkage linkage, StringRef name,
2400 Attribute value, uint64_t alignment,
unsigned addrSpace,
2401 bool dsoLocal, ThreadLocalMode threadModel,
2404 result.getOrAddProperties<Properties>().sym_name =
2406 result.addAttribute(getGlobalTypeAttrName(
result.name), TypeAttr::get(type));
2408 getTlsModeAttrName(
result.name),
2409 ThreadLocalModeAttr::get(builder.
getContext(), threadModel));
2414 result.addAttribute(getValueAttrName(
result.name), value);
2419 result.addAttribute(getComdatAttrName(
result.name), comdat);
2429 LinkageAttr::get(builder.
getContext(), linkage));
2433 result.attributes.append(attrs.begin(), attrs.end());
2435 if (!dbgExprs.empty())
2437 ArrayAttr::get(builder.
getContext(), dbgExprs));
2442template <
typename OpType>
2444 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2445 StringRef visibility = stringifyVisibility(op.getVisibility_());
2446 if (!visibility.empty())
2447 p << visibility <<
' ';
2449 if (ThreadLocalMode mode = op.getTlsMode();
2450 mode != ThreadLocalMode::NotThreadLocal) {
2451 p <<
"thread_local";
2452 if (mode != ThreadLocalMode::GeneralDynamic)
2453 p <<
'(' << mode <<
')';
2457 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2458 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2470 if (
auto value = getValueOrNull())
2473 if (
auto comdat = getComdat())
2474 p <<
" comdat(" << *comdat <<
')';
2480 (*this)->getAttrs(),
2481 {getSymNameAttrName(), getGlobalTypeAttrName(), getConstantAttrName(),
2482 getValueAttrName(), getLinkageAttrName(), getUnnamedAddrAttrName(),
2483 getTlsModeAttrName(), getVisibility_AttrName(), getComdatAttrName()});
2486 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2490 Region &initializer = getInitializerRegion();
2491 if (!initializer.
empty()) {
2498 std::optional<SymbolRefAttr> attr) {
2503 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2504 return op->
emitError() <<
"expected comdat symbol";
2514 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2515 if (blockTags.contains(blockTagOp.getTag())) {
2516 blockTagOp.emitError()
2517 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2518 <<
"' in the same function: ";
2521 blockTags.insert(blockTagOp.getTag());
2525 return failure(res.wasInterrupted());
2530template <
typename OpType>
2537 OpType::getLinkageAttrName(
result.name),
2539 parser, LLVM::Linkage::External)));
2542 result.addAttribute(OpType::getVisibility_AttrName(
result.name),
2545 parser, LLVM::Visibility::Default)));
2548 ThreadLocalMode threadModel = ThreadLocalMode::GeneralDynamic;
2555 parser, ThreadLocalMode::NotThreadLocal);
2556 if (threadModel == ThreadLocalMode::NotThreadLocal) {
2557 parser.
emitError(kwLoc,
"invalid value for thread_local");
2563 result.addAttribute(OpType::getTlsModeAttrName(
result.name),
2564 ThreadLocalModeAttr::get(ctx, threadModel));
2568 result.addAttribute(OpType::getUnnamedAddrAttrName(
result.name),
2571 parser, LLVM::UnnamedAddr::None)));
2609 SymbolRefAttr comdat;
2614 result.addAttribute(getComdatAttrName(
result.name), comdat);
2622 if (types.size() > 1)
2626 if (types.empty()) {
2627 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2629 auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2630 strAttr.getValue().size());
2631 types.push_back(arrayType);
2634 "type can only be omitted for string globals");
2644 result.addAttribute(getGlobalTypeAttrName(
result.name),
2645 TypeAttr::get(types[0]));
2650 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2651 return intValue.getValue().isZero();
2652 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2653 return fpValue.getValue().isZero();
2654 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2656 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2658 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2663LogicalResult GlobalOp::verify() {
2665 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2667 :
llvm::isa<PointerElementTypeInterface>(
getType());
2670 "expects type to be a valid element type for an LLVM global");
2672 return emitOpError(
"must appear at the module level");
2674 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2675 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2676 IntegerType elementType =
2677 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) :
nullptr;
2678 if (!elementType || elementType.getWidth() != 8 ||
2679 type.getNumElements() != strAttr.getValue().size())
2681 "requires an i8 array type of the length equal to that of the string "
2685 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2686 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2687 return emitOpError()
2688 <<
"this target extension type cannot be used in a global";
2691 return emitOpError() <<
"global with target extension type can only be "
2692 "initialized with zero-initializer";
2695 if (getLinkage() == Linkage::Common) {
2696 if (
Attribute value = getValueOrNull()) {
2698 return emitOpError()
2699 <<
"expected zero value for '"
2700 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2705 if (getLinkage() == Linkage::Appending) {
2706 if (!llvm::isa<LLVMArrayType>(
getType())) {
2707 return emitOpError() <<
"expected array type for '"
2708 << stringifyLinkage(Linkage::Appending)
2716 std::optional<uint64_t> alignAttr = getAlignment();
2717 if (alignAttr.has_value()) {
2718 uint64_t value = alignAttr.value();
2719 if (!llvm::isPowerOf2_64(value))
2720 return emitError() <<
"alignment attribute is not a power of 2";
2724 if (associated.getValue() == getSymName())
2725 return emitOpError(
"associated cannot refer to the global itself");
2728 if (
ArrayAttr absSym = getAbsoluteSymbolAttr()) {
2729 if (absSym.empty() || absSym.size() % 2 != 0)
2731 "absolute_symbol must contain one or more integer range pairs");
2734 auto intAttr = dyn_cast<IntegerAttr>(attr);
2736 return emitOpError(
"absolute_symbol operands must be integers");
2738 pairType = intAttr.getType();
2739 else if (intAttr.getType() != pairType)
2740 return emitOpError(
"absolute_symbol range pair types must match");
2747LogicalResult GlobalOp::verifyRegions() {
2748 if (
Block *
b = getInitializerBlock()) {
2749 ReturnOp ret = cast<ReturnOp>(
b->getTerminator());
2750 if (ret.operand_type_begin() == ret.operand_type_end())
2751 return emitOpError(
"initializer region cannot return void");
2752 if (*ret.operand_type_begin() !=
getType())
2753 return emitOpError(
"initializer region type ")
2754 << *ret.operand_type_begin() <<
" does not match global type "
2758 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2759 if (!iface || !iface.hasNoEffect())
2760 return op.emitError()
2761 <<
"ops with side effects not allowed in global initializers";
2764 if (getValueOrNull())
2765 return emitOpError(
"cannot have both initializer value and region");
2780 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2783 return op->
emitError(
"data element must be symbol or #llvm.zero");
2796LogicalResult GlobalCtorsOp::verify() {
2800 if (getCtors().size() == getPriorities().size() &&
2801 getCtors().size() == getData().size())
2804 "ctors, priorities, and data must have the same number of elements");
2821LogicalResult GlobalDtorsOp::verify() {
2825 if (getDtors().size() == getPriorities().size() &&
2826 getDtors().size() == getData().size())
2829 "dtors, priorities, and data must have the same number of elements");
2837 Linkage linkage, StringRef name,
bool dsoLocal,
2838 ThreadLocalMode threadModel,
2842 result.addAttribute(getAliasTypeAttrName(
result.name), TypeAttr::get(type));
2844 getTlsModeAttrName(
result.name),
2845 ThreadLocalModeAttr::get(builder.
getContext(), threadModel));
2851 LinkageAttr::get(builder.
getContext(), linkage));
2852 result.attributes.append(attrs.begin(), attrs.end());
2862 {getSymNameAttrName(), getAliasTypeAttrName(),
2863 getLinkageAttrName(), getUnnamedAddrAttrName(),
2864 getTlsModeAttrName(), getVisibility_AttrName()});
2867 p <<
" : " <<
getType() <<
' ';
2893 if (types.size() > 1)
2901 TypeAttr::get(types[0]));
2905LogicalResult AliasOp::verify() {
2907 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2909 :
llvm::isa<PointerElementTypeInterface>(
getType());
2912 "expects type to be a valid element type for an LLVM global alias");
2915 switch (getLinkage()) {
2916 case Linkage::External:
2917 case Linkage::Internal:
2918 case Linkage::Private:
2920 case Linkage::WeakODR:
2921 case Linkage::Linkonce:
2922 case Linkage::LinkonceODR:
2923 case Linkage::AvailableExternally:
2926 return emitOpError()
2927 <<
"'" << stringifyLinkage(getLinkage())
2928 <<
"' linkage not supported in aliases, available options: private, "
2929 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2930 "available_externally";
2936LogicalResult AliasOp::verifyRegions() {
2937 Block &
b = getInitializerBlock();
2938 auto ret = cast<ReturnOp>(
b.getTerminator());
2939 if (ret.getNumOperands() == 0 ||
2940 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2941 return emitOpError(
"initializer region must always return a pointer");
2944 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2945 if (!iface || !iface.hasNoEffect())
2946 return op.emitError()
2947 <<
"ops with side effects are not allowed in alias initializers";
2953unsigned AliasOp::getAddrSpace() {
2954 Block &initializer = getInitializerBlock();
2956 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2957 return ptrTy.getAddressSpace();
2965 Type iFuncType, StringRef resolverName,
Type resolverType,
2966 Linkage linkage, LLVM::Visibility visibility) {
2967 return build(builder,
result, name, iFuncType, resolverName, resolverType,
2969 UnnamedAddr::None, visibility,
nullptr);
2976 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2977 auto alias = dyn_cast<AliasOp>(symbol);
2979 Block &initBlock = alias.getInitializerBlock();
2981 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
2988 resolver = addrOp.getFunction(symbolTable);
2989 alias = addrOp.getAlias(symbolTable);
2992 return emitOpError(
"must have a function resolver");
2993 Linkage linkage = resolver.getLinkage();
2994 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
2995 return emitOpError(
"resolver must be a definition");
2996 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
2997 return emitOpError(
"resolver must return a pointer");
2998 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
2999 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
3000 return emitOpError(
"resolver has incorrect type");
3004LogicalResult IFuncOp::verify() {
3005 switch (getLinkage()) {
3006 case Linkage::External:
3007 case Linkage::Internal:
3008 case Linkage::Private:
3010 case Linkage::WeakODR:
3011 case Linkage::Linkonce:
3012 case Linkage::LinkonceODR:
3015 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
3016 <<
"' linkage not supported in ifuncs, available "
3017 "options: private, internal, linkonce, weak, "
3018 "linkonce_odr, weak_odr, or external linkage";
3030 auto containerType = v1.
getType();
3034 build(builder, state, vType, v1, v2, mask);
3049 "expected an LLVM compatible vector type");
3061LogicalResult ShuffleVectorOp::verify() {
3063 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
3064 return emitOpError(
"expected a splat operation for scalable vectors");
3070OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
3072 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
3073 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
3077 if (getMask().size() != 1 || getMask()[0] != 0)
3088 assert(empty() &&
"function already has an entry block");
3093 LLVMFunctionType type = getFunctionType();
3094 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
3095 entry->
addArgument(type.getParamType(i), getLoc());
3100 StringRef name,
Type type, LLVM::Linkage linkage,
3101 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
3104 std::optional<uint64_t> functionEntryCount) {
3108 result.addAttribute(getFunctionTypeAttrName(
result.name),
3109 TypeAttr::get(type));
3111 LinkageAttr::get(builder.
getContext(), linkage));
3113 CConvAttr::get(builder.
getContext(), cconv));
3114 result.attributes.append(attrs.begin(), attrs.end());
3119 result.addAttribute(getComdatAttrName(
result.name), comdat);
3120 if (functionEntryCount)
3121 result.addAttribute(getFunctionEntryCountAttrName(
result.name),
3122 FunctionEntryCountAttr::get(
3126 std::optional<NamedAttribute> duplicate =
result.attributes.findDuplicate();
3127 if (duplicate.has_value()) {
3128 llvm::report_fatal_error(
3129 Twine(
"LLVMFuncOp propagated an attribute that is meant "
3130 "to be constructed by the builder: ") +
3131 duplicate->getName().str());
3134 if (argAttrs.empty())
3137 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
3138 "expected as many argument attribute lists as arguments");
3140 builder,
result, argAttrs, {},
3141 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3152 if (outputs.size() > 1) {
3153 parser.
emitError(loc,
"failed to construct function type: expected zero or "
3154 "one function result");
3160 for (
auto t : inputs) {
3162 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3163 "type for function arguments");
3166 llvmInputs.push_back(t);
3171 outputs.empty() ? LLVMVoidType::get(
b.getContext()) : outputs.front();
3173 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3174 "type for function results")
3178 return LLVMFunctionType::get(llvmOutput, llvmInputs,
3194 parser, LLVM::Linkage::External)));
3197 result.addAttribute(getVisibility_AttrName(
result.name),
3200 parser, LLVM::Visibility::Default)));
3203 result.addAttribute(getUnnamedAddrAttrName(
result.name),
3206 parser, LLVM::UnnamedAddr::None)));
3210 getCConvAttrName(
result.name),
3214 StringAttr nameAttr;
3224 parser,
true, entryArgs, isVariadic, resultTypes,
3229 for (
auto &arg : entryArgs)
3230 argTypes.push_back(arg.type);
3236 result.addAttribute(getFunctionTypeAttrName(
result.name),
3237 TypeAttr::get(type));
3245 auto intTy = IntegerType::get(parser.
getContext(), 32);
3247 getVscaleRangeAttrName(
result.name),
3248 LLVM::VScaleRangeAttr::get(parser.
getContext(),
3249 IntegerAttr::get(intTy, minRange),
3250 IntegerAttr::get(intTy, maxRange)));
3254 SymbolRefAttr comdat;
3259 result.addAttribute(getComdatAttrName(
result.name), comdat);
3266 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3268 auto *body =
result.addRegion();
3279 if (getLinkage() != LLVM::Linkage::External)
3280 p << stringifyLinkage(getLinkage()) <<
' ';
3281 StringRef visibility = stringifyVisibility(getVisibility_());
3282 if (!visibility.empty())
3283 p << visibility <<
' ';
3284 if (
auto unnamedAddr = getUnnamedAddr()) {
3285 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3289 if (getCConv() != LLVM::CConv::C)
3290 p << stringifyCConv(getCConv()) <<
' ';
3294 LLVMFunctionType fnType = getFunctionType();
3297 argTypes.reserve(fnType.getNumParams());
3298 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3299 argTypes.push_back(fnType.getParamType(i));
3301 Type returnType = fnType.getReturnType();
3302 if (!llvm::isa<LLVMVoidType>(returnType))
3303 resTypes.push_back(returnType);
3306 isVarArg(), resTypes);
3309 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3310 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3311 << vscale->getMaxRange().getInt() <<
')';
3314 if (
auto comdat = getComdat())
3315 p <<
" comdat(" << *comdat <<
')';
3319 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3320 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3321 getComdatAttrName(), getUnnamedAddrAttrName(),
3322 getVscaleRangeAttrName()});
3325 Region &body = getBody();
3326 if (!body.empty()) {
3337LogicalResult LLVMFuncOp::verify() {
3338 if (getLinkage() == LLVM::Linkage::Common)
3339 return emitOpError() <<
"functions cannot have '"
3340 << stringifyLinkage(LLVM::Linkage::Common)
3347 if (getFunctionEntryCountAttr())
3348 return emitOpError() <<
"external functions cannot have "
3349 << getFunctionEntryCountAttrName() <<
" attribute";
3351 if (getLinkage() != LLVM::Linkage::External &&
3352 getLinkage() != LLVM::Linkage::ExternWeak)
3353 return emitOpError() <<
"external functions must have '"
3354 << stringifyLinkage(LLVM::Linkage::External)
3356 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3362 if (isNoInline() && isAlwaysInline())
3363 return emitError(
"no_inline and always_inline attributes are incompatible");
3365 if (isOptimizeNone() && !isNoInline())
3366 return emitOpError(
"with optimize_none must also be no_inline");
3368 Type landingpadResultTy;
3369 StringRef diagnosticMessage;
3370 bool isLandingpadTypeConsistent =
3372 const auto checkType = [&](
Type type, StringRef errorMessage) {
3373 if (!landingpadResultTy) {
3374 landingpadResultTy = type;
3377 if (landingpadResultTy != type) {
3378 diagnosticMessage = errorMessage;
3384 .Case([&](LandingpadOp landingpad) {
3385 constexpr StringLiteral errorMessage =
3386 "'llvm.landingpad' should have a consistent result type "
3387 "inside a function";
3388 return checkType(landingpad.getType(), errorMessage);
3390 .Case([&](ResumeOp resume) {
3391 constexpr StringLiteral errorMessage =
3392 "'llvm.resume' should have a consistent input type inside a "
3394 return checkType(resume.getValue().getType(), errorMessage);
3397 }).wasInterrupted();
3398 if (!isLandingpadTypeConsistent) {
3399 assert(!diagnosticMessage.empty() &&
3400 "Expecting a non-empty diagnostic message");
3412LogicalResult LLVMFuncOp::verifyRegions() {
3416 unsigned numArguments = getFunctionType().getNumParams();
3417 Block &entryBlock = front();
3418 for (
unsigned i = 0; i < numArguments; ++i) {
3421 return emitOpError(
"entry block argument #")
3422 << i <<
" is not of LLVM type";
3428Region *LLVMFuncOp::getCallableRegion() {
3457OpFoldResult LLVM::MetadataAsValueOp::fold(FoldAdaptor) {
3458 return getMetadataAttr();
3465LogicalResult LLVM::ZeroOp::verify() {
3466 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3467 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3468 return emitOpError()
3469 <<
"target extension type does not support zero-initializer";
3491 if (
auto vecType = dyn_cast<VectorType>(t)) {
3492 assert(!vecType.isScalable() &&
3493 "number of elements of a scalable vector type is unknown");
3494 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3496 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3497 return arrayType.getNumElements() *
3505 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3506 type = arrayType.getElementType();
3507 if (
auto vecType = dyn_cast<VectorType>(type))
3508 return vecType.getElementType();
3509 if (
auto tenType = dyn_cast<TensorType>(type))
3510 return tenType.getElementType();
3517 if (
auto vecType = dyn_cast<VectorType>(t)) {
3518 if (vecType.isScalable())
3522 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3530 LLVM::LLVMArrayType arrayType,
3532 if (arrayType.getNumElements() != arrayAttr.size())
3533 return op.emitOpError()
3534 <<
"array attribute size does not match array type size in "
3536 << dim <<
": " << arrayAttr.size() <<
" vs. "
3537 << arrayType.getNumElements();
3542 if (
auto subArrayType =
3543 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3544 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3545 if (elementsVerified.insert(elementAttr).second) {
3546 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3548 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3550 return op.emitOpError()
3551 <<
"nested attribute for sub-array in dimension " << dim
3552 <<
" at index " << idx
3553 <<
" must be a zero, or undef, or array attribute";
3567 Type elementType = arrayType.getElementType();
3568 if (isa<LLVM::LLVMPointerType>(elementType)) {
3569 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3571 LLVM::PoisonAttr>(elementAttr))
3573 return op.emitOpError()
3574 <<
"pointer array element at index " << idx
3575 <<
" must be a flat symbol reference, zero, undef, or poison";
3579 auto structType = dyn_cast<LLVM::LLVMStructType>(elementType);
3581 return op.emitOpError() <<
"for array with an array attribute must have a "
3582 "struct element type";
3586 size_t numStructElements = structType.getBody().size();
3587 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3588 if (elementsVerified.insert(elementAttr).second) {
3589 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3591 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3593 return op.emitOpError()
3594 <<
"nested attribute for struct element at index " << idx
3595 <<
" must be a zero, or undef, or array attribute";
3596 if (subArrayAttr.size() != numStructElements)
3597 return op.emitOpError()
3598 <<
"nested array attribute size for struct element at index "
3599 << idx <<
" must match struct size: " << subArrayAttr.size()
3600 <<
" vs. " << numStructElements;
3607LogicalResult LLVM::ConstantOp::verify() {
3608 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3609 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3610 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3611 !arrayType.getElementType().isInteger(8)) {
3612 return emitOpError() <<
"expected array type of "
3613 << sAttr.getValue().size()
3614 <<
" i8 elements for the string constant";
3618 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3619 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3621 return emitOpError() <<
"expected array attribute for struct type";
3624 if (arrayAttr.size() != elementTypes.size()) {
3625 return emitOpError() <<
"expected array attribute of size "
3626 << elementTypes.size();
3628 for (
auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3630 return emitOpError() <<
"expected struct element types to be floating "
3631 "point type or integer type";
3633 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3634 return emitOpError() <<
"expected element of array attribute to be "
3635 "floating point or integer";
3637 if (cast<TypedAttr>(attr).
getType() != type)
3638 return emitOpError()
3639 <<
"struct element at index " << i <<
" is of wrong type";
3644 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3645 return emitOpError() <<
"does not support target extension type.";
3656 auto verifyFloatSemantics =
3657 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3658 Type constantElementType) -> LogicalResult {
3659 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3660 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3661 return emitOpError()
3662 <<
"attribute and type have different float semantics";
3666 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3667 if (isa<IntegerType>(constantElementType)) {
3668 if (!constantElementType.isInteger(floatWidth))
3669 return emitOpError() <<
"expected integer type of width " << floatWidth;
3684 auto verifyIntegerSemantics = [
this](
Type attributeIntType,
3685 Type constantElementType,
3686 StringRef description) -> LogicalResult {
3687 if (attributeIntType != constantElementType)
3688 return emitOpError() <<
"attribute and type have different integer "
3689 << description <<
"s: " << attributeIntType
3690 <<
" vs. " << constantElementType;
3695 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
3696 if (!llvm::isa<IntegerType>(
getType()))
3697 return emitOpError() <<
"expected integer type";
3698 return verifyIntegerSemantics(intAttr.getType(),
getType(),
"type");
3699 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3700 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3701 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3705 auto verifyElementTypes = [&](ElementsAttr attr) -> LogicalResult {
3708 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3709 return verifyFloatSemantics(floatType.getFloatSemantics(),
3712 if (isa<IntegerType, IndexType>(attrElmType)) {
3713 if (!isa<IntegerType>(resultElmType))
3715 "expected integer element type for integer elements attribute");
3716 return verifyIntegerSemantics(attrElmType, resultElmType,
3725 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3726 if (!splatElementsAttr)
3727 return emitOpError()
3728 <<
"scalable vector type requires a splat attribute";
3729 return verifyElementTypes(splatElementsAttr);
3731 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3732 return emitOpError() <<
"expected vector or array type";
3735 int64_t attrNumElements = elementsAttr.getNumElements();
3737 return emitOpError()
3738 <<
"type and attribute have a different number of elements: "
3742 return verifyElementTypes(elementsAttr);
3743 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3746 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3748 return emitOpError()
3749 <<
"expected array or struct type for array attribute";
3755 return emitOpError()
3756 <<
"only supports integer, float, string or elements attributes";
3760bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3762 auto typedAttr = dyn_cast<TypedAttr>(value);
3769 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3774 if (isBuildableWith(value, type))
3775 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3780OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3788 AtomicOrdering ordering, StringRef syncscope,
3789 unsigned alignment,
bool isVolatile) {
3790 build(builder, state, val.
getType(), binOp,
ptr, val, ordering,
3791 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3794 nullptr,
nullptr,
nullptr);
3797LogicalResult AtomicRMWOp::verify() {
3798 auto valType = getVal().getType();
3799 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3800 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3801 getBinOp() == AtomicBinOp::fminimum ||
3802 getBinOp() == AtomicBinOp::fmaximum ||
3803 getBinOp() == AtomicBinOp::fminimumnum ||
3804 getBinOp() == AtomicBinOp::fmaximumnum) {
3807 return emitOpError(
"expected LLVM IR fixed vector type");
3808 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3811 "expected LLVM IR floating point type for vector element");
3813 return emitOpError(
"expected LLVM IR floating point type");
3815 }
else if (getBinOp() == AtomicBinOp::xchg) {
3818 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3820 auto intType = llvm::dyn_cast<IntegerType>(valType);
3821 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3822 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3824 return emitOpError(
"expected LLVM IR integer type");
3827 if (
static_cast<unsigned>(getOrdering()) <
3828 static_cast<unsigned>(AtomicOrdering::monotonic))
3829 return emitOpError() <<
"expected at least '"
3830 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3842 auto boolType = IntegerType::get(valType.
getContext(), 1);
3843 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3848 AtomicOrdering successOrdering,
3849 AtomicOrdering failureOrdering, StringRef syncscope,
3850 unsigned alignment,
bool isWeak,
bool isVolatile) {
3852 successOrdering, failureOrdering,
3853 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3855 isVolatile,
nullptr,
3856 nullptr,
nullptr,
nullptr);
3859LogicalResult AtomicCmpXchgOp::verify() {
3860 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3862 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3863 auto valType = getVal().getType();
3866 return emitOpError(
"unexpected LLVM IR type");
3867 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3868 getFailureOrdering() < AtomicOrdering::monotonic)
3869 return emitOpError(
"ordering must be at least 'monotonic'");
3870 if (getFailureOrdering() == AtomicOrdering::release ||
3871 getFailureOrdering() == AtomicOrdering::acq_rel)
3872 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3881 AtomicOrdering ordering, StringRef syncscope) {
3882 build(builder, state, ordering,
3883 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3886LogicalResult FenceOp::verify() {
3887 if (getOrdering() == AtomicOrdering::not_atomic ||
3888 getOrdering() == AtomicOrdering::unordered ||
3889 getOrdering() == AtomicOrdering::monotonic)
3890 return emitOpError(
"can be given only acquire, release, acq_rel, "
3891 "and seq_cst orderings");
3901template <
class ExtOp>
3903 IntegerType inputType, outputType;
3906 return op.emitError(
3907 "input type is a vector but output type is an integer");
3910 return op.emitError(
"input and output vectors are of incompatible shape");
3913 inputType = cast<IntegerType>(
3914 cast<VectorType>(op.getArg().getType()).getElementType());
3915 outputType = cast<IntegerType>(
3916 cast<VectorType>(op.getResult().getType()).getElementType());
3920 inputType = cast<IntegerType>(op.getArg().getType());
3921 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3923 return op.emitError(
3924 "input type is an integer but output type is a vector");
3927 if (outputType.getWidth() <= inputType.getWidth())
3928 return op.emitError(
"integer width of the output type is smaller or "
3929 "equal to the integer width of the input type");
3940 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3944 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3945 return IntegerAttr::get(
getType(), arg.getValue().zext(targetSize));
3959template <
typename T>
3961 typename T::FoldAdaptor adaptor) {
3963 if (castOp.getArg().getType() == castOp.getType())
3964 return castOp.getArg();
3965 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3967 if (prev.getArg().getType() == castOp.getType())
3968 return prev.getArg();
3970 castOp.getArgMutable().set(prev.getArg());
3971 return Value{castOp};
3976OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3980LogicalResult LLVM::BitcastOp::verify() {
3986 if (isa<LLVMByteType>(srcElemType) || isa<LLVMByteType>(dstElemType))
3989 auto resultType = llvm::dyn_cast<LLVMPointerType>(dstElemType);
3990 auto sourceType = llvm::dyn_cast<LLVMPointerType>(srcElemType);
3994 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3995 return emitOpError(
"can only cast pointers from and to pointers");
4000 auto isVector = llvm::IsaPred<VectorType>;
4004 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
4005 return emitOpError(
"cannot cast pointer to vector of pointers");
4007 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
4008 return emitOpError(
"cannot cast vector of pointers to pointer");
4012 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
4013 return emitOpError(
"cannot cast pointers of different address spaces, "
4014 "use 'llvm.addrspacecast' instead");
4019LogicalResult LLVM::PtrToAddrOp::verify() {
4026 assert(width &&
"pointers always return an index bitwidth");
4027 if (width != integerType.getWidth())
4028 return emitOpError(
"bit-width of integer result type ")
4029 << integerType <<
" must match the pointer bitwidth (" << *width
4030 <<
") specified in the datalayout";
4039OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
4043Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
4051 adaptor.getDynamicIndices());
4055 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(
indices[0]))
4056 if (integer.getValue().isZero())
4060 bool changed =
false;
4062 for (
auto iter : llvm::enumerate(
indices)) {
4063 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
4066 if (!
indices.isDynamicIndex(iter.index()) || !integer ||
4070 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
4071 gepArgs.emplace_back(val);
4073 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
4079 gepArgs.emplace_back(integer.getInt());
4087 getDynamicIndicesMutable().assign(dynamicIndices);
4088 setRawConstantIndices(rawConstantIndices);
4089 return Value{*
this};
4095Value LLVM::GEPOp::getViewSource() {
return getBase(); }
4102 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4106 if (rhs.getValue().uge(getLhs().
getType().getIntOrFloatBitWidth()))
4109 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4113 return IntegerAttr::get(
getType(), lhs.getValue().shl(rhs.getValue()));
4121 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4125 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4129 return IntegerAttr::get(
getType(), lhs.getValue() | rhs.getValue());
4136LogicalResult CallIntrinsicOp::verify() {
4137 if (!getIntrin().starts_with(
"llvm."))
4138 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
4146 build(builder, state,
TypeRange{}, intrin, args,
4147 FastmathFlagsAttr{},
4154 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4155 build(builder, state,
TypeRange{}, intrin, args,
4162 mlir::Type resultType, mlir::StringAttr intrin,
4164 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
4172 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4173 build(builder, state, resultTypes, intrin, args, fastMathFlags,
4178ParseResult CallIntrinsicOp::parse(
OpAsmParser &parser,
4180 StringAttr intrinAttr;
4190 result.addAttribute(CallIntrinsicOp::getIntrinAttrName(
result.name),
4198 return mlir::failure();
4201 return mlir::failure();
4206 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
4209 if (opBundleTags && !opBundleTags.empty())
4211 CallIntrinsicOp::getOpBundleTagsAttrName(
result.name).getValue(),
4215 return mlir::failure();
4220 operands, argAttrs, resultAttrs))
4224 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
4227 opBundleOperandTypes,
4228 getOpBundleSizesAttrName(
result.name)))
4231 int32_t numOpBundleOperands = 0;
4232 for (
const auto &operands : opBundleOperands)
4233 numOpBundleOperands += operands.size();
4236 CallIntrinsicOp::getOperandSegmentSizeAttr(),
4238 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
4240 return mlir::success();
4248 p <<
"(" << args <<
")";
4251 if (!getOpBundleOperands().empty()) {
4254 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
4258 {getOperandSegmentSizesAttrName(),
4259 getOpBundleSizesAttrName(), getIntrinAttrName(),
4260 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
4261 getResAttrsAttrName()});
4267 p, args.
getTypes(), getArgAttrsAttr(),
4268 false, getResultTypes(), getResAttrsAttr());
4275LogicalResult LinkerOptionsOp::verify() {
4278 return emitOpError(
"must appear at the module level");
4286LogicalResult ModuleFlagsOp::verify() {
4289 return emitOpError(
"must appear at the module level");
4293 auto moduleFlag = dyn_cast<ModuleFlagAttrInterface>(flag);
4295 return emitOpError(
"expected a module flag attribute");
4297 moduleFlag.getModuleFlagKey(), moduleFlag.getModuleFlagValue(),
4298 [&] { return emitOpError(); })))
4300 if (moduleFlag.getModuleFlagBehavior() == ModFlagBehavior::Require)
4302 StringAttr key = moduleFlag.getModuleFlagKey();
4303 if (!seenNonRequireKeys.insert(key).second)
4304 return emitOpError(
"expected module flag key '")
4305 << key.getValue() <<
"' to be unique for non-require flags";
4314void InlineAsmOp::getEffects(
4317 if (getHasSideEffects()) {
4330 getBlockAddr().getFunction());
4331 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
4334 return emitOpError(
"must reference a function defined by 'llvm.func'");
4344BlockTagOp BlockAddressOp::getBlockTagOp() {
4349 auto funcOp = dyn_cast<LLVMFuncOp>(sym);
4352 BlockTagOp blockTagOp =
nullptr;
4353 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4354 if (labelOp.getTag() == getBlockAddr().getTag()) {
4355 blockTagOp = labelOp;
4363LogicalResult BlockAddressOp::verify() {
4364 if (!getBlockTagOp())
4366 "expects an existing block label target in the referenced function");
4373OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4380 assert(
index < getNumSuccessors() &&
"invalid successor index");
4392 rangeSegments.push_back(range.size());
4406 Block *destination = nullptr;
4407 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4408 SmallVector<Type> operandTypes;
4410 if (parser.parseSuccessor(destination).failed())
4413 if (succeeded(parser.parseOptionalLParen())) {
4414 if (failed(parser.parseOperandList(
4415 operands, OpAsmParser::Delimiter::None)) ||
4416 failed(parser.parseColonTypeList(operandTypes)) ||
4417 failed(parser.parseRParen()))
4420 succOperandBlocks.push_back(destination);
4421 succOperands.emplace_back(operands);
4422 succOperandsTypes.emplace_back(operandTypes);
4425 "successor blocks")))
4435 llvm::zip(succs, succOperands),
4441 if (!succOperands.empty())
4450LogicalResult LLVM::SincosOp::verify() {
4451 auto operandType = getOperand().getType();
4452 auto resultType = getResult().getType();
4453 auto resultStructType =
4454 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4455 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4456 resultStructType.getBody()[0] != operandType ||
4457 resultStructType.getBody()[1] != operandType) {
4458 return emitOpError(
"expected result type to be an homogeneous struct with "
4459 "two elements matching the operand type, but got ")
4471 return build(builder, state, cond, {},
4483 return build(builder, state, cond,
"align",
ValueRange{
ptr, align});
4489 return build(builder, state, cond,
"separate_storage",
4499LogicalResult LLVM::masked_gather::verify() {
4500 auto ptrsVectorType = getPtrs().getType();
4501 Type expectedPtrsVectorType =
4506 if (ptrsVectorType != expectedPtrsVectorType)
4507 return emitOpError(
"expected operand #1 type to be ")
4508 << expectedPtrsVectorType;
4516LogicalResult LLVM::masked_scatter::verify() {
4517 auto ptrsVectorType = getPtrs().getType();
4518 Type expectedPtrsVectorType =
4523 if (ptrsVectorType != expectedPtrsVectorType)
4524 return emitOpError(
"expected operand #2 type to be ")
4525 << expectedPtrsVectorType;
4538 build(builder, state, resTys,
ptr, mask, passthru, argAttrs,
4546void LLVM::masked_compressstore::build(
OpBuilder &builder,
4551 build(builder, state, value,
ptr, mask, argAttrs,
4559LogicalResult InlineAsmOp::verify() {
4560 if (!getTailCallKindAttr())
4563 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4565 "tail call kind 'musttail' is not supported by this operation");
4575 Value divisor = getRhs();
4590 Value divisor = getRhs();
4602void LLVMDialect::initialize() {
4603 registerAttributes();
4606 addTypes<LLVMVoidType,
4608 LLVMMetadataType>();
4612 registerLLVMDialectOperations(
this);
4615 allowUnknownOperations();
4616 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4620LogicalResult LLVMDialect::verifyDataLayoutString(
4623 llvm::DataLayout::parse(descr);
4624 if (maybeDataLayout)
4627 std::string message;
4628 llvm::raw_string_ostream messageStream(message);
4629 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4630 reportError(
"invalid data layout descriptor: " + message);
4635LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4641 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4643 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4644 return verifyDataLayoutString(
4645 stringAttr.getValue(),
4646 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4649 << LLVM::LLVMDialect::getDataLayoutAttrName()
4650 <<
"' to be a string attributes";
4653LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4661 StringAttr name = paramAttr.
getName();
4663 auto checkUnitAttrType = [&]() -> LogicalResult {
4664 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4665 return op->
emitError() << name <<
" should be a unit attribute";
4668 auto checkTypeAttrType = [&]() -> LogicalResult {
4669 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4670 return op->
emitError() << name <<
" should be a type attribute";
4673 auto checkIntegerAttrType = [&]() -> LogicalResult {
4674 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4675 return op->
emitError() << name <<
" should be an integer attribute";
4678 auto checkPointerType = [&]() -> LogicalResult {
4679 if (!llvm::isa<LLVMPointerType>(paramType))
4681 << name <<
" attribute attached to non-pointer LLVM type";
4684 auto checkIntegerType = [&]() -> LogicalResult {
4685 if (!llvm::isa<IntegerType>(paramType))
4687 << name <<
" attribute attached to non-integer LLVM type";
4690 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4691 if (
failed(checkPointerType()))
4698 if (name == LLVMDialect::getNoAliasAttrName() ||
4699 name == LLVMDialect::getReadonlyAttrName() ||
4700 name == LLVMDialect::getReadnoneAttrName() ||
4701 name == LLVMDialect::getWriteOnlyAttrName() ||
4702 name == LLVMDialect::getNestAttrName() ||
4703 name == LLVMDialect::getNoCaptureAttrName() ||
4704 name == LLVMDialect::getNoFreeAttrName() ||
4705 name == LLVMDialect::getNoFreeObjAttrName() ||
4706 name == LLVMDialect::getNonNullAttrName()) {
4707 if (
failed(checkUnitAttrType()))
4709 if (verifyValueType &&
failed(checkPointerType()))
4715 if (name == LLVMDialect::getStructRetAttrName() ||
4716 name == LLVMDialect::getByValAttrName() ||
4717 name == LLVMDialect::getByRefAttrName() ||
4718 name == LLVMDialect::getElementTypeAttrName() ||
4719 name == LLVMDialect::getInAllocaAttrName() ||
4720 name == LLVMDialect::getPreallocatedAttrName()) {
4721 if (
failed(checkTypeAttrType()))
4723 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4729 if (name == LLVMDialect::getSExtAttrName() ||
4730 name == LLVMDialect::getZExtAttrName()) {
4731 if (
failed(checkUnitAttrType()))
4733 if (verifyValueType &&
failed(checkIntegerType()))
4739 if (name == LLVMDialect::getAlignAttrName() ||
4740 name == LLVMDialect::getDereferenceableAttrName() ||
4741 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4742 if (
failed(checkIntegerAttrType()))
4744 if (verifyValueType &&
failed(checkPointerType()))
4750 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4751 if (
failed(checkIntegerAttrType()))
4757 if (name == LLVMDialect::getNoUndefAttrName() ||
4758 name == LLVMDialect::getInRegAttrName() ||
4759 name == LLVMDialect::getReturnedAttrName())
4760 return checkUnitAttrType();
4766LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4770 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4773 Type argType = funcOp.getArgumentTypes()[argIdx];
4775 return verifyParameterAttribute(op, argType, argAttr);
4778LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4782 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4785 Type resType = funcOp.getResultTypes()[resIdx];
4789 if (llvm::isa<LLVMVoidType>(resType))
4790 return op->
emitError() <<
"cannot attach result attributes to functions "
4791 "with a void return";
4795 auto name = resAttr.
getName();
4796 if (name == LLVMDialect::getAllocAlignAttrName() ||
4797 name == LLVMDialect::getAllocatedPointerAttrName() ||
4798 name == LLVMDialect::getByValAttrName() ||
4799 name == LLVMDialect::getByRefAttrName() ||
4800 name == LLVMDialect::getInAllocaAttrName() ||
4801 name == LLVMDialect::getNestAttrName() ||
4802 name == LLVMDialect::getNoCaptureAttrName() ||
4803 name == LLVMDialect::getNoFreeAttrName() ||
4804 name == LLVMDialect::getPreallocatedAttrName() ||
4805 name == LLVMDialect::getReadnoneAttrName() ||
4806 name == LLVMDialect::getReadonlyAttrName() ||
4807 name == LLVMDialect::getReturnedAttrName() ||
4808 name == LLVMDialect::getStackAlignmentAttrName() ||
4809 name == LLVMDialect::getStructRetAttrName() ||
4810 name == LLVMDialect::getWriteOnlyAttrName())
4811 return op->
emitError() << name <<
" is not a valid result attribute";
4812 return verifyParameterAttribute(op, resType, resAttr);
4820 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4821 if (isa<LLVM::LLVMPointerType>(type))
4822 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4823 if (isa<LLVM::UndefAttr>(value))
4824 return LLVM::UndefOp::create(builder, loc, type);
4825 if (isa<LLVM::PoisonAttr>(value))
4826 return LLVM::PoisonOp::create(builder, loc, type);
4827 if (isa<LLVM::ZeroAttr>(value))
4828 return LLVM::ZeroOp::create(builder, loc, type);
4829 if (isa<LLVM::MDStringAttr, LLVM::MDConstantAttr, LLVM::MDGlobalValueAttr,
4830 LLVM::MDNodeAttr>(value))
4831 if (isa<LLVM::LLVMMetadataType>(type))
4832 return LLVM::MetadataAsValueOp::create(builder, loc, type, value);
4834 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4842 StringRef name, StringRef value,
4843 LLVM::Linkage linkage) {
4846 "expected builder to point to a block constrained in an op");
4848 builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4849 assert(module &&
"builder points to an op outside of a module");
4854 auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4855 auto global = LLVM::GlobalOp::create(
4856 moduleBuilder, loc, type,
true, linkage, name,
4859 LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4862 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4863 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4875 module = module->getParentOp();
4876 assert(module &&
"unexpected operation outside of a module");
getNumOperands() - 1))) return failure()
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 LogicalResult verifyOperandBundles(OpType &op)
static void printOneOpBundle(OpAsmPrinter &p, OperandRange operands, TypeRange operandTypes, StringRef tag)
static LogicalResult verifyComdat(Operation *op, std::optional< SymbolRefAttr > attr)
static unsigned getNumConsumedCalleeOperands(OpTy callOp)
Return the number of leading callee operands of callOp that the operation consumes instead of passing...
static LLVMFunctionType getLLVMFuncType(MLIRContext *context, TypeRange results, ValueRange args)
Constructs a LLVMFunctionType from MLIR results and args.
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 Operation::operand_range getOperandsPassedToCallee(OpTy callOp)
Return the operands of callOp that are passed to the callee, including the variadic arguments in case...
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 ParseResult resolveOpBundleOperands(OpAsmParser &parser, SMLoc loc, OperationState &state, ArrayRef< SmallVector< OpAsmParser::UnresolvedOperand > > opBundleOperands, ArrayRef< SmallVector< Type > > opBundleOperandTypes, StringAttr opBundleSizesAttrName)
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 NamedAttrList getAttrsForPrinting(Operation *op)
static ParseResult parseCmpPredicateImpl(OpAsmParser &parser, PredicateAttr &predicate, function_ref< std::optional< Predicate >(StringRef)> symbolize)
static void printCommonGlobalAndAlias(OpAsmPrinter &p, OpType op)
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 LogicalResult verifyExtOp(ExtOp op)
Verifies that the given extension operation operates on consistent scalars or vectors,...
static constexpr const char kElemTypeAttrName[]
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.
#define REGISTER_ENUM_TYPE(Ty)
static Operation::operand_range getArgOperandsImpl(OpTy callOp)
Return the operands of callOp that correspond to the declared parameters of the callee,...
static std::string diag(const llvm::Value &value)
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
This base class exposes generic asm parser hooks, usable across the various derived parsers.
ParseResult parseSymbolName(StringAttr &result)
Parse an -identifier and store it (without the '@' symbol) in a string attribute.
@ Paren
Parens surrounding zero or more operands.
@ None
Zero or more operands with no delimiters.
@ Square
Square brackets surrounding zero or more operands.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseColonTypeList(SmallVectorImpl< Type > &result)=0
Parse a colon followed by a type list, which must have at least one type.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseOptionalColonTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional colon followed by a type list, which if present must have at least one type.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
virtual ParseResult parseCustomAttributeWithFallback(Attribute &result, Type type, function_ref< ParseResult(Attribute &result, Type type)> parseAttribute)=0
Parse a custom attribute with the provided callback, unless the next token is #, in which case the ge...
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
virtual ParseResult parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
virtual void printAttribute(Attribute attr)
virtual void printNewline()
Print a newline and indent the printer to the start of the current operation/attribute/type.
Attributes are known-constant values of operations.
MLIRContext * getContext() const
Return the context this attribute belongs to.
This class provides an abstraction over the different types of ranges over Blocks.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
static BoolAttr get(MLIRContext *context, bool value)
This class is a general helper class for creating context-global objects like types,...
IntegerAttr getI32IntegerAttr(int32_t value)
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
IntegerAttr getI64IntegerAttr(int64_t value)
Ty getType(Args &&...args)
Get or construct an instance of the type Ty with provided arguments.
StringAttr getStringAttr(const Twine &bytes)
TypedAttr getZeroAttr(Type type)
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
MLIRContext * getContext() const
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
NamedAttribute getNamedAttr(StringRef name, Attribute val)
ArrayAttr getStrArrayAttr(ArrayRef< StringRef > values)
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
The main mechanism for performing data layout queries.
static DataLayout closest(Operation *op)
Returns the layout of the closest parent operation carrying layout info.
std::optional< uint64_t > getTypeIndexBitwidth(Type t) const
Returns the bitwidth that should be used when performing index computations for the given pointer-lik...
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
An attribute that represents a reference to a dense integer vector or tensor object.
static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg)
Get an instance of a DenseIntElementsAttr with the given arguments.
A symbol reference with a reference path containing a single element.
StringRef getValue() const
Returns the name of the held symbol reference.
StringAttr getAttr() const
Returns the name of the held symbol reference as a StringAttr.
This class represents a fused location whose metadata is known to be an instance of the given type.
This class represents a diagnostic that is inflight and set to be reported.
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
Class used for building a 'llvm.getelementptr'.
Class used for convenient access and iteration over GEP indices.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
This class provides a mutable adaptor for a range of operands.
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
ArrayRef< NamedAttribute > getAttrs() const
Return all of the attributes on this operation.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
NamedAttribute represents a combination of a name and an Attribute value.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
virtual ParseResult parseSuccessor(Block *&dest)=0
Parse a single operation successor.
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
virtual OptionalParseResult parseOptionalOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single operand if present.
virtual ParseResult parseSuccessorAndUseList(Block *&dest, SmallVectorImpl< Value > &operands)=0
Parse a single operation successor and its operand list.
virtual OptionalParseResult parseOptionalRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region if present.
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printSuccessorAndUseList(Block *successor, ValueRange succOperands)=0
Print the successor and its operands.
void printOperands(const ContainerType &container)
Print a comma separated list of operands.
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
This class represents a single result from folding an operation.
This class provides the API for ops that are known to be isolated from above.
A trait used to provide symbol table functionalities to a region operation.
This class represents a contiguous range of operand ranges, e.g.
This class implements the operand iterators for the Operation class.
type_range getTypes() const
void walkInherentAttrs(Operation *op, InherentAttrVisitor visitor) const
Visit the inherent attributes stored in the properties of op.
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...
DictionaryAttr getRawDictionaryAttrs()
Return all attributes that are not stored as properties.
OperandRange operand_range
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OperationName getName()
The name of an operation is the key identifier for it.
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.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
This class contains a list of basic blocks and a link to the parent operation it is attached to.
iterator_range< OpIterator > getOps()
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
void modifyOpInPlace(Operation *root, CallableT &&callable)
This method is a utility wrapper around an in-place modification of an operation.
This class represents a specific instance of an effect.
static DerivedEffect * get()
This class models how operands are forwarded to block arguments in control flow.
This class implements the successor iterators for Block.
This class represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
static 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()
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.
LogicalResult verifyModuleFlagValue(StringAttr key, Attribute value, function_ref< InFlightDiagnostic()> emitError)
Verifies that a module flag value can be exported to LLVM IR.
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.
mlir::ParseResult parseCmpPredicate(mlir::OpAsmParser &parser, mlir::LLVM::ICmpPredicateAttr &predicate)
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
void printCmpPredicate(mlir::OpAsmPrinter &printer, mlir::Operation *, mlir::LLVM::ICmpPredicateAttr predicate)
mlir::ParseResult parseInsertExtractValueElementType(mlir::AsmParser &parser, mlir::Type &valueType, mlir::Type containerType, mlir::DenseI64ArrayAttr position)
Infer the value type from the container type and position.
void printLLVMLinkage(mlir::OpAsmPrinter &p, mlir::Operation *, mlir::LLVM::LinkageAttr val)
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...
void printOpBundles(mlir::OpAsmPrinter &p, mlir::Operation *op, mlir::OperandRangeRange opBundleOperands, mlir::TypeRangeRange opBundleOperandTypes, std::optional< mlir::ArrayAttr > opBundleTags)
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
mlir::ParseResult parseShuffleType(mlir::AsmParser &parser, mlir::Type v1Type, mlir::Type &resType, mlir::DenseI32ArrayAttr mask)
Build the result type of a shuffle vector operation.
constexpr int kGEPConstantBitWidth
Bit-width of a 'GEPConstantIndex' within GEPArg.
void printShuffleType(mlir::AsmPrinter &printer, mlir::Operation *op, mlir::Type v1Type, mlir::Type resType, mlir::DenseI32ArrayAttr mask)
Nothing to do when the result type is inferred.
mlir::Type getI1SameShape(mlir::Type type)
Returns a boolean type that has the same shape as type.
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.
void printSwitchOpCases(mlir::OpAsmPrinter &p, mlir::LLVM::SwitchOp op, mlir::Type flagType, mlir::DenseIntElementsAttr caseValues, mlir::SuccessorRange caseDestinations, mlir::OperandRangeRange caseOperands, const mlir::TypeRangeRange &caseOperandTypes)
void printIndirectBrOpSucessors(mlir::OpAsmPrinter &p, mlir::LLVM::IndirectBrOp op, mlir::Type flagType, mlir::SuccessorRange succs, mlir::OperandRangeRange succOperands, const mlir::TypeRangeRange &succOperandsTypes)
mlir::ParseResult parseIndirectBrOpSucessors(mlir::OpAsmParser &parser, mlir::Type &flagType, mlir::SmallVectorImpl< mlir::Block * > &succOperandBlocks, mlir::SmallVectorImpl< mlir::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &succOperands, mlir::SmallVectorImpl< mlir::SmallVector< mlir::Type > > &succOperandsTypes)
mlir::ParseResult parseLLVMLinkage(mlir::OpAsmParser &p, mlir::LLVM::LinkageAttr &val)
mlir::LLVM::LLVMStructType getValAndBoolStructType(mlir::Type valType)
Returns an LLVM struct type that contains a value type and a boolean type.
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
std::optional< mlir::ParseResult > parseOpBundles(mlir::OpAsmParser &p, mlir::SmallVector< mlir::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &opBundleOperands, mlir::SmallVector< mlir::SmallVector< mlir::Type > > &opBundleOperandTypes, mlir::ArrayAttr &opBundleTags)
Type getConstantElementType(Type type)
Determines the element type of type the way the llvm.mlir.constant verifier does, i....
mlir::ParseResult parseGEPIndices(mlir::OpAsmParser &parser, mlir::SmallVectorImpl< mlir::OpAsmParser::UnresolvedOperand > &indices, mlir::DenseI32ArrayAttr &rawConstantIndices)
void printGEPIndices(mlir::OpAsmPrinter &printer, mlir::LLVM::GEPOp gepOp, mlir::OperandRange indices, mlir::DenseI32ArrayAttr rawConstantIndices)
void printInsertExtractValueElementType(mlir::AsmPrinter &printer, mlir::Operation *op, mlir::Type valueType, mlir::Type containerType, mlir::DenseI64ArrayAttr position)
Nothing to print for an inferred type.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
mlir::ParseResult parseSwitchOpCases(mlir::OpAsmParser &parser, mlir::Type flagType, mlir::DenseIntElementsAttr &caseValues, mlir::SmallVectorImpl< mlir::Block * > &caseDestinations, mlir::SmallVectorImpl< mlir::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &caseOperands, mlir::SmallVectorImpl< mlir::SmallVector< mlir::Type > > &caseOperandTypes)
<cases> ::= [ (case (, case )* )?
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.
LogicalResult verifyCallOpInterface(CallOpInterface call, TypeRange argumentTypes, TypeRange resultTypes)
Verify that the forwarded operands and results of call are in a 1:1 relationship with the given argum...
void addArgAndResultAttrs(Builder &builder, OperationState &result, ArrayRef< DictionaryAttr > argAttrs, ArrayRef< DictionaryAttr > resultAttrs, StringAttr argAttrsName, StringAttr resAttrsName)
Adds argument and result attributes, provided as argAttrs and resultAttrs arguments,...
void walk(Operation *op, function_ref< void(Region *)> callback, WalkOrder order)
Walk all of the regions, blocks, or operations nested under (and including) the given operation.
ParseResult parseFunctionSignatureWithArguments(OpAsmParser &parser, bool allowVariadic, SmallVectorImpl< OpAsmParser::Argument > &arguments, bool &isVariadic, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses a function signature using parser.
void printFunctionAttributes(OpAsmPrinter &p, Operation *op, ArrayRef< StringRef > elided={})
Prints the list of function prefixed with the "attributes" keyword.
void printFunctionSignature(OpAsmPrinter &p, FunctionOpInterface op, ArrayRef< Type > argTypes, bool isVariadic, ArrayRef< Type > resultTypes)
Prints the signature of the function-like operation op.
Operation::operand_range getIndices(Operation *op)
Get the indices that the given load/store operation is operating on.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
detail::constant_int_value_binder m_ConstantInt(IntegerAttr::ValueType *bind_value)
Matches a constant holding a scalar/vector/tensor integer (splat) and writes the integer value to bin...
detail::DenseArrayAttrImpl< int64_t > DenseI64ArrayAttr
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
detail::constant_int_range_predicate_matcher m_IntRangeWithoutNegOneS()
Matches a constant scalar / vector splat / tensor splat integer or a signed integer range that does n...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
detail::DenseArrayAttrImpl< int32_t > DenseI32ArrayAttr
llvm::TypeSwitch< T, ResultT > TypeSwitch
detail::constant_int_range_predicate_matcher m_IntRangeWithoutZeroS()
Matches a constant scalar / vector splat / tensor splat integer or a signed integer range that does n...
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
llvm::function_ref< Fn > function_ref
detail::constant_int_range_predicate_matcher m_IntRangeWithoutZeroU()
Matches a constant scalar / vector splat / tensor splat integer or a unsigned integer range that does...
A callable is either a symbol, or an SSA value, that is referenced by a call-like operation.
This is the representation of an operand reference.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
OpRewritePattern(MLIRContext *context, PatternBenefit benefit=1, ArrayRef< StringRef > generatedNames={})
Patterns must specify the root operation name they match against, and can also specify the benefit of...
This represents an operation in an abstracted form, suitable for use with the builder APIs.
T & getOrAddProperties()
Get (or create) the properties of the provided type to be set on the operation on creation.
SmallVector< Value, 4 > operands
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addSuccessors(Block *successor)
Adds a successor to the operation sate. successor must not be null.