27#include "llvm/ADT/APFloat.h"
28#include "llvm/ADT/DenseSet.h"
29#include "llvm/ADT/STLExtras.h"
30#include "llvm/ADT/TypeSwitch.h"
31#include "llvm/IR/DataLayout.h"
32#include "llvm/Support/Error.h"
41using mlir::LLVM::cconv::getMaxEnumValForCConv;
42using mlir::LLVM::linkage::getMaxEnumValForLinkage;
43using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
45#include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
56 if (attr.
getName() ==
"fastmathFlags") {
76 << name <<
"' does not reference a valid LLVM function";
77 if (
func.isExternal())
78 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
96 for (
const auto &en : llvm::enumerate(keywords)) {
104template <
typename Ty>
107#define REGISTER_ENUM_TYPE(Ty) \
109 struct EnumTraits<Ty> { \
110 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
111 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
125template <
typename EnumTy,
typename RetTy = EnumTy>
127 EnumTy defaultValue) {
129 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
130 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
134 return static_cast<RetTy
>(defaultValue);
135 return static_cast<RetTy
>(
index);
139 p << stringifyLinkage(val.getLinkage());
143 val = LinkageAttr::get(
151 uint64_t alignment = 1) {
157 if (alignment == 1) {
164 builder.
getNamedAttr(LLVMDialect::getAlignAttrName(), alignmentAttr);
174 int pos = isExpandLoad ? 0 : 1;
176 {alignDictAttr, emptyDictAttr, emptyDictAttr})
178 {emptyDictAttr, alignDictAttr, emptyDictAttr});
190 if (!operands.empty()) {
193 llvm::interleaveComma(operandTypes, p);
202 std::optional<ArrayAttr> opBundleTags) {
203 if (opBundleOperands.empty())
205 assert(opBundleTags &&
"expect operand bundle tags");
208 llvm::interleaveComma(
209 llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
211 auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
229 return p.
emitError(currentParserLoc,
"expect operand bundle tag");
240 opBundleOperands.push_back(std::move(operands));
241 opBundleOperandTypes.push_back(std::move(types));
242 opBundleTags.push_back(StringAttr::get(p.
getContext(), tag));
259 auto bundleParser = [&] {
269 opBundleTags = ArrayAttr::get(p.
getContext(), opBundleTagAttrs);
279 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
280 <<
", " << getOperand(1);
282 p <<
" : " << getLhs().getType();
286 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
287 <<
", " << getOperand(1);
289 p <<
" : " << getLhs().getType();
296template <
typename CmpPredicateType>
298 StringAttr predicateAttr;
301 SMLoc predicateLoc, trailingTypeLoc;
314 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
315 std::optional<ICmpPredicate> predicate =
316 symbolizeICmpPredicate(predicateAttr.getValue());
319 <<
"'" << predicateAttr.getValue()
320 <<
"' is an incorrect value of the 'predicate' attribute";
321 predicateValue =
static_cast<int64_t>(*predicate);
323 std::optional<FCmpPredicate> predicate =
324 symbolizeFCmpPredicate(predicateAttr.getValue());
327 <<
"'" << predicateAttr.getValue()
328 <<
"' is an incorrect value of the 'predicate' attribute";
329 predicateValue =
static_cast<int64_t>(*predicate);
332 result.attributes.set(
"predicate",
339 "expected LLVM dialect-compatible type");
355 ShapedType shapedType = dyn_cast<ShapedType>(type);
362 if (getPredicate() != ICmpPredicate::eq &&
363 getPredicate() != ICmpPredicate::ne)
367 if (getLhs() == getRhs())
369 getPredicate() == ICmpPredicate::eq);
372 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
374 getPredicate() == ICmpPredicate::ne);
377 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
380 getLhsMutable().assign(
rhs);
381 getRhsMutable().assign(
lhs);
399 p <<
' ' << getArraySize() <<
" x " << getElemType();
400 if (getAlignment() && *getAlignment() != 0)
402 {kElemTypeAttrName, getInallocaAttrName()});
406 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
407 p <<
" : " << funcTy;
415 SMLoc trailingTypeLoc;
427 std::optional<NamedAttribute> alignmentAttr =
428 result.attributes.getNamed(
"alignment");
429 if (alignmentAttr.has_value()) {
430 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
433 "expected integer alignment");
434 if (alignmentInt.getValue().isZero())
435 result.attributes.erase(
"alignment");
439 auto funcType = llvm::dyn_cast<FunctionType>(type);
440 if (!funcType || funcType.getNumInputs() != 1 ||
441 funcType.getNumResults() != 1)
444 "expected trailing function type with one argument and one result");
449 Type resultType = funcType.getResult(0);
450 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
453 result.addTypes({funcType.getResult(0)});
457LogicalResult AllocaOp::verify() {
459 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
460 targetExtType && !targetExtType.supportsMemOps())
462 <<
"this target extension type cannot be used in alloca";
472 assert(
index == 0 &&
"invalid successor index");
481 assert(
index < getNumSuccessors() &&
"invalid successor index");
483 : getFalseDestOperandsMutable());
489 std::optional<std::pair<uint32_t, uint32_t>> weights) {
494 static_cast<int32_t
>(weights->second)});
496 build(builder,
result, condition, trueOperands, falseOperands, weightsAttr,
497 {}, trueDest, falseDest);
511 if (!branchWeights.empty())
514 build(builder,
result, value, defaultOperands, caseOperands, caseValues,
515 weightsAttr, defaultDestination, caseDestinations);
524 if (!caseValues.empty()) {
525 ShapedType caseValueType = VectorType::get(
530 build(builder,
result, value, defaultDestination, defaultOperands,
531 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
540 if (!caseValues.empty()) {
541 ShapedType caseValueType = VectorType::get(
546 build(builder,
result, value, defaultDestination, defaultOperands,
547 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
563 auto parseCase = [&]() {
567 values.push_back(APInt(bitWidth, value,
true));
580 caseDestinations.push_back(destination);
581 caseOperands.emplace_back(operands);
582 caseOperandTypes.emplace_back(operandTypes);
588 ShapedType caseValueType =
589 VectorType::get(
static_cast<int64_t>(values.size()), flagType);
608 llvm::zip(caseValues, caseDestinations),
623LogicalResult SwitchOp::verify() {
624 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
626 getCaseValues()->size() !=
627 static_cast<int64_t>(getCaseDestinations().size())))
628 return emitOpError(
"expects number of case values to match number of "
629 "case destinations");
630 if (getCaseValues() &&
632 return emitError(
"expects case value type to match condition value type");
637 assert(
index < getNumSuccessors() &&
"invalid successor index");
639 : getCaseOperandsMutable(
index - 1));
648 getDynamicIndices());
653 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
654 return vectorType.getElementType();
671 bool requiresConst = !rawConstantIndices.empty() &&
672 isa_and_nonnull<LLVMStructType>(currType);
673 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
677 rawConstantIndices.push_back(intC.getSExtValue());
679 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
680 dynamicIndices.push_back(val);
683 rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
688 if (rawConstantIndices.size() == 1 || !currType)
692 .Case<VectorType, LLVMArrayType>([](
auto containerType) {
693 return containerType.getElementType();
695 .Case([&](LLVMStructType structType) ->
Type {
696 int64_t memberIndex = rawConstantIndices.back();
697 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
698 structType.getBody().size())
699 return structType.getBody()[memberIndex];
708 GEPNoWrapFlags noWrapFlags,
714 result.addTypes(resultType);
715 result.addAttributes(attributes);
716 result.getOrAddProperties<Properties>().rawConstantIndices =
718 result.getOrAddProperties<Properties>().noWrapFlags = noWrapFlags;
719 result.getOrAddProperties<Properties>().elem_type =
720 TypeAttr::get(elementType);
721 result.addOperands(basePtr);
722 result.addOperands(dynamicIndices);
727 GEPNoWrapFlags noWrapFlags,
729 build(builder,
result, resultType, elementType, basePtr,
739 auto idxParser = [&]() -> ParseResult {
740 int32_t constantIndex;
744 if (failed(parsedInteger.
value()))
746 constantIndices.push_back(constantIndex);
750 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
764 llvm::interleaveComma(
767 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
770 printer << cast<IntegerAttr>(cst).getInt();
780 if (indexPos >=
indices.size())
785 .Case([&](LLVMStructType structType) -> LogicalResult {
786 auto attr = dyn_cast<IntegerAttr>(
indices[indexPos]);
788 return emitOpError() <<
"expected index " << indexPos
789 <<
" indexing a struct to be constant";
791 int32_t gepIndex = attr.getInt();
794 static_cast<size_t>(gepIndex) >= elementTypes.size())
796 <<
" indexing a struct is out of bounds";
803 .Case<VectorType, LLVMArrayType>(
804 [&](
auto containerType) -> LogicalResult {
808 .Default([&](
auto otherType) -> LogicalResult {
810 <<
"type " << otherType <<
" cannot be indexed (index #"
822LogicalResult LLVM::GEPOp::verify() {
823 if (
static_cast<size_t>(
824 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
825 getDynamicIndices().size())
826 return emitOpError(
"expected as many dynamic indices as specified in '")
827 << getRawConstantIndicesAttrName().getValue() <<
"'";
829 if (getNoWrapFlags() == GEPNoWrapFlags::inboundsFlag)
830 return emitOpError(
"'inbounds_flag' cannot be used directly.");
840void LoadOp::getEffects(
849 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
850 getOrdering() != AtomicOrdering::unordered)) {
861 if (!isa<IntegerType, LLVMPointerType>(type))
866 if (bitWidth.isScalable())
869 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
873template <
typename OpTy>
877 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
880 return memOp.emitOpError(
"unsupported type ")
881 << valueType <<
" for atomic access";
882 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
883 return memOp.emitOpError(
"unsupported ordering '")
884 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
885 if (!memOp.getAlignment())
886 return memOp.emitOpError(
"expected alignment for atomic access");
889 if (memOp.getSyncscope())
890 return memOp.emitOpError(
891 "expected syncscope to be null for non-atomic access");
895LogicalResult LoadOp::verify() {
896 Type valueType = getResult().getType();
898 {AtomicOrdering::release, AtomicOrdering::acq_rel});
902 Value addr,
unsigned alignment,
bool isVolatile,
903 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
904 AtomicOrdering ordering, StringRef syncscope) {
905 build(builder, state, type, addr,
907 isNonTemporal, isInvariant, isInvariantGroup, ordering,
908 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
919void StoreOp::getEffects(
928 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
929 getOrdering() != AtomicOrdering::unordered)) {
935LogicalResult StoreOp::verify() {
936 Type valueType = getValue().getType();
938 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
942 Value addr,
unsigned alignment,
bool isVolatile,
943 bool isNonTemporal,
bool isInvariantGroup,
944 AtomicOrdering ordering, StringRef syncscope) {
945 build(builder, state, value, addr,
947 isNonTemporal, isInvariantGroup, ordering,
948 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
950 nullptr,
nullptr,
nullptr);
960 Type resultType = calleeType.getReturnType();
961 if (!isa<LLVM::LLVMVoidType>(resultType))
962 results.push_back(resultType);
968 return calleeType.isVarArg() ? TypeAttr::get(calleeType) :
nullptr;
976 resultType = LLVMVoidType::get(context);
978 resultType = results.front();
979 return LLVMFunctionType::get(resultType, llvm::to_vector(args.
getTypes()),
985 build(builder, state, results, builder.
getStringAttr(callee), args);
990 build(builder, state, results, SymbolRefAttr::get(callee), args);
995 assert(callee &&
"expected non-null callee in direct call builder");
996 build(builder, state, results,
997 nullptr, callee, args,
nullptr,
1000 nullptr,
nullptr,
nullptr,
1001 nullptr,
nullptr,
nullptr,
1005 nullptr,
nullptr,
nullptr,
1019 LLVMFunctionType calleeType, StringRef callee,
1021 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1025 LLVMFunctionType calleeType, StringAttr callee,
1027 build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
1045 nullptr,
nullptr,
nullptr,
1053 nullptr,
nullptr,
nullptr,
1059 LLVMFunctionType calleeType,
ValueRange args) {
1064 nullptr,
nullptr,
nullptr,
1065 nullptr,
nullptr,
nullptr,
1071 nullptr,
nullptr,
nullptr,
1086 auto calleeType =
func.getFunctionType();
1090 nullptr,
nullptr,
nullptr,
1091 nullptr,
nullptr,
nullptr,
1097 nullptr,
nullptr,
nullptr,
1115 return getOperand(0);
1121 auto symRef = cast<SymbolRefAttr>(callee);
1122 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1125 return setOperand(0, cast<Value>(callee));
1130template <
typename OpTy>
1133 if (callOp.getCallee().has_value())
1140template <
typename OpTy>
1142 return callOp.getCalleeOperands().drop_front(
1154template <
typename OpTy>
1157 if (std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType())
1158 return operands.take_front(varCalleeType->getNumParams());
1175 if (callee.isExternal())
1177 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1181 auto hasSubprogram = [](
Operation *op) {
1186 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1188 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1190 return callOp.emitError()
1191 <<
"inlinable function call in a function with a DISubprogram "
1192 "location must have a debug location";
1198template <
typename OpTy>
1201 if (!callOp.getCallee().has_value() && callOp.getCalleeOperands().empty())
1202 return callOp.emitOpError(
1203 "must have either a `callee` attribute or at least an operand");
1205 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1210 if (!varCalleeType->isVarArg())
1211 return callOp.emitOpError(
1212 "expected var_callee_type to be a variadic function type");
1220 if (varCalleeType->getNumParams() > passedOperands.size())
1221 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1222 << passedOperands.size() <<
" parameters";
1225 for (
auto [paramType, operand] :
1226 llvm::zip(varCalleeType->getParams(), passedOperands))
1227 if (paramType != operand.getType())
1228 return callOp.emitOpError()
1229 <<
"var_callee_type parameter type mismatch: " << paramType
1230 <<
" != " << operand.getType();
1233 if (!callOp.getNumResults()) {
1234 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1235 return callOp.emitOpError(
"expected var_callee_type to return void");
1237 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1238 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1239 << varCalleeType->getReturnType()
1240 <<
" != " << callOp.getResult().getType();
1245template <
typename OpType>
1248 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1250 auto isStringAttr = [](
Attribute tagAttr) {
1251 return isa<StringAttr>(tagAttr);
1253 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1254 return op.emitError(
"operand bundle tag must be a StringAttr");
1256 size_t numOpBundles = opBundleOperands.size();
1257 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1258 if (numOpBundles != numOpBundleTags)
1259 return op.emitError(
"expected ")
1260 << numOpBundles <<
" operand bundle tags, but actually got "
1281 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1283 return emitOpError(
"indirect call expects a pointer as callee: ")
1284 << getOperand(0).getType();
1294 <<
"' does not reference a symbol in the current scope";
1295 if (
auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1298 fnType = fn.getFunctionType();
1299 }
else if (
auto ifunc = dyn_cast<IFuncOp>(callee)) {
1300 fnType = ifunc.getIFuncType();
1301 }
else if (isa<AliasOp>(callee)) {
1305 fnType = getCalleeFunctionType();
1309 <<
"' does not reference a valid LLVM function, IFunc, or alias";
1313 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1315 return emitOpError(
"callee does not have a functional type: ") << fnType;
1317 if (funcType.isVarArg() && !getVarCalleeType())
1318 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1322 if (getNumResults() == 0 &&
1323 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1324 return emitOpError() <<
"expected function call to produce a value";
1326 if (getNumResults() != 0 &&
1327 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1329 <<
"calling function with void result must not produce values";
1331 if (getNumResults() > 1)
1333 <<
"expected LLVM function call to produce 0 or 1 result";
1335 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1336 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1337 <<
" != " << funcType.getReturnType();
1343 if (!llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1344 calleeResultTypes.push_back(funcType.getReturnType());
1350 auto callee = getCallee();
1351 bool isDirect = callee.has_value();
1356 if (getCConv() != LLVM::CConv::C)
1357 p << stringifyCConv(getCConv()) <<
' ';
1359 if (getTailCallKind() != LLVM::TailCallKind::None)
1360 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1369 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1370 p <<
'(' << args <<
')';
1373 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1374 p <<
" vararg(" << *varCalleeType <<
")";
1376 if (!getOpBundleOperands().empty()) {
1379 getOpBundleOperands().getTypes(), getOpBundleTags());
1383 {getCalleeAttrName(), getTailCallKindAttrName(),
1384 getVarCalleeTypeAttrName(), getCConvAttrName(),
1385 getOperandSegmentSizesAttrName(),
1386 getOpBundleSizesAttrName(),
1387 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1388 getResAttrsAttrName()});
1392 p << getOperand(0).getType() <<
", ";
1396 p, args.getTypes(), getArgAttrsAttr(),
1397 false, getResultTypes(), getResAttrsAttr());
1412 types.emplace_back();
1417 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1422 resTypes, resultAttrs)) {
1424 return parser.
emitError(trailingTypesLoc,
1425 "expected direct call to have 1 trailing types");
1426 return parser.
emitError(trailingTypesLoc,
1427 "expected trailing function type");
1430 if (resTypes.size() > 1)
1431 return parser.
emitError(trailingTypesLoc,
1432 "expected function with 0 or 1 result");
1433 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1434 return parser.
emitError(trailingTypesLoc,
1435 "expected a non-void result type");
1441 llvm::append_range(types, argTypes);
1445 if (!resTypes.empty())
1446 result.addTypes(resTypes);
1459 if (failed(*parseResult))
1460 return *parseResult;
1461 operands.push_back(funcPtrOperand);
1470 StringAttr opBundleSizesAttrName) {
1471 unsigned opBundleIndex = 0;
1472 for (
const auto &[operands, types] :
1473 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1474 if (operands.size() != types.size())
1475 return parser.
emitError(loc,
"expected ")
1477 <<
" types for operand bundle operands for operand bundle #"
1478 << opBundleIndex <<
", but actually got " << types.size();
1484 opBundleSizes.reserve(opBundleOperands.size());
1485 for (
const auto &operands : opBundleOperands)
1486 opBundleSizes.push_back(operands.size());
1489 opBundleSizesAttrName,
1501 SymbolRefAttr funcAttr;
1502 TypeAttr varCalleeType;
1510 getCConvAttrName(
result.name),
1515 getTailCallKindAttrName(
result.name),
1518 parser, LLVM::TailCallKind::None)));
1523 bool isDirect = operands.empty();
1536 StringAttr varCalleeTypeAttrName =
1537 CallOp::getVarCalleeTypeAttrName(
result.name);
1549 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1552 if (opBundleTags && !opBundleTags.empty())
1553 result.addAttribute(CallOp::getOpBundleTagsAttrName(
result.name).getValue(),
1563 argAttrs, resultAttrs))
1567 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1569 opBundleOperandTypes,
1570 getOpBundleSizesAttrName(
result.name)))
1573 int32_t numOpBundleOperands = 0;
1574 for (
const auto &operands : opBundleOperands)
1575 numOpBundleOperands += operands.size();
1578 CallOp::getOperandSegmentSizeAttr(),
1580 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1584LLVMFunctionType CallOp::getCalleeFunctionType() {
1585 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1586 return *varCalleeType;
1597 auto calleeType =
func.getFunctionType();
1600 nullptr,
nullptr, normalOps, unwindOps,
1601 nullptr,
nullptr,
nullptr, {}, {}, normal,
1609 build(builder, state, tys,
1610 nullptr, callee, ops,
nullptr,
1611 nullptr, normalOps, unwindOps,
nullptr,
nullptr,
1612 nullptr, {}, {}, normal, unwind);
1621 nullptr,
nullptr, normalOps, unwindOps,
1622 nullptr,
nullptr,
nullptr, {}, {}, normal,
1627 assert(
index < getNumSuccessors() &&
"invalid successor index");
1629 : getUnwindDestOperandsMutable());
1637 return getOperand(0);
1643 auto symRef = cast<SymbolRefAttr>(callee);
1644 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1647 return setOperand(0, cast<Value>(callee));
1659LogicalResult InvokeOp::verify() {
1663 Block *unwindDest = getUnwindDest();
1664 if (unwindDest->
empty())
1665 return emitError(
"must have at least one operation in unwind destination");
1668 if (!isa<LandingpadOp>(unwindDest->
front()))
1669 return emitError(
"first operation in unwind destination should be a "
1670 "llvm.landingpad operation");
1679 auto callee = getCallee();
1680 bool isDirect = callee.has_value();
1685 if (getCConv() != LLVM::CConv::C)
1686 p << stringifyCConv(getCConv()) <<
' ';
1694 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1701 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1702 p <<
" vararg(" << *varCalleeType <<
")";
1704 if (!getOpBundleOperands().empty()) {
1707 getOpBundleOperands().getTypes(), getOpBundleTags());
1711 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1712 getCConvAttrName(), getVarCalleeTypeAttrName(),
1713 getOpBundleSizesAttrName(),
1714 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1715 getResAttrsAttrName()});
1719 p << getOperand(0).getType() <<
", ";
1721 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1723 false, getResultTypes(), getResAttrsAttr());
1736 SymbolRefAttr funcAttr;
1737 TypeAttr varCalleeType;
1741 Block *normalDest, *unwindDest;
1747 getCConvAttrName(
result.name),
1754 bool isDirect = operands.empty();
1770 StringAttr varCalleeTypeAttrName =
1771 InvokeOp::getVarCalleeTypeAttrName(
result.name);
1783 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1786 if (opBundleTags && !opBundleTags.empty())
1788 InvokeOp::getOpBundleTagsAttrName(
result.name).getValue(),
1798 argAttrs, resultAttrs))
1802 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1805 opBundleOperandTypes,
1806 getOpBundleSizesAttrName(
result.name)))
1809 result.addSuccessors({normalDest, unwindDest});
1810 result.addOperands(normalOperands);
1811 result.addOperands(unwindOperands);
1813 int32_t numOpBundleOperands = 0;
1814 for (
const auto &operands : opBundleOperands)
1815 numOpBundleOperands += operands.size();
1818 InvokeOp::getOperandSegmentSizeAttr(),
1820 static_cast<int32_t>(normalOperands.size()),
1821 static_cast<int32_t>(unwindOperands.size()),
1822 numOpBundleOperands}));
1826LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1827 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1828 return *varCalleeType;
1836LogicalResult LandingpadOp::verify() {
1838 if (LLVMFuncOp
func = (*this)->getParentOfType<LLVMFuncOp>()) {
1839 if (!
func.getPersonality())
1841 "llvm.landingpad needs to be in a function with a personality");
1847 if (!getCleanup() && getOperands().empty())
1848 return emitError(
"landingpad instruction expects at least one clause or "
1849 "cleanup attribute");
1851 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1852 value = getOperand(idx);
1853 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1860 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1863 <<
"global addresses expected as operand to "
1864 "bitcast used in clauses for landingpad";
1872 << idx <<
" is not a known constant - null, addressof, bitcast";
1879 p << (getCleanup() ?
" cleanup " :
" ");
1882 for (
auto value : getOperands()) {
1885 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1886 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1933 Type llvmType = containerType;
1935 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1943 for (
int64_t idx : position) {
1944 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1945 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1946 emitError(
"position out of bounds: ") << idx;
1949 llvmType = arrayType.getElementType();
1950 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1952 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1953 emitError(
"position out of bounds: ") << idx;
1956 llvmType = structType.getBody()[idx];
1958 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1969 for (
int64_t idx : position) {
1970 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1971 llvmType = structType.getBody()[idx];
1973 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1985 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
1986 ShapedType shapedType = elementsAttr.getShapedType();
1987 if (!shapedType.hasRank() || shapedType.getRank() != 1)
1989 if (
index <
static_cast<size_t>(elementsAttr.getNumElements()))
1993 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
1994 if (
index < arrayAttr.getValue().size())
1995 return arrayAttr[
index];
1998 if (isa<ZeroAttr, UndefAttr, PoisonAttr>(attr))
2003OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
2004 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
2006 newPos.append(getPosition().begin(), getPosition().end());
2007 setPosition(newPos);
2008 getContainerMutable().set(extractValueOp.getContainer());
2014 for (
int64_t pos : getPosition()) {
2019 return containerAttr;
2022 Value container = getContainer();
2024 while (
auto insertValueOp = container.
getDefiningOp<InsertValueOp>()) {
2026 auto extractPosSize = extractPos.size();
2027 auto insertPosSize = insertPos.size();
2030 if (extractPos == insertPos)
2031 return insertValueOp.getValue();
2045 if (extractPosSize > insertPosSize &&
2046 extractPos.take_front(insertPosSize) == insertPos) {
2047 container = insertValueOp.getValue();
2048 extractPos = extractPos.drop_front(insertPosSize);
2064 if (insertPosSize > extractPosSize &&
2065 extractPos == insertPos.take_front(extractPosSize))
2070 container = insertValueOp.getContainer();
2076 if (container == getContainer())
2078 setPosition(extractPos);
2079 getContainerMutable().assign(container);
2083LogicalResult ExtractValueOp::verify() {
2090 if (getRes().
getType() != valueType)
2091 return emitOpError() <<
"Type mismatch: extracting from "
2092 << getContainer().getType() <<
" should produce "
2093 << valueType <<
" but this op returns "
2094 << getRes().getType();
2100 build(builder, state,
2139 LogicalResult matchAndRewrite(InsertValueOp insertOp,
2140 PatternRewriter &rewriter)
const override {
2141 bool changed =
false;
2147 auto insertBaseIdx = insertOp.getPosition()[0];
2148 for (
auto &use : insertOp->getUses()) {
2149 if (
auto extractOp = dyn_cast<ExtractValueOp>(use.getOwner())) {
2150 auto baseIdx = extractOp.getPosition()[0];
2153 if (baseIdx == insertBaseIdx)
2155 posToExtractOps[baseIdx].push_back(extractOp);
2160 Value nextContainer = insertOp.getContainer();
2161 while (!posToExtractOps.empty()) {
2163 dyn_cast_or_null<InsertValueOp>(nextContainer.
getDefiningOp());
2166 nextContainer = curInsert.getContainer();
2169 auto curInsertBaseIdx = curInsert.getPosition()[0];
2170 auto it = posToExtractOps.find(curInsertBaseIdx);
2171 if (it == posToExtractOps.end())
2175 for (
auto &extractOp : it->second) {
2177 extractOp.getContainerMutable().assign(curInsert);
2182 assert(!it->second.empty());
2184 posToExtractOps.erase(it);
2188 for (
auto &[baseIdx, extracts] : posToExtractOps) {
2189 for (
auto &extractOp : extracts) {
2191 extractOp.getContainerMutable().assign(nextContainer);
2194 assert(!extracts.empty() &&
"Empty list in map");
2204 patterns.
add<ResolveExtractValueSource>(context);
2213 [&](StringRef msg) {
2226LogicalResult InsertValueOp::verify() {
2233 if (getValue().
getType() != valueType)
2234 return emitOpError() <<
"Type mismatch: cannot insert "
2235 << getValue().getType() <<
" into "
2236 << getContainer().getType();
2245LogicalResult ReturnOp::verify() {
2246 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2250 Type expectedType = parent.getFunctionType().getReturnType();
2251 if (llvm::isa<LLVMVoidType>(expectedType)) {
2255 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2259 if (llvm::isa<LLVMVoidType>(expectedType))
2262 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2265 if (expectedType != getArg().
getType()) {
2267 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2278 return dyn_cast_or_null<GlobalOp>(
2283 return dyn_cast_or_null<LLVMFuncOp>(
2288 return dyn_cast_or_null<AliasOp>(
2293 return dyn_cast_or_null<IFuncOp>(
2302 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2303 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2304 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2305 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2307 if (!global && !function && !alias && !ifunc)
2308 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2309 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2311 LLVMPointerType type =
getType();
2312 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2313 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2314 return emitOpError(
"pointer address space must match address space of the "
2315 "referenced global or alias");
2322 return getGlobalNameAttr();
2343 getFunctionNameAttr());
2344 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2345 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2347 if (!function && !alias)
2349 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2352 if (alias.getInitializer()
2353 .walk([&](AddressOfOp addrOp) {
2354 if (addrOp.getGlobal(symbolTable))
2355 return WalkResult::interrupt();
2356 return WalkResult::advance();
2359 return emitOpError(
"must reference an alias to a function");
2362 if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2363 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2365 "target function with 'extern_weak' linkage not allowed");
2373 return DSOLocalEquivalentAttr::get(
getContext(), getFunctionNameAttr());
2381 StringRef symName) {
2384 Region *body =
result.addRegion();
2388LogicalResult ComdatOp::verifyRegions() {
2389 Region &body = getBody();
2390 for (Operation &op : body.
getOps())
2391 if (!isa<ComdatSelectorOp>(op))
2392 return op.emitError(
2393 "only comdat selector symbols can appear in a comdat region");
2403 bool isConstant, Linkage linkage, StringRef name,
2404 Attribute value, uint64_t alignment,
unsigned addrSpace,
2405 bool dsoLocal, ThreadLocalMode threadModel,
2410 result.addAttribute(getGlobalTypeAttrName(
result.name), TypeAttr::get(type));
2412 getTlsModeAttrName(
result.name),
2413 ThreadLocalModeAttr::get(builder.
getContext(), threadModel));
2418 result.addAttribute(getValueAttrName(
result.name), value);
2423 result.addAttribute(getComdatAttrName(
result.name), comdat);
2433 LinkageAttr::get(builder.
getContext(), linkage));
2437 result.attributes.append(attrs.begin(), attrs.end());
2439 if (!dbgExprs.empty())
2441 ArrayAttr::get(builder.
getContext(), dbgExprs));
2446template <
typename OpType>
2448 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2449 StringRef visibility = stringifyVisibility(op.getVisibility_());
2450 if (!visibility.empty())
2451 p << visibility <<
' ';
2453 if (ThreadLocalMode mode = op.getTlsMode();
2454 mode != ThreadLocalMode::NotThreadLocal) {
2455 p <<
"thread_local";
2456 if (mode != ThreadLocalMode::GeneralDynamic)
2457 p <<
'(' << mode <<
')';
2461 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2462 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2474 if (
auto value = getValueOrNull())
2477 if (
auto comdat = getComdat())
2478 p <<
" comdat(" << *comdat <<
')';
2484 {SymbolTable::getSymbolAttrName(),
2485 getGlobalTypeAttrName(), getConstantAttrName(),
2486 getValueAttrName(), getLinkageAttrName(),
2487 getUnnamedAddrAttrName(), getTlsModeAttrName(),
2488 getVisibility_AttrName(), getComdatAttrName()});
2491 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2495 Region &initializer = getInitializerRegion();
2496 if (!initializer.
empty()) {
2503 std::optional<SymbolRefAttr> attr) {
2508 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2509 return op->
emitError() <<
"expected comdat symbol";
2519 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2520 if (blockTags.contains(blockTagOp.getTag())) {
2521 blockTagOp.emitError()
2522 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2523 <<
"' in the same function: ";
2526 blockTags.insert(blockTagOp.getTag());
2535template <
typename OpType>
2541 OpType::getLinkageAttrName(
result.name),
2543 parser, LLVM::Linkage::External)));
2546 result.addAttribute(OpType::getVisibility_AttrName(
result.name),
2549 parser, LLVM::Visibility::Default)));
2552 ThreadLocalMode threadModel = ThreadLocalMode::GeneralDynamic;
2559 parser, ThreadLocalMode::NotThreadLocal);
2560 if (threadModel == ThreadLocalMode::NotThreadLocal) {
2561 parser.
emitError(kwLoc,
"invalid value for thread_local");
2567 result.addAttribute(OpType::getTlsModeAttrName(
result.name),
2568 ThreadLocalModeAttr::get(ctx, threadModel));
2572 result.addAttribute(OpType::getUnnamedAddrAttrName(
result.name),
2575 parser, LLVM::UnnamedAddr::None)));
2613 SymbolRefAttr comdat;
2618 result.addAttribute(getComdatAttrName(
result.name), comdat);
2626 if (types.size() > 1)
2630 if (types.empty()) {
2631 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2633 auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2634 strAttr.getValue().size());
2635 types.push_back(arrayType);
2638 "type can only be omitted for string globals");
2648 result.addAttribute(getGlobalTypeAttrName(
result.name),
2649 TypeAttr::get(types[0]));
2654 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2655 return intValue.getValue().isZero();
2656 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2657 return fpValue.getValue().isZero();
2658 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2660 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2662 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2667LogicalResult GlobalOp::verify() {
2669 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2671 :
llvm::isa<PointerElementTypeInterface>(
getType());
2674 "expects type to be a valid element type for an LLVM global");
2676 return emitOpError(
"must appear at the module level");
2678 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2679 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2680 IntegerType elementType =
2681 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) :
nullptr;
2682 if (!elementType || elementType.getWidth() != 8 ||
2683 type.getNumElements() != strAttr.getValue().size())
2685 "requires an i8 array type of the length equal to that of the string "
2689 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2690 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2692 <<
"this target extension type cannot be used in a global";
2695 return emitOpError() <<
"global with target extension type can only be "
2696 "initialized with zero-initializer";
2699 if (getLinkage() == Linkage::Common) {
2700 if (
Attribute value = getValueOrNull()) {
2703 <<
"expected zero value for '"
2704 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2709 if (getLinkage() == Linkage::Appending) {
2710 if (!llvm::isa<LLVMArrayType>(
getType())) {
2711 return emitOpError() <<
"expected array type for '"
2712 << stringifyLinkage(Linkage::Appending)
2720 std::optional<uint64_t> alignAttr = getAlignment();
2721 if (alignAttr.has_value()) {
2722 uint64_t value = alignAttr.value();
2723 if (!llvm::isPowerOf2_64(value))
2724 return emitError() <<
"alignment attribute is not a power of 2";
2730LogicalResult GlobalOp::verifyRegions() {
2731 if (
Block *
b = getInitializerBlock()) {
2732 ReturnOp ret = cast<ReturnOp>(
b->getTerminator());
2733 if (ret.operand_type_begin() == ret.operand_type_end())
2734 return emitOpError(
"initializer region cannot return void");
2735 if (*ret.operand_type_begin() !=
getType())
2737 << *ret.operand_type_begin() <<
" does not match global type "
2741 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2742 if (!iface || !iface.hasNoEffect())
2743 return op.emitError()
2744 <<
"ops with side effects not allowed in global initializers";
2747 if (getValueOrNull())
2748 return emitOpError(
"cannot have both initializer value and region");
2763 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2766 return op->
emitError(
"data element must be symbol or #llvm.zero");
2779LogicalResult GlobalCtorsOp::verify() {
2783 if (getCtors().size() == getPriorities().size() &&
2784 getCtors().size() == getData().size())
2787 "ctors, priorities, and data must have the same number of elements");
2804LogicalResult GlobalDtorsOp::verify() {
2808 if (getDtors().size() == getPriorities().size() &&
2809 getDtors().size() == getData().size())
2812 "dtors, priorities, and data must have the same number of elements");
2820 Linkage linkage, StringRef name,
bool dsoLocal,
2821 ThreadLocalMode threadModel,
2825 result.addAttribute(getAliasTypeAttrName(
result.name), TypeAttr::get(type));
2827 getTlsModeAttrName(
result.name),
2828 ThreadLocalModeAttr::get(builder.
getContext(), threadModel));
2834 LinkageAttr::get(builder.
getContext(), linkage));
2835 result.attributes.append(attrs.begin(), attrs.end());
2845 {SymbolTable::getSymbolAttrName(),
2846 getAliasTypeAttrName(), getLinkageAttrName(),
2847 getUnnamedAddrAttrName(), getTlsModeAttrName(),
2848 getVisibility_AttrName()});
2851 p <<
" : " <<
getType() <<
' ';
2877 if (types.size() > 1)
2885 TypeAttr::get(types[0]));
2889LogicalResult AliasOp::verify() {
2891 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2893 :
llvm::isa<PointerElementTypeInterface>(
getType());
2896 "expects type to be a valid element type for an LLVM global alias");
2899 switch (getLinkage()) {
2900 case Linkage::External:
2901 case Linkage::Internal:
2902 case Linkage::Private:
2904 case Linkage::WeakODR:
2905 case Linkage::Linkonce:
2906 case Linkage::LinkonceODR:
2907 case Linkage::AvailableExternally:
2911 <<
"'" << stringifyLinkage(getLinkage())
2912 <<
"' linkage not supported in aliases, available options: private, "
2913 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2914 "available_externally";
2920LogicalResult AliasOp::verifyRegions() {
2921 Block &
b = getInitializerBlock();
2922 auto ret = cast<ReturnOp>(
b.getTerminator());
2923 if (ret.getNumOperands() == 0 ||
2924 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2925 return emitOpError(
"initializer region must always return a pointer");
2928 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2929 if (!iface || !iface.hasNoEffect())
2930 return op.emitError()
2931 <<
"ops with side effects are not allowed in alias initializers";
2937unsigned AliasOp::getAddrSpace() {
2938 Block &initializer = getInitializerBlock();
2940 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2941 return ptrTy.getAddressSpace();
2949 Type iFuncType, StringRef resolverName,
Type resolverType,
2950 Linkage linkage, LLVM::Visibility visibility) {
2951 return build(builder,
result, name, iFuncType, resolverName, resolverType,
2953 UnnamedAddr::None, visibility);
2960 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2961 auto alias = dyn_cast<AliasOp>(symbol);
2963 Block &initBlock = alias.getInitializerBlock();
2965 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
2972 resolver = addrOp.getFunction(symbolTable);
2973 alias = addrOp.getAlias(symbolTable);
2976 return emitOpError(
"must have a function resolver");
2977 Linkage linkage = resolver.getLinkage();
2978 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
2979 return emitOpError(
"resolver must be a definition");
2980 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
2981 return emitOpError(
"resolver must return a pointer");
2982 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
2983 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
2984 return emitOpError(
"resolver has incorrect type");
2988LogicalResult IFuncOp::verify() {
2989 switch (getLinkage()) {
2990 case Linkage::External:
2991 case Linkage::Internal:
2992 case Linkage::Private:
2994 case Linkage::WeakODR:
2995 case Linkage::Linkonce:
2996 case Linkage::LinkonceODR:
2999 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
3000 <<
"' linkage not supported in ifuncs, available "
3001 "options: private, internal, linkonce, weak, "
3002 "linkonce_odr, weak_odr, or external linkage";
3014 auto containerType = v1.
getType();
3018 build(builder, state, vType, v1, v2, mask);
3032 "expected an LLVM compatible vector type");
3043LogicalResult ShuffleVectorOp::verify() {
3045 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
3046 return emitOpError(
"expected a splat operation for scalable vectors");
3052OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
3054 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
3055 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
3059 if (getMask().size() != 1 || getMask()[0] != 0)
3070 assert(empty() &&
"function already has an entry block");
3075 LLVMFunctionType type = getFunctionType();
3076 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
3077 entry->
addArgument(type.getParamType(i), getLoc());
3082 StringRef name,
Type type, LLVM::Linkage linkage,
3083 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
3086 std::optional<uint64_t> functionEntryCount) {
3090 result.addAttribute(getFunctionTypeAttrName(
result.name),
3091 TypeAttr::get(type));
3093 LinkageAttr::get(builder.
getContext(), linkage));
3095 CConvAttr::get(builder.
getContext(), cconv));
3096 result.attributes.append(attrs.begin(), attrs.end());
3101 result.addAttribute(getComdatAttrName(
result.name), comdat);
3102 if (functionEntryCount)
3103 result.addAttribute(getFunctionEntryCountAttrName(
result.name),
3104 FunctionEntryCountAttr::get(
3108 std::optional<NamedAttribute> duplicate =
result.attributes.findDuplicate();
3109 if (duplicate.has_value()) {
3110 llvm::report_fatal_error(
3111 Twine(
"LLVMFuncOp propagated an attribute that is meant "
3112 "to be constructed by the builder: ") +
3113 duplicate->getName().str());
3116 if (argAttrs.empty())
3119 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
3120 "expected as many argument attribute lists as arguments");
3122 builder,
result, argAttrs, {},
3123 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3134 if (outputs.size() > 1) {
3135 parser.
emitError(loc,
"failed to construct function type: expected zero or "
3136 "one function result");
3142 for (
auto t : inputs) {
3144 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3145 "type for function arguments");
3148 llvmInputs.push_back(t);
3153 outputs.empty() ? LLVMVoidType::get(
b.getContext()) : outputs.front();
3155 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3156 "type for function results")
3160 return LLVMFunctionType::get(llvmOutput, llvmInputs,
3176 parser, LLVM::Linkage::External)));
3179 result.addAttribute(getVisibility_AttrName(
result.name),
3182 parser, LLVM::Visibility::Default)));
3185 result.addAttribute(getUnnamedAddrAttrName(
result.name),
3188 parser, LLVM::UnnamedAddr::None)));
3192 getCConvAttrName(
result.name),
3196 StringAttr nameAttr;
3206 parser,
true, entryArgs, isVariadic, resultTypes,
3211 for (
auto &arg : entryArgs)
3212 argTypes.push_back(arg.type);
3218 result.addAttribute(getFunctionTypeAttrName(
result.name),
3219 TypeAttr::get(type));
3227 auto intTy = IntegerType::get(parser.
getContext(), 32);
3229 getVscaleRangeAttrName(
result.name),
3230 LLVM::VScaleRangeAttr::get(parser.
getContext(),
3231 IntegerAttr::get(intTy, minRange),
3232 IntegerAttr::get(intTy, maxRange)));
3236 SymbolRefAttr comdat;
3241 result.addAttribute(getComdatAttrName(
result.name), comdat);
3248 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3250 auto *body =
result.addRegion();
3261 if (getLinkage() != LLVM::Linkage::External)
3262 p << stringifyLinkage(getLinkage()) <<
' ';
3263 StringRef visibility = stringifyVisibility(getVisibility_());
3264 if (!visibility.empty())
3265 p << visibility <<
' ';
3266 if (
auto unnamedAddr = getUnnamedAddr()) {
3267 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3271 if (getCConv() != LLVM::CConv::C)
3272 p << stringifyCConv(getCConv()) <<
' ';
3276 LLVMFunctionType fnType = getFunctionType();
3279 argTypes.reserve(fnType.getNumParams());
3280 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3281 argTypes.push_back(fnType.getParamType(i));
3283 Type returnType = fnType.getReturnType();
3284 if (!llvm::isa<LLVMVoidType>(returnType))
3285 resTypes.push_back(returnType);
3288 isVarArg(), resTypes);
3291 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3292 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3293 << vscale->getMaxRange().getInt() <<
')';
3296 if (
auto comdat = getComdat())
3297 p <<
" comdat(" << *comdat <<
')';
3301 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3302 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3303 getComdatAttrName(), getUnnamedAddrAttrName(),
3304 getVscaleRangeAttrName()});
3307 Region &body = getBody();
3308 if (!body.empty()) {
3319LogicalResult LLVMFuncOp::verify() {
3320 if (getLinkage() == LLVM::Linkage::Common)
3322 << stringifyLinkage(LLVM::Linkage::Common)
3329 if (getLinkage() != LLVM::Linkage::External &&
3330 getLinkage() != LLVM::Linkage::ExternWeak)
3331 return emitOpError() <<
"external functions must have '"
3332 << stringifyLinkage(LLVM::Linkage::External)
3334 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3340 if (isNoInline() && isAlwaysInline())
3341 return emitError(
"no_inline and always_inline attributes are incompatible");
3343 if (isOptimizeNone() && !isNoInline())
3344 return emitOpError(
"with optimize_none must also be no_inline");
3346 Type landingpadResultTy;
3347 StringRef diagnosticMessage;
3348 bool isLandingpadTypeConsistent =
3350 const auto checkType = [&](
Type type, StringRef errorMessage) {
3351 if (!landingpadResultTy) {
3352 landingpadResultTy = type;
3355 if (landingpadResultTy != type) {
3356 diagnosticMessage = errorMessage;
3362 .Case([&](LandingpadOp landingpad) {
3363 constexpr StringLiteral errorMessage =
3364 "'llvm.landingpad' should have a consistent result type "
3365 "inside a function";
3366 return checkType(landingpad.getType(), errorMessage);
3368 .Case([&](ResumeOp resume) {
3369 constexpr StringLiteral errorMessage =
3370 "'llvm.resume' should have a consistent input type inside a "
3372 return checkType(resume.getValue().getType(), errorMessage);
3375 }).wasInterrupted();
3376 if (!isLandingpadTypeConsistent) {
3377 assert(!diagnosticMessage.empty() &&
3378 "Expecting a non-empty diagnostic message");
3390LogicalResult LLVMFuncOp::verifyRegions() {
3394 unsigned numArguments = getFunctionType().getNumParams();
3395 Block &entryBlock = front();
3396 for (
unsigned i = 0; i < numArguments; ++i) {
3400 << i <<
" is not of LLVM type";
3406Region *LLVMFuncOp::getCallableRegion() {
3435OpFoldResult LLVM::MetadataAsValueOp::fold(FoldAdaptor) {
3436 return getMetadataAttr();
3443LogicalResult LLVM::ZeroOp::verify() {
3444 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3445 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3447 <<
"target extension type does not support zero-initializer";
3469 if (
auto vecType = dyn_cast<VectorType>(t)) {
3470 assert(!vecType.isScalable() &&
3471 "number of elements of a scalable vector type is unknown");
3472 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3474 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3475 return arrayType.getNumElements() *
3483 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3484 type = arrayType.getElementType();
3485 if (
auto vecType = dyn_cast<VectorType>(type))
3486 return vecType.getElementType();
3487 if (
auto tenType = dyn_cast<TensorType>(type))
3488 return tenType.getElementType();
3495 if (
auto vecType = dyn_cast<VectorType>(t)) {
3496 if (vecType.isScalable())
3500 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3508 LLVM::LLVMArrayType arrayType,
3510 if (arrayType.getNumElements() != arrayAttr.size())
3511 return op.emitOpError()
3512 <<
"array attribute size does not match array type size in "
3514 << dim <<
": " << arrayAttr.size() <<
" vs. "
3515 << arrayType.getNumElements();
3520 if (
auto subArrayType =
3521 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3522 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3523 if (elementsVerified.insert(elementAttr).second) {
3524 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3526 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3528 return op.emitOpError()
3529 <<
"nested attribute for sub-array in dimension " << dim
3530 <<
" at index " << idx
3531 <<
" must be a zero, or undef, or array attribute";
3545 Type elementType = arrayType.getElementType();
3546 if (isa<LLVM::LLVMPointerType>(elementType)) {
3547 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3549 LLVM::PoisonAttr>(elementAttr))
3551 return op.emitOpError()
3552 <<
"pointer array element at index " << idx
3553 <<
" must be a flat symbol reference, zero, undef, or poison";
3557 auto structType = dyn_cast<LLVM::LLVMStructType>(elementType);
3559 return op.emitOpError() <<
"for array with an array attribute must have a "
3560 "struct element type";
3564 size_t numStructElements = structType.getBody().size();
3565 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3566 if (elementsVerified.insert(elementAttr).second) {
3567 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3569 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3571 return op.emitOpError()
3572 <<
"nested attribute for struct element at index " << idx
3573 <<
" must be a zero, or undef, or array attribute";
3574 if (subArrayAttr.size() != numStructElements)
3575 return op.emitOpError()
3576 <<
"nested array attribute size for struct element at index "
3577 << idx <<
" must match struct size: " << subArrayAttr.size()
3578 <<
" vs. " << numStructElements;
3585LogicalResult LLVM::ConstantOp::verify() {
3586 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3587 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3588 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3589 !arrayType.getElementType().isInteger(8)) {
3591 << sAttr.getValue().size()
3592 <<
" i8 elements for the string constant";
3596 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3597 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3599 return emitOpError() <<
"expected array attribute for struct type";
3602 if (arrayAttr.size() != elementTypes.size()) {
3603 return emitOpError() <<
"expected array attribute of size "
3604 << elementTypes.size();
3606 for (
auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3608 return emitOpError() <<
"expected struct element types to be floating "
3609 "point type or integer type";
3611 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3612 return emitOpError() <<
"expected element of array attribute to be "
3613 "floating point or integer";
3615 if (cast<TypedAttr>(attr).
getType() != type)
3617 <<
"struct element at index " << i <<
" is of wrong type";
3622 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3623 return emitOpError() <<
"does not support target extension type.";
3634 auto verifyFloatSemantics =
3635 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3636 Type constantElementType) -> LogicalResult {
3637 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3638 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3640 <<
"attribute and type have different float semantics";
3644 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3645 if (isa<IntegerType>(constantElementType)) {
3646 if (!constantElementType.isInteger(floatWidth))
3647 return emitOpError() <<
"expected integer type of width " << floatWidth;
3655 if (isa<IntegerAttr>(getValue())) {
3656 if (!llvm::isa<IntegerType>(
getType()))
3658 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3659 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3660 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3664 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3665 if (!splatElementsAttr)
3667 <<
"scalable vector type requires a splat attribute";
3670 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3671 return emitOpError() <<
"expected vector or array type";
3674 int64_t attrNumElements = elementsAttr.getNumElements();
3677 <<
"type and attribute have a different number of elements: "
3683 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3684 return verifyFloatSemantics(floatType.getFloatSemantics(), resultElmType);
3686 if (isa<IntegerType>(attrElmType) && !isa<IntegerType>(resultElmType)) {
3688 "expected integer element type for integer elements attribute");
3690 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3693 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3696 <<
"expected array or struct type for array attribute";
3703 <<
"only supports integer, float, string or elements attributes";
3709bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3711 auto typedAttr = dyn_cast<TypedAttr>(value);
3718 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3723 if (isBuildableWith(value, type))
3724 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3729OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3737 AtomicOrdering ordering, StringRef syncscope,
3738 unsigned alignment,
bool isVolatile) {
3739 build(builder, state, val.
getType(), binOp,
ptr, val, ordering,
3740 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3743 nullptr,
nullptr,
nullptr);
3746LogicalResult AtomicRMWOp::verify() {
3747 auto valType = getVal().getType();
3748 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3749 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3750 getBinOp() == AtomicBinOp::fminimum ||
3751 getBinOp() == AtomicBinOp::fmaximum ||
3752 getBinOp() == AtomicBinOp::fminimumnum ||
3753 getBinOp() == AtomicBinOp::fmaximumnum) {
3756 return emitOpError(
"expected LLVM IR fixed vector type");
3757 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3760 "expected LLVM IR floating point type for vector element");
3762 return emitOpError(
"expected LLVM IR floating point type");
3764 }
else if (getBinOp() == AtomicBinOp::xchg) {
3767 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3769 auto intType = llvm::dyn_cast<IntegerType>(valType);
3770 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3771 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3773 return emitOpError(
"expected LLVM IR integer type");
3776 if (
static_cast<unsigned>(getOrdering()) <
3777 static_cast<unsigned>(AtomicOrdering::monotonic))
3779 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3791 auto boolType = IntegerType::get(valType.
getContext(), 1);
3792 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3797 AtomicOrdering successOrdering,
3798 AtomicOrdering failureOrdering, StringRef syncscope,
3799 unsigned alignment,
bool isWeak,
bool isVolatile) {
3801 successOrdering, failureOrdering,
3802 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3804 isVolatile,
nullptr,
3805 nullptr,
nullptr,
nullptr);
3808LogicalResult AtomicCmpXchgOp::verify() {
3809 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3811 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3812 auto valType = getVal().getType();
3816 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3817 getFailureOrdering() < AtomicOrdering::monotonic)
3818 return emitOpError(
"ordering must be at least 'monotonic'");
3819 if (getFailureOrdering() == AtomicOrdering::release ||
3820 getFailureOrdering() == AtomicOrdering::acq_rel)
3821 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3830 AtomicOrdering ordering, StringRef syncscope) {
3831 build(builder, state, ordering,
3832 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3835LogicalResult FenceOp::verify() {
3836 if (getOrdering() == AtomicOrdering::not_atomic ||
3837 getOrdering() == AtomicOrdering::unordered ||
3838 getOrdering() == AtomicOrdering::monotonic)
3839 return emitOpError(
"can be given only acquire, release, acq_rel, "
3840 "and seq_cst orderings");
3850template <
class ExtOp>
3852 IntegerType inputType, outputType;
3855 return op.emitError(
3856 "input type is a vector but output type is an integer");
3859 return op.emitError(
"input and output vectors are of incompatible shape");
3862 inputType = cast<IntegerType>(
3863 cast<VectorType>(op.getArg().getType()).getElementType());
3864 outputType = cast<IntegerType>(
3865 cast<VectorType>(op.getResult().getType()).getElementType());
3869 inputType = cast<IntegerType>(op.getArg().getType());
3870 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3872 return op.emitError(
3873 "input type is an integer but output type is a vector");
3876 if (outputType.getWidth() <= inputType.getWidth())
3877 return op.emitError(
"integer width of the output type is smaller or "
3878 "equal to the integer width of the input type");
3889 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3893 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3894 return IntegerAttr::get(
getType(), arg.getValue().zext(targetSize));
3908template <
typename T>
3910 typename T::FoldAdaptor adaptor) {
3912 if (castOp.getArg().getType() == castOp.getType())
3913 return castOp.getArg();
3914 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3916 if (prev.getArg().getType() == castOp.getType())
3917 return prev.getArg();
3919 castOp.getArgMutable().set(prev.getArg());
3920 return Value{castOp};
3925OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3929LogicalResult LLVM::BitcastOp::verify() {
3935 if (isa<LLVMByteType>(srcElemType) || isa<LLVMByteType>(dstElemType))
3938 auto resultType = llvm::dyn_cast<LLVMPointerType>(dstElemType);
3939 auto sourceType = llvm::dyn_cast<LLVMPointerType>(srcElemType);
3943 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3944 return emitOpError(
"can only cast pointers from and to pointers");
3949 auto isVector = llvm::IsaPred<VectorType>;
3953 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3954 return emitOpError(
"cannot cast pointer to vector of pointers");
3956 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3957 return emitOpError(
"cannot cast vector of pointers to pointer");
3961 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3962 return emitOpError(
"cannot cast pointers of different address spaces, "
3963 "use 'llvm.addrspacecast' instead");
3968LogicalResult LLVM::PtrToAddrOp::verify() {
3975 assert(width &&
"pointers always return an index bitwidth");
3976 if (width != integerType.getWidth())
3977 return emitOpError(
"bit-width of integer result type ")
3978 << integerType <<
" must match the pointer bitwidth (" << *width
3979 <<
") specified in the datalayout";
3988OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3992Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
4000 adaptor.getDynamicIndices());
4004 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(
indices[0]))
4005 if (integer.getValue().isZero())
4009 bool changed =
false;
4011 for (
auto iter : llvm::enumerate(
indices)) {
4012 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
4015 if (!
indices.isDynamicIndex(iter.index()) || !integer ||
4019 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
4020 gepArgs.emplace_back(val);
4022 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
4028 gepArgs.emplace_back(integer.getInt());
4036 getDynamicIndicesMutable().assign(dynamicIndices);
4037 setRawConstantIndices(rawConstantIndices);
4038 return Value{*
this};
4044Value LLVM::GEPOp::getViewSource() {
return getBase(); }
4051 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4055 if (
rhs.getValue().getZExtValue() >=
4056 getLhs().
getType().getIntOrFloatBitWidth())
4059 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4063 return IntegerAttr::get(
getType(),
lhs.getValue().shl(
rhs.getValue()));
4071 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4075 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4079 return IntegerAttr::get(
getType(),
lhs.getValue() |
rhs.getValue());
4086LogicalResult CallIntrinsicOp::verify() {
4087 if (!getIntrin().starts_with(
"llvm."))
4088 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
4096 build(builder, state,
TypeRange{}, intrin, args,
4097 FastmathFlagsAttr{},
4104 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4105 build(builder, state,
TypeRange{}, intrin, args,
4112 mlir::Type resultType, mlir::StringAttr intrin,
4114 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
4122 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4123 build(builder, state, resultTypes, intrin, args, fastMathFlags,
4128ParseResult CallIntrinsicOp::parse(
OpAsmParser &parser,
4130 StringAttr intrinAttr;
4140 result.addAttribute(CallIntrinsicOp::getIntrinAttrName(
result.name),
4148 return mlir::failure();
4151 return mlir::failure();
4156 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
4159 if (opBundleTags && !opBundleTags.empty())
4161 CallIntrinsicOp::getOpBundleTagsAttrName(
result.name).getValue(),
4165 return mlir::failure();
4170 operands, argAttrs, resultAttrs))
4174 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
4177 opBundleOperandTypes,
4178 getOpBundleSizesAttrName(
result.name)))
4181 int32_t numOpBundleOperands = 0;
4182 for (
const auto &operands : opBundleOperands)
4183 numOpBundleOperands += operands.size();
4186 CallIntrinsicOp::getOperandSegmentSizeAttr(),
4188 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
4190 return mlir::success();
4198 p <<
"(" << args <<
")";
4201 if (!getOpBundleOperands().empty()) {
4204 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
4208 {getOperandSegmentSizesAttrName(),
4209 getOpBundleSizesAttrName(), getIntrinAttrName(),
4210 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
4211 getResAttrsAttrName()});
4217 p, args.
getTypes(), getArgAttrsAttr(),
4218 false, getResultTypes(), getResAttrsAttr());
4225LogicalResult LinkerOptionsOp::verify() {
4228 return emitOpError(
"must appear at the module level");
4236LogicalResult ModuleFlagsOp::verify() {
4239 return emitOpError(
"must appear at the module level");
4243 auto moduleFlag = dyn_cast<ModuleFlagAttrInterface>(flag);
4245 return emitOpError(
"expected a module flag attribute");
4247 moduleFlag.getModuleFlagKey(), moduleFlag.getModuleFlagValue(),
4248 [&] { return emitOpError(); })))
4250 if (moduleFlag.getModuleFlagBehavior() == ModFlagBehavior::Require)
4252 StringAttr key = moduleFlag.getModuleFlagKey();
4253 if (!seenNonRequireKeys.insert(key).second)
4255 << key.getValue() <<
"' to be unique for non-require flags";
4264void InlineAsmOp::getEffects(
4267 if (getHasSideEffects()) {
4280 getBlockAddr().getFunction());
4281 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
4284 return emitOpError(
"must reference a function defined by 'llvm.func'");
4294BlockTagOp BlockAddressOp::getBlockTagOp() {
4299 auto funcOp = dyn_cast<LLVMFuncOp>(sym);
4302 BlockTagOp blockTagOp =
nullptr;
4303 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4304 if (labelOp.getTag() == getBlockAddr().getTag()) {
4305 blockTagOp = labelOp;
4313LogicalResult BlockAddressOp::verify() {
4314 if (!getBlockTagOp())
4316 "expects an existing block label target in the referenced function");
4323OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4330 assert(
index < getNumSuccessors() &&
"invalid successor index");
4342 rangeSegments.push_back(range.size());
4356 Block *destination = nullptr;
4357 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4358 SmallVector<Type> operandTypes;
4360 if (parser.parseSuccessor(destination).failed())
4363 if (succeeded(parser.parseOptionalLParen())) {
4364 if (failed(parser.parseOperandList(
4365 operands, OpAsmParser::Delimiter::None)) ||
4366 failed(parser.parseColonTypeList(operandTypes)) ||
4367 failed(parser.parseRParen()))
4370 succOperandBlocks.push_back(destination);
4371 succOperands.emplace_back(operands);
4372 succOperandsTypes.emplace_back(operandTypes);
4375 "successor blocks")))
4386 llvm::zip(succs, succOperands),
4392 if (!succOperands.empty())
4401LogicalResult LLVM::SincosOp::verify() {
4402 auto operandType = getOperand().getType();
4403 auto resultType = getResult().getType();
4404 auto resultStructType =
4405 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4406 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4407 resultStructType.getBody()[0] != operandType ||
4408 resultStructType.getBody()[1] != operandType) {
4409 return emitOpError(
"expected result type to be an homogeneous struct with "
4410 "two elements matching the operand type, but got ")
4422 return build(builder, state, cond, {},
4434 return build(builder, state, cond,
"align",
ValueRange{
ptr, align});
4440 return build(builder, state, cond,
"separate_storage",
4450LogicalResult LLVM::masked_gather::verify() {
4451 auto ptrsVectorType = getPtrs().getType();
4452 Type expectedPtrsVectorType =
4457 if (ptrsVectorType != expectedPtrsVectorType)
4458 return emitOpError(
"expected operand #1 type to be ")
4459 << expectedPtrsVectorType;
4467LogicalResult LLVM::masked_scatter::verify() {
4468 auto ptrsVectorType = getPtrs().getType();
4469 Type expectedPtrsVectorType =
4474 if (ptrsVectorType != expectedPtrsVectorType)
4475 return emitOpError(
"expected operand #2 type to be ")
4476 << expectedPtrsVectorType;
4489 build(builder, state, resTys,
ptr, mask, passthru, argAttrs,
4497void LLVM::masked_compressstore::build(
OpBuilder &builder,
4502 build(builder, state, value,
ptr, mask, argAttrs,
4510LogicalResult InlineAsmOp::verify() {
4511 if (!getTailCallKindAttr())
4514 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4516 "tail call kind 'musttail' is not supported by this operation");
4526 Value divisor = getRhs();
4541 Value divisor = getRhs();
4553void LLVMDialect::initialize() {
4554 registerAttributes();
4557 addTypes<LLVMVoidType,
4559 LLVMMetadataType>();
4565#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4569#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4574 allowUnknownOperations();
4575 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4579#define GET_OP_CLASSES
4580#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4582#define GET_OP_CLASSES
4583#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4585LogicalResult LLVMDialect::verifyDataLayoutString(
4588 llvm::DataLayout::parse(descr);
4589 if (maybeDataLayout)
4592 std::string message;
4593 llvm::raw_string_ostream messageStream(message);
4594 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4595 reportError(
"invalid data layout descriptor: " + message);
4600LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4606 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4608 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4609 return verifyDataLayoutString(
4610 stringAttr.getValue(),
4611 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4614 << LLVM::LLVMDialect::getDataLayoutAttrName()
4615 <<
"' to be a string attributes";
4618LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4626 StringAttr name = paramAttr.
getName();
4628 auto checkUnitAttrType = [&]() -> LogicalResult {
4629 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4630 return op->
emitError() << name <<
" should be a unit attribute";
4633 auto checkTypeAttrType = [&]() -> LogicalResult {
4634 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4635 return op->
emitError() << name <<
" should be a type attribute";
4638 auto checkIntegerAttrType = [&]() -> LogicalResult {
4639 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4640 return op->
emitError() << name <<
" should be an integer attribute";
4643 auto checkPointerType = [&]() -> LogicalResult {
4644 if (!llvm::isa<LLVMPointerType>(paramType))
4646 << name <<
" attribute attached to non-pointer LLVM type";
4649 auto checkIntegerType = [&]() -> LogicalResult {
4650 if (!llvm::isa<IntegerType>(paramType))
4652 << name <<
" attribute attached to non-integer LLVM type";
4655 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4656 if (
failed(checkPointerType()))
4663 if (name == LLVMDialect::getNoAliasAttrName() ||
4664 name == LLVMDialect::getReadonlyAttrName() ||
4665 name == LLVMDialect::getReadnoneAttrName() ||
4666 name == LLVMDialect::getWriteOnlyAttrName() ||
4667 name == LLVMDialect::getNestAttrName() ||
4668 name == LLVMDialect::getNoCaptureAttrName() ||
4669 name == LLVMDialect::getNoFreeAttrName() ||
4670 name == LLVMDialect::getNonNullAttrName()) {
4671 if (
failed(checkUnitAttrType()))
4673 if (verifyValueType &&
failed(checkPointerType()))
4679 if (name == LLVMDialect::getStructRetAttrName() ||
4680 name == LLVMDialect::getByValAttrName() ||
4681 name == LLVMDialect::getByRefAttrName() ||
4682 name == LLVMDialect::getElementTypeAttrName() ||
4683 name == LLVMDialect::getInAllocaAttrName() ||
4684 name == LLVMDialect::getPreallocatedAttrName()) {
4685 if (
failed(checkTypeAttrType()))
4687 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4693 if (name == LLVMDialect::getSExtAttrName() ||
4694 name == LLVMDialect::getZExtAttrName()) {
4695 if (
failed(checkUnitAttrType()))
4697 if (verifyValueType &&
failed(checkIntegerType()))
4703 if (name == LLVMDialect::getAlignAttrName() ||
4704 name == LLVMDialect::getDereferenceableAttrName() ||
4705 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4706 if (
failed(checkIntegerAttrType()))
4708 if (verifyValueType &&
failed(checkPointerType()))
4714 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4715 if (
failed(checkIntegerAttrType()))
4721 if (name == LLVMDialect::getNoUndefAttrName() ||
4722 name == LLVMDialect::getInRegAttrName() ||
4723 name == LLVMDialect::getReturnedAttrName())
4724 return checkUnitAttrType();
4730LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4734 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4737 Type argType = funcOp.getArgumentTypes()[argIdx];
4739 return verifyParameterAttribute(op, argType, argAttr);
4742LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4746 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4749 Type resType = funcOp.getResultTypes()[resIdx];
4753 if (llvm::isa<LLVMVoidType>(resType))
4754 return op->
emitError() <<
"cannot attach result attributes to functions "
4755 "with a void return";
4759 auto name = resAttr.
getName();
4760 if (name == LLVMDialect::getAllocAlignAttrName() ||
4761 name == LLVMDialect::getAllocatedPointerAttrName() ||
4762 name == LLVMDialect::getByValAttrName() ||
4763 name == LLVMDialect::getByRefAttrName() ||
4764 name == LLVMDialect::getInAllocaAttrName() ||
4765 name == LLVMDialect::getNestAttrName() ||
4766 name == LLVMDialect::getNoCaptureAttrName() ||
4767 name == LLVMDialect::getNoFreeAttrName() ||
4768 name == LLVMDialect::getPreallocatedAttrName() ||
4769 name == LLVMDialect::getReadnoneAttrName() ||
4770 name == LLVMDialect::getReadonlyAttrName() ||
4771 name == LLVMDialect::getReturnedAttrName() ||
4772 name == LLVMDialect::getStackAlignmentAttrName() ||
4773 name == LLVMDialect::getStructRetAttrName() ||
4774 name == LLVMDialect::getWriteOnlyAttrName())
4775 return op->
emitError() << name <<
" is not a valid result attribute";
4776 return verifyParameterAttribute(op, resType, resAttr);
4784 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4785 if (isa<LLVM::LLVMPointerType>(type))
4786 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4787 if (isa<LLVM::UndefAttr>(value))
4788 return LLVM::UndefOp::create(builder, loc, type);
4789 if (isa<LLVM::PoisonAttr>(value))
4790 return LLVM::PoisonOp::create(builder, loc, type);
4791 if (isa<LLVM::ZeroAttr>(value))
4792 return LLVM::ZeroOp::create(builder, loc, type);
4793 if (isa<LLVM::MDStringAttr, LLVM::MDConstantAttr, LLVM::MDGlobalValueAttr,
4794 LLVM::MDNodeAttr>(value))
4795 if (isa<LLVM::LLVMMetadataType>(type))
4796 return LLVM::MetadataAsValueOp::create(builder, loc, type, value);
4798 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4806 StringRef name, StringRef value,
4807 LLVM::Linkage linkage) {
4810 "expected builder to point to a block constrained in an op");
4812 builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4813 assert(module &&
"builder points to an op outside of a module");
4818 auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4819 auto global = LLVM::GlobalOp::create(
4820 moduleBuilder, loc, type,
true, linkage, name,
4823 LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4826 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4827 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4839 module = module->getParentOp();
4840 assert(module &&
"unexpected operation outside of a module");
p<< " : "<< getMemRefType()<< ", "<< getType();}static LogicalResult verifyVectorMemoryOp(Operation *op, MemRefType memrefType, VectorType vectorType) { if(memrefType.getElementType() !=vectorType.getElementType()) return op-> emitOpError("requires memref and vector types of the same elemental type")
Given a list of lists of parsed operands, populates uniqueOperands with unique operands.
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
static int parseOptionalKeywordAlternative(OpAsmParser &parser, ArrayRef< StringRef > keywords)
static ArrayAttr getLLVMAlignParamForCompressExpand(OpBuilder &builder, bool isExpandLoad, uint64_t alignment=1)
static LogicalResult verifyAtomicMemOp(OpTy memOp, Type valueType, ArrayRef< AtomicOrdering > unsupportedOrderings)
Verifies the attributes and the type of atomic memory access operations.
static RetTy parseOptionalLLVMKeyword(OpAsmParser &parser, EnumTy defaultValue)
Parse an enum from the keyword, or default to the provided default value.
static LogicalResult checkGlobalXtorData(Operation *op, ArrayAttr data)
static ParseResult parseGEPIndices(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &indices, DenseI32ArrayAttr &rawConstantIndices)
static LogicalResult verifyOperandBundles(OpType &op)
static ParseResult parseCmpOp(OpAsmParser &parser, OperationState &result)
static void printOneOpBundle(OpAsmPrinter &p, OperandRange operands, TypeRange operandTypes, StringRef tag)
static LogicalResult verifyComdat(Operation *op, std::optional< SymbolRefAttr > attr)
static 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 void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type flagType, DenseIntElementsAttr caseValues, SuccessorRange caseDestinations, OperandRangeRange caseOperands, const TypeRangeRange &caseOperandTypes)
static ParseResult parseSwitchOpCases(OpAsmParser &parser, Type flagType, DenseIntElementsAttr &caseValues, SmallVectorImpl< Block * > &caseDestinations, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand > > &caseOperands, SmallVectorImpl< SmallVector< Type > > &caseOperandTypes)
<cases> ::= [ (case (, case )* )?
static LogicalResult verifyCallOpVarCalleeType(OpTy callOp)
Verify that the parameter and return types of the variadic callee type match the callOp argument and ...
static ParseResult parseOptionalCallFuncPtr(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operands)
Parses an optional function pointer operand before the call argument list for indirect calls,...
static bool isZeroAttribute(Attribute value)
static Operation::operand_range getOperandsPassedToCallee(OpTy callOp)
Return the operands of callOp that are passed to the callee, including the variadic arguments in case...
static void printGEPIndices(OpAsmPrinter &printer, LLVM::GEPOp gepOp, OperandRange indices, DenseI32ArrayAttr rawConstantIndices)
static std::optional< ParseResult > parseOpBundles(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand > > &opBundleOperands, SmallVector< SmallVector< Type > > &opBundleOperandTypes, ArrayAttr &opBundleTags)
static LLVMStructType getValAndBoolStructType(Type valType)
Returns an LLVM struct type that contains a value type and a boolean type.
static void printOpBundles(OpAsmPrinter &p, Operation *op, OperandRangeRange opBundleOperands, TypeRangeRange opBundleOperandTypes, std::optional< ArrayAttr > opBundleTags)
static void printShuffleType(AsmPrinter &printer, Operation *op, Type v1Type, Type resType, DenseI32ArrayAttr mask)
Nothing to do when the result type is inferred.
static LogicalResult verifyBlockTags(LLVMFuncOp funcOp)
static Type buildLLVMFunctionType(OpAsmParser &parser, SMLoc loc, ArrayRef< Type > inputs, ArrayRef< Type > outputs, function_interface_impl::VariadicFlag variadicFlag)
static auto processFMFAttr(ArrayRef< NamedAttribute > attrs)
static TypeAttr getCallOpVarCalleeType(LLVMFunctionType calleeType)
Gets the variadic callee type for a LLVMFunctionType.
static Type getInsertExtractValueElementType(function_ref< InFlightDiagnostic(StringRef)> emitError, Type containerType, ArrayRef< int64_t > position)
Extract the type at position in the LLVM IR aggregate type containerType.
static ParseResult parseOneOpBundle(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand > > &opBundleOperands, SmallVector< SmallVector< Type > > &opBundleOperandTypes, SmallVector< Attribute > &opBundleTags)
static Type getElementType(Type type)
Determine the element type of type.
static void printIndirectBrOpSucessors(OpAsmPrinter &p, IndirectBrOp op, Type flagType, SuccessorRange succs, OperandRangeRange succOperands, const TypeRangeRange &succOperandsTypes)
static ParseResult resolveOpBundleOperands(OpAsmParser &parser, SMLoc loc, OperationState &state, ArrayRef< SmallVector< OpAsmParser::UnresolvedOperand > > opBundleOperands, ArrayRef< SmallVector< Type > > opBundleOperandTypes, StringAttr opBundleSizesAttrName)
static void printLLVMLinkage(OpAsmPrinter &p, Operation *, LinkageAttr val)
static LogicalResult verifyStructArrayConstant(LLVM::ConstantOp op, LLVM::LLVMArrayType arrayType, ArrayAttr arrayAttr, int dim)
Verifies the constant array represented by arrayAttr matches the provided arrayType.
static ParseResult parseCallTypeAndResolveOperands(OpAsmParser &parser, OperationState &result, bool isDirect, ArrayRef< OpAsmParser::UnresolvedOperand > operands, SmallVectorImpl< DictionaryAttr > &argAttrs, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses the type of a call operation and resolves the operands if the parsing succeeds.
static LogicalResult verifySymbolAttrUse(FlatSymbolRefAttr symbol, Operation *op, SymbolTableCollection &symbolTable)
Verifies symbol's use in op to ensure the symbol is a valid and fully defined llvm....
static Type extractVectorElementType(Type type)
Returns the elemental type of any LLVM-compatible vector type or self.
static bool hasScalableVectorType(Type t)
Check if the given type is a scalable vector type or a vector/array type that contains a nested scala...
static SmallVector< Type, 1 > getCallOpResultTypes(LLVMFunctionType calleeType)
Gets the MLIR Op-like result types of a LLVMFunctionType.
static OpFoldResult foldChainableCast(T castOp, typename T::FoldAdaptor adaptor)
Folds a cast op that can be chained.
static void destructureIndices(Type currType, ArrayRef< GEPArg > indices, SmallVectorImpl< int32_t > &rawConstantIndices, SmallVectorImpl< Value > &dynamicIndices)
Destructures the 'indices' parameter into 'rawConstantIndices' and 'dynamicIndices',...
static ParseResult parseCommonGlobalAndAlias(OpAsmParser &parser, OperationState &result)
Parse common attributes that might show up in the same order in both GlobalOp and AliasOp.
static Type getI1SameShape(Type type)
Returns a boolean type that has the same shape as type.
static void printCommonGlobalAndAlias(OpAsmPrinter &p, OpType op)
static ParseResult parseLLVMLinkage(OpAsmParser &p, LinkageAttr &val)
static Attribute getBoolAttribute(Type type, MLIRContext *ctx, bool value)
Returns a scalar or vector boolean attribute of the given type.
static LogicalResult verifyCallOpDebugInfo(CallOp callOp, LLVMFuncOp callee)
Verify that an inlinable callsite of a debug-info-bearing function in a debug-info-bearing function h...
static ParseResult parseShuffleType(AsmParser &parser, Type v1Type, Type &resType, DenseI32ArrayAttr mask)
Build the result type of a shuffle vector operation.
static LogicalResult verifyExtOp(ExtOp op)
Verifies that the given extension operation operates on consistent scalars or vectors,...
static constexpr const char kElemTypeAttrName[]
static ParseResult parseInsertExtractValueElementType(AsmParser &parser, Type &valueType, Type containerType, DenseI64ArrayAttr position)
Infer the value type from the container type and position.
static LogicalResult verifyStructIndices(Type baseGEPType, unsigned indexPos, GEPIndicesAdaptor< ValueRange > indices, function_ref< InFlightDiagnostic()> emitOpError)
For the given indices, check if they comply with baseGEPType, especially check against LLVMStructType...
static Attribute extractElementAt(Attribute attr, size_t index)
Extracts the element at the given index from an attribute.
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
static void printInsertExtractValueElementType(AsmPrinter &printer, Operation *op, Type valueType, Type containerType, DenseI64ArrayAttr position)
Nothing to print for an inferred type.
static ParseResult parseIndirectBrOpSucessors(OpAsmParser &parser, Type &flagType, SmallVectorImpl< Block * > &succOperandBlocks, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand > > &succOperands, SmallVectorImpl< SmallVector< Type > > &succOperandsTypes)
#define REGISTER_ENUM_TYPE(Ty)
static 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)
This base class exposes generic asm parser hooks, usable across the various derived parsers.
ParseResult parseSymbolName(StringAttr &result)
Parse an -identifier and store it (without the '@' symbol) in a string attribute.
@ Paren
Parens surrounding zero or more operands.
@ None
Zero or more operands with no delimiters.
@ Square
Square brackets surrounding zero or more operands.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseColonTypeList(SmallVectorImpl< Type > &result)=0
Parse a colon followed by a type list, which must have at least one type.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseOptionalColonTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional colon followed by a type list, which if present must have at least one type.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
virtual ParseResult parseCustomAttributeWithFallback(Attribute &result, Type type, function_ref< ParseResult(Attribute &result, Type type)> parseAttribute)=0
Parse a custom attribute with the provided callback, unless the next token is #, in which case the ge...
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
virtual ParseResult parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
virtual void printAttribute(Attribute attr)
virtual void printNewline()
Print a newline and indent the printer to the start of the current operation/attribute/type.
Attributes are known-constant values of operations.
MLIRContext * getContext() const
Return the context this attribute belongs to.
This class provides an abstraction over the different types of ranges over Blocks.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
static BoolAttr get(MLIRContext *context, bool value)
This class is a general helper class for creating context-global objects like types,...
IntegerAttr getI32IntegerAttr(int32_t value)
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
IntegerAttr getI64IntegerAttr(int64_t value)
Ty getType(Args &&...args)
Get or construct an instance of the type Ty with provided arguments.
StringAttr getStringAttr(const Twine &bytes)
TypedAttr getZeroAttr(Type type)
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
MLIRContext * getContext() const
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
NamedAttribute getNamedAttr(StringRef name, Attribute val)
ArrayAttr getStrArrayAttr(ArrayRef< StringRef > values)
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
The main mechanism for performing data layout queries.
static DataLayout closest(Operation *op)
Returns the layout of the closest parent operation carrying layout info.
std::optional< uint64_t > getTypeIndexBitwidth(Type t) const
Returns the bitwidth that should be used when performing index computations for the given pointer-lik...
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
An attribute that represents a reference to a dense integer vector or tensor object.
static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg)
Get an instance of a DenseIntElementsAttr with the given arguments.
A symbol reference with a reference path containing a single element.
StringRef getValue() const
Returns the name of the held symbol reference.
StringAttr getAttr() const
Returns the name of the held symbol reference as a StringAttr.
This class represents a fused location whose metadata is known to be an instance of the given type.
This class represents a diagnostic that is inflight and set to be reported.
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
Class used for building a 'llvm.getelementptr'.
Class used for convenient access and iteration over GEP indices.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
This class provides a mutable adaptor for a range of operands.
NamedAttribute represents a combination of a name and an Attribute value.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
virtual ParseResult parseSuccessor(Block *&dest)=0
Parse a single operation successor.
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
virtual OptionalParseResult parseOptionalOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single operand if present.
virtual ParseResult parseSuccessorAndUseList(Block *&dest, SmallVectorImpl< Value > &operands)=0
Parse a single operation successor and its operand list.
virtual OptionalParseResult parseOptionalRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region if present.
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printSuccessorAndUseList(Block *successor, ValueRange succOperands)=0
Print the successor and its operands.
void printOperands(const ContainerType &container)
Print a comma separated list of operands.
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
This class represents a single result from folding an operation.
This class provides the API for ops that are known to be isolated from above.
A trait used to provide symbol table functionalities to a region operation.
This class represents a contiguous range of operand ranges, e.g.
This class implements the operand iterators for the Operation class.
type_range getTypes() const
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
OperandRange operand_range
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class implements Optional functionality for ParseResult.
ParseResult value() const
Access the internal ParseResult value.
bool has_value() const
Returns true if we contain a valid ParseResult value.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
iterator_range< OpIterator > getOps()
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
void modifyOpInPlace(Operation *root, CallableT &&callable)
This method is a utility wrapper around an in-place modification of an operation.
This class represents a specific instance of an effect.
static DerivedEffect * get()
This class models how operands are forwarded to block arguments in control flow.
This class implements the successor iterators for Block.
This class represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
This class provides an abstraction for a range of TypeRange.
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
bool isSignlessIntOrIndexOrFloat() const
Return true if this is a signless integer, index, or float type.
This class provides an abstraction over the different types of ranges over Values.
type_range getTypes() const
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
bool wasInterrupted() const
Returns true if the walk was interrupted.
static WalkResult interrupt()
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
ArrayRef< T > asArrayRef() const
A named class for passing around the variadic flag.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
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.
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
bool isCompatibleOuterType(Type type)
Returns true if the given outer type is compatible with the LLVM dialect without checking its potenti...
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
constexpr int kGEPConstantBitWidth
Bit-width of a 'GEPConstantIndex' within GEPArg.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
bool isTypeCompatibleWithAtomicOp(Type type, const DataLayout &dataLayout)
Returns true if the given type is supported by atomic operations.
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Speculatability
This enum is returned from the getSpeculatability method in the ConditionallySpeculatable op interfac...
constexpr auto Speculatable
constexpr auto NotSpeculatable
void printFunctionSignature(OpAsmPrinter &p, TypeRange argTypes, ArrayAttr argAttrs, bool isVariadic, TypeRange resultTypes, ArrayAttr resultAttrs, Region *body=nullptr, bool printEmptyResult=true)
Print a function signature for a call or callable operation.
ParseResult parseFunctionSignature(OpAsmParser &parser, SmallVectorImpl< Type > &argTypes, SmallVectorImpl< DictionaryAttr > &argAttrs, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs, bool mustParseEmptyResult=true)
Parses a function signature using parser.
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.