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(); } \
124template <
typename EnumTy,
typename RetTy = EnumTy>
126 EnumTy defaultValue) {
128 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
129 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
133 return static_cast<RetTy
>(defaultValue);
134 return static_cast<RetTy
>(
index);
138 p << stringifyLinkage(val.getLinkage());
142 val = LinkageAttr::get(
150 uint64_t alignment = 1) {
156 if (alignment == 1) {
163 builder.
getNamedAttr(LLVMDialect::getAlignAttrName(), alignmentAttr);
173 int pos = isExpandLoad ? 0 : 1;
175 {alignDictAttr, emptyDictAttr, emptyDictAttr})
177 {emptyDictAttr, alignDictAttr, emptyDictAttr});
189 if (!operands.empty()) {
192 llvm::interleaveComma(operandTypes, p);
201 std::optional<ArrayAttr> opBundleTags) {
202 if (opBundleOperands.empty())
204 assert(opBundleTags &&
"expect operand bundle tags");
207 llvm::interleaveComma(
208 llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
210 auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
228 return p.
emitError(currentParserLoc,
"expect operand bundle tag");
239 opBundleOperands.push_back(std::move(operands));
240 opBundleOperandTypes.push_back(std::move(types));
241 opBundleTags.push_back(StringAttr::get(p.
getContext(), tag));
258 auto bundleParser = [&] {
268 opBundleTags = ArrayAttr::get(p.
getContext(), opBundleTagAttrs);
278 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
279 <<
", " << getOperand(1);
281 p <<
" : " << getLhs().getType();
285 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
286 <<
", " << getOperand(1);
288 p <<
" : " << getLhs().getType();
295template <
typename CmpPredicateType>
297 StringAttr predicateAttr;
300 SMLoc predicateLoc, trailingTypeLoc;
313 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
314 std::optional<ICmpPredicate> predicate =
315 symbolizeICmpPredicate(predicateAttr.getValue());
318 <<
"'" << predicateAttr.getValue()
319 <<
"' is an incorrect value of the 'predicate' attribute";
320 predicateValue =
static_cast<int64_t>(*predicate);
322 std::optional<FCmpPredicate> predicate =
323 symbolizeFCmpPredicate(predicateAttr.getValue());
326 <<
"'" << predicateAttr.getValue()
327 <<
"' is an incorrect value of the 'predicate' attribute";
328 predicateValue =
static_cast<int64_t>(*predicate);
331 result.attributes.set(
"predicate",
338 "expected LLVM dialect-compatible type");
354 ShapedType shapedType = dyn_cast<ShapedType>(type);
361 if (getPredicate() != ICmpPredicate::eq &&
362 getPredicate() != ICmpPredicate::ne)
366 if (getLhs() == getRhs())
368 getPredicate() == ICmpPredicate::eq);
371 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
373 getPredicate() == ICmpPredicate::ne);
376 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
379 getLhsMutable().assign(
rhs);
380 getRhsMutable().assign(
lhs);
398 p <<
' ' << getArraySize() <<
" x " << getElemType();
399 if (getAlignment() && *getAlignment() != 0)
401 {kElemTypeAttrName, getInallocaAttrName()});
405 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
406 p <<
" : " << funcTy;
414 SMLoc trailingTypeLoc;
426 std::optional<NamedAttribute> alignmentAttr =
427 result.attributes.getNamed(
"alignment");
428 if (alignmentAttr.has_value()) {
429 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
432 "expected integer alignment");
433 if (alignmentInt.getValue().isZero())
434 result.attributes.erase(
"alignment");
438 auto funcType = llvm::dyn_cast<FunctionType>(type);
439 if (!funcType || funcType.getNumInputs() != 1 ||
440 funcType.getNumResults() != 1)
443 "expected trailing function type with one argument and one result");
448 Type resultType = funcType.getResult(0);
449 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
452 result.addTypes({funcType.getResult(0)});
456LogicalResult AllocaOp::verify() {
458 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
459 targetExtType && !targetExtType.supportsMemOps())
461 <<
"this target extension type cannot be used in alloca";
471 assert(
index == 0 &&
"invalid successor index");
480 assert(
index < getNumSuccessors() &&
"invalid successor index");
482 : getFalseDestOperandsMutable());
488 std::optional<std::pair<uint32_t, uint32_t>> weights) {
493 static_cast<int32_t
>(weights->second)});
495 build(builder,
result, condition, trueOperands, falseOperands, weightsAttr,
496 {}, trueDest, falseDest);
510 if (!branchWeights.empty())
513 build(builder,
result, value, defaultOperands, caseOperands, caseValues,
514 weightsAttr, defaultDestination, caseDestinations);
523 if (!caseValues.empty()) {
524 ShapedType caseValueType = VectorType::get(
529 build(builder,
result, value, defaultDestination, defaultOperands,
530 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
539 if (!caseValues.empty()) {
540 ShapedType caseValueType = VectorType::get(
545 build(builder,
result, value, defaultDestination, defaultOperands,
546 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
562 auto parseCase = [&]() {
566 values.push_back(APInt(bitWidth, value,
true));
579 caseDestinations.push_back(destination);
580 caseOperands.emplace_back(operands);
581 caseOperandTypes.emplace_back(operandTypes);
587 ShapedType caseValueType =
588 VectorType::get(
static_cast<int64_t>(values.size()), flagType);
607 llvm::zip(caseValues, caseDestinations),
622LogicalResult SwitchOp::verify() {
623 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
625 getCaseValues()->size() !=
626 static_cast<int64_t>(getCaseDestinations().size())))
627 return emitOpError(
"expects number of case values to match number of "
628 "case destinations");
629 if (getCaseValues() &&
631 return emitError(
"expects case value type to match condition value type");
636 assert(
index < getNumSuccessors() &&
"invalid successor index");
638 : getCaseOperandsMutable(
index - 1));
647 getDynamicIndices());
652 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
653 return vectorType.getElementType();
670 bool requiresConst = !rawConstantIndices.empty() &&
671 isa_and_nonnull<LLVMStructType>(currType);
672 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
676 rawConstantIndices.push_back(intC.getSExtValue());
678 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
679 dynamicIndices.push_back(val);
682 rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
687 if (rawConstantIndices.size() == 1 || !currType)
691 .Case<VectorType, LLVMArrayType>([](
auto containerType) {
692 return containerType.getElementType();
694 .Case([&](LLVMStructType structType) ->
Type {
695 int64_t memberIndex = rawConstantIndices.back();
696 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
697 structType.getBody().size())
698 return structType.getBody()[memberIndex];
707 GEPNoWrapFlags noWrapFlags,
713 result.addTypes(resultType);
714 result.addAttributes(attributes);
715 result.getOrAddProperties<Properties>().rawConstantIndices =
717 result.getOrAddProperties<Properties>().noWrapFlags = noWrapFlags;
718 result.getOrAddProperties<Properties>().elem_type =
719 TypeAttr::get(elementType);
720 result.addOperands(basePtr);
721 result.addOperands(dynamicIndices);
726 GEPNoWrapFlags noWrapFlags,
728 build(builder,
result, resultType, elementType, basePtr,
738 auto idxParser = [&]() -> ParseResult {
739 int32_t constantIndex;
743 if (failed(parsedInteger.
value()))
745 constantIndices.push_back(constantIndex);
749 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
763 llvm::interleaveComma(
766 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
769 printer << cast<IntegerAttr>(cst).getInt();
779 if (indexPos >=
indices.size())
784 .Case([&](LLVMStructType structType) -> LogicalResult {
785 auto attr = dyn_cast<IntegerAttr>(
indices[indexPos]);
787 return emitOpError() <<
"expected index " << indexPos
788 <<
" indexing a struct to be constant";
790 int32_t gepIndex = attr.getInt();
793 static_cast<size_t>(gepIndex) >= elementTypes.size())
795 <<
" indexing a struct is out of bounds";
802 .Case<VectorType, LLVMArrayType>(
803 [&](
auto containerType) -> LogicalResult {
807 .Default([&](
auto otherType) -> LogicalResult {
809 <<
"type " << otherType <<
" cannot be indexed (index #"
821LogicalResult LLVM::GEPOp::verify() {
822 if (
static_cast<size_t>(
823 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
824 getDynamicIndices().size())
825 return emitOpError(
"expected as many dynamic indices as specified in '")
826 << getRawConstantIndicesAttrName().getValue() <<
"'";
828 if (getNoWrapFlags() == GEPNoWrapFlags::inboundsFlag)
829 return emitOpError(
"'inbounds_flag' cannot be used directly.");
839void LoadOp::getEffects(
848 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
849 getOrdering() != AtomicOrdering::unordered)) {
860 if (!isa<IntegerType, LLVMPointerType>(type))
865 if (bitWidth.isScalable())
868 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
872template <
typename OpTy>
876 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
879 return memOp.emitOpError(
"unsupported type ")
880 << valueType <<
" for atomic access";
881 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
882 return memOp.emitOpError(
"unsupported ordering '")
883 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
884 if (!memOp.getAlignment())
885 return memOp.emitOpError(
"expected alignment for atomic access");
888 if (memOp.getSyncscope())
889 return memOp.emitOpError(
890 "expected syncscope to be null for non-atomic access");
894LogicalResult LoadOp::verify() {
895 Type valueType = getResult().getType();
897 {AtomicOrdering::release, AtomicOrdering::acq_rel});
901 Value addr,
unsigned alignment,
bool isVolatile,
902 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
903 AtomicOrdering ordering, StringRef syncscope) {
904 build(builder, state, type, addr,
906 isNonTemporal, isInvariant, isInvariantGroup, ordering,
907 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
918void StoreOp::getEffects(
927 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
928 getOrdering() != AtomicOrdering::unordered)) {
934LogicalResult StoreOp::verify() {
935 Type valueType = getValue().getType();
937 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
941 Value addr,
unsigned alignment,
bool isVolatile,
942 bool isNonTemporal,
bool isInvariantGroup,
943 AtomicOrdering ordering, StringRef syncscope) {
944 build(builder, state, value, addr,
946 isNonTemporal, isInvariantGroup, ordering,
947 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
949 nullptr,
nullptr,
nullptr);
959 Type resultType = calleeType.getReturnType();
960 if (!isa<LLVM::LLVMVoidType>(resultType))
961 results.push_back(resultType);
967 return calleeType.isVarArg() ? TypeAttr::get(calleeType) :
nullptr;
975 resultType = LLVMVoidType::get(context);
977 resultType = results.front();
978 return LLVMFunctionType::get(resultType, llvm::to_vector(args.
getTypes()),
984 build(builder, state, results, builder.
getStringAttr(callee), args);
989 build(builder, state, results, SymbolRefAttr::get(callee), args);
994 assert(callee &&
"expected non-null callee in direct call builder");
995 build(builder, state, results,
996 nullptr, callee, args,
nullptr,
999 nullptr,
nullptr,
nullptr,
1000 nullptr,
nullptr,
nullptr,
1004 nullptr,
nullptr,
nullptr,
1018 LLVMFunctionType calleeType, StringRef callee,
1020 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1024 LLVMFunctionType calleeType, StringAttr callee,
1026 build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
1044 nullptr,
nullptr,
nullptr,
1052 nullptr,
nullptr,
nullptr,
1058 LLVMFunctionType calleeType,
ValueRange args) {
1063 nullptr,
nullptr,
nullptr,
1064 nullptr,
nullptr,
nullptr,
1070 nullptr,
nullptr,
nullptr,
1085 auto calleeType =
func.getFunctionType();
1089 nullptr,
nullptr,
nullptr,
1090 nullptr,
nullptr,
nullptr,
1096 nullptr,
nullptr,
nullptr,
1114 return getOperand(0);
1120 auto symRef = cast<SymbolRefAttr>(callee);
1121 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1124 return setOperand(0, cast<Value>(callee));
1128 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1133 getCalleeOperands().size());
1140 if (callee.isExternal())
1142 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1146 auto hasSubprogram = [](
Operation *op) {
1151 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1153 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1155 return callOp.emitError()
1156 <<
"inlinable function call in a function with a DISubprogram "
1157 "location must have a debug location";
1163template <
typename OpTy>
1165 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1170 if (!varCalleeType->isVarArg())
1171 return callOp.emitOpError(
1172 "expected var_callee_type to be a variadic function type");
1176 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1177 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1178 << callOp.getArgOperands().size() <<
" parameters";
1181 for (
auto [paramType, operand] :
1182 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1183 if (paramType != operand.getType())
1184 return callOp.emitOpError()
1185 <<
"var_callee_type parameter type mismatch: " << paramType
1186 <<
" != " << operand.getType();
1189 if (!callOp.getNumResults()) {
1190 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1191 return callOp.emitOpError(
"expected var_callee_type to return void");
1193 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1194 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1195 << varCalleeType->getReturnType()
1196 <<
" != " << callOp.getResult().getType();
1201template <
typename OpType>
1204 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1206 auto isStringAttr = [](
Attribute tagAttr) {
1207 return isa<StringAttr>(tagAttr);
1209 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1210 return op.emitError(
"operand bundle tag must be a StringAttr");
1212 size_t numOpBundles = opBundleOperands.size();
1213 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1214 if (numOpBundles != numOpBundleTags)
1215 return op.emitError(
"expected ")
1216 << numOpBundles <<
" operand bundle tags, but actually got "
1232 bool isIndirect =
false;
1238 if (!getNumOperands())
1240 "must have either a `callee` attribute or at least an operand");
1241 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1243 return emitOpError(
"indirect call expects a pointer as callee: ")
1244 << getOperand(0).getType();
1253 <<
"' does not reference a symbol in the current scope";
1254 if (
auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1257 fnType = fn.getFunctionType();
1258 }
else if (
auto ifunc = dyn_cast<IFuncOp>(callee)) {
1259 fnType = ifunc.getIFuncType();
1260 }
else if (isa<AliasOp>(callee)) {
1264 fnType = getCalleeFunctionType();
1268 <<
"' does not reference a valid LLVM function, IFunc, or alias";
1272 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1274 return emitOpError(
"callee does not have a functional type: ") << fnType;
1276 if (funcType.isVarArg() && !getVarCalleeType())
1277 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1281 if (!funcType.isVarArg() &&
1282 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1283 return emitOpError() <<
"incorrect number of operands ("
1284 << (getCalleeOperands().size() - isIndirect)
1285 <<
") for callee (expecting: "
1286 << funcType.getNumParams() <<
")";
1288 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1289 return emitOpError() <<
"incorrect number of operands ("
1290 << (getCalleeOperands().size() - isIndirect)
1291 <<
") for varargs callee (expecting at least: "
1292 << funcType.getNumParams() <<
")";
1294 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1295 if (getOperand(i + isIndirect).
getType() != funcType.getParamType(i))
1296 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1297 << getOperand(i + isIndirect).getType()
1298 <<
" != " << funcType.getParamType(i);
1300 if (getNumResults() == 0 &&
1301 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1302 return emitOpError() <<
"expected function call to produce a value";
1304 if (getNumResults() != 0 &&
1305 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1307 <<
"calling function with void result must not produce values";
1309 if (getNumResults() > 1)
1311 <<
"expected LLVM function call to produce 0 or 1 result";
1313 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1314 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1315 <<
" != " << funcType.getReturnType();
1321 auto callee = getCallee();
1322 bool isDirect = callee.has_value();
1327 if (getCConv() != LLVM::CConv::C)
1328 p << stringifyCConv(getCConv()) <<
' ';
1330 if (getTailCallKind() != LLVM::TailCallKind::None)
1331 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1340 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1341 p <<
'(' << args <<
')';
1344 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1345 p <<
" vararg(" << *varCalleeType <<
")";
1347 if (!getOpBundleOperands().empty()) {
1350 getOpBundleOperands().getTypes(), getOpBundleTags());
1354 {getCalleeAttrName(), getTailCallKindAttrName(),
1355 getVarCalleeTypeAttrName(), getCConvAttrName(),
1356 getOperandSegmentSizesAttrName(),
1357 getOpBundleSizesAttrName(),
1358 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1359 getResAttrsAttrName()});
1363 p << getOperand(0).getType() <<
", ";
1367 p, args.getTypes(), getArgAttrsAttr(),
1368 false, getResultTypes(), getResAttrsAttr());
1383 types.emplace_back();
1388 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1393 resTypes, resultAttrs)) {
1395 return parser.
emitError(trailingTypesLoc,
1396 "expected direct call to have 1 trailing types");
1397 return parser.
emitError(trailingTypesLoc,
1398 "expected trailing function type");
1401 if (resTypes.size() > 1)
1402 return parser.
emitError(trailingTypesLoc,
1403 "expected function with 0 or 1 result");
1404 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1405 return parser.
emitError(trailingTypesLoc,
1406 "expected a non-void result type");
1412 llvm::append_range(types, argTypes);
1416 if (!resTypes.empty())
1417 result.addTypes(resTypes);
1430 if (failed(*parseResult))
1431 return *parseResult;
1432 operands.push_back(funcPtrOperand);
1441 StringAttr opBundleSizesAttrName) {
1442 unsigned opBundleIndex = 0;
1443 for (
const auto &[operands, types] :
1444 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1445 if (operands.size() != types.size())
1446 return parser.
emitError(loc,
"expected ")
1448 <<
" types for operand bundle operands for operand bundle #"
1449 << opBundleIndex <<
", but actually got " << types.size();
1455 opBundleSizes.reserve(opBundleOperands.size());
1456 for (
const auto &operands : opBundleOperands)
1457 opBundleSizes.push_back(operands.size());
1460 opBundleSizesAttrName,
1472 SymbolRefAttr funcAttr;
1473 TypeAttr varCalleeType;
1481 getCConvAttrName(
result.name),
1486 getTailCallKindAttrName(
result.name),
1489 parser, LLVM::TailCallKind::None)));
1494 bool isDirect = operands.empty();
1507 StringAttr varCalleeTypeAttrName =
1508 CallOp::getVarCalleeTypeAttrName(
result.name);
1520 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1523 if (opBundleTags && !opBundleTags.empty())
1524 result.addAttribute(CallOp::getOpBundleTagsAttrName(
result.name).getValue(),
1534 argAttrs, resultAttrs))
1538 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1540 opBundleOperandTypes,
1541 getOpBundleSizesAttrName(
result.name)))
1544 int32_t numOpBundleOperands = 0;
1545 for (
const auto &operands : opBundleOperands)
1546 numOpBundleOperands += operands.size();
1549 CallOp::getOperandSegmentSizeAttr(),
1551 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1555LLVMFunctionType CallOp::getCalleeFunctionType() {
1556 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1557 return *varCalleeType;
1568 auto calleeType =
func.getFunctionType();
1571 nullptr,
nullptr, normalOps, unwindOps,
1572 nullptr,
nullptr,
nullptr, {}, {}, normal,
1580 build(builder, state, tys,
1581 nullptr, callee, ops,
nullptr,
1582 nullptr, normalOps, unwindOps,
nullptr,
nullptr,
1583 nullptr, {}, {}, normal, unwind);
1592 nullptr,
nullptr, normalOps, unwindOps,
1593 nullptr,
nullptr,
nullptr, {}, {}, normal,
1598 assert(
index < getNumSuccessors() &&
"invalid successor index");
1600 : getUnwindDestOperandsMutable());
1608 return getOperand(0);
1614 auto symRef = cast<SymbolRefAttr>(callee);
1615 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1618 return setOperand(0, cast<Value>(callee));
1622 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1627 getCalleeOperands().size());
1630LogicalResult InvokeOp::verify() {
1634 Block *unwindDest = getUnwindDest();
1635 if (unwindDest->
empty())
1636 return emitError(
"must have at least one operation in unwind destination");
1639 if (!isa<LandingpadOp>(unwindDest->
front()))
1640 return emitError(
"first operation in unwind destination should be a "
1641 "llvm.landingpad operation");
1650 auto callee = getCallee();
1651 bool isDirect = callee.has_value();
1656 if (getCConv() != LLVM::CConv::C)
1657 p << stringifyCConv(getCConv()) <<
' ';
1665 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1672 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1673 p <<
" vararg(" << *varCalleeType <<
")";
1675 if (!getOpBundleOperands().empty()) {
1678 getOpBundleOperands().getTypes(), getOpBundleTags());
1682 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1683 getCConvAttrName(), getVarCalleeTypeAttrName(),
1684 getOpBundleSizesAttrName(),
1685 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1686 getResAttrsAttrName()});
1690 p << getOperand(0).getType() <<
", ";
1692 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1694 false, getResultTypes(), getResAttrsAttr());
1707 SymbolRefAttr funcAttr;
1708 TypeAttr varCalleeType;
1712 Block *normalDest, *unwindDest;
1718 getCConvAttrName(
result.name),
1725 bool isDirect = operands.empty();
1741 StringAttr varCalleeTypeAttrName =
1742 InvokeOp::getVarCalleeTypeAttrName(
result.name);
1754 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1757 if (opBundleTags && !opBundleTags.empty())
1759 InvokeOp::getOpBundleTagsAttrName(
result.name).getValue(),
1769 argAttrs, resultAttrs))
1773 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1776 opBundleOperandTypes,
1777 getOpBundleSizesAttrName(
result.name)))
1780 result.addSuccessors({normalDest, unwindDest});
1781 result.addOperands(normalOperands);
1782 result.addOperands(unwindOperands);
1784 int32_t numOpBundleOperands = 0;
1785 for (
const auto &operands : opBundleOperands)
1786 numOpBundleOperands += operands.size();
1789 InvokeOp::getOperandSegmentSizeAttr(),
1791 static_cast<int32_t>(normalOperands.size()),
1792 static_cast<int32_t>(unwindOperands.size()),
1793 numOpBundleOperands}));
1797LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1798 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1799 return *varCalleeType;
1807LogicalResult LandingpadOp::verify() {
1809 if (LLVMFuncOp
func = (*this)->getParentOfType<LLVMFuncOp>()) {
1810 if (!
func.getPersonality())
1812 "llvm.landingpad needs to be in a function with a personality");
1818 if (!getCleanup() && getOperands().empty())
1819 return emitError(
"landingpad instruction expects at least one clause or "
1820 "cleanup attribute");
1822 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1823 value = getOperand(idx);
1824 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1831 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1834 <<
"global addresses expected as operand to "
1835 "bitcast used in clauses for landingpad";
1843 << idx <<
" is not a known constant - null, addressof, bitcast";
1850 p << (getCleanup() ?
" cleanup " :
" ");
1853 for (
auto value : getOperands()) {
1856 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1857 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1904 Type llvmType = containerType;
1906 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1914 for (
int64_t idx : position) {
1915 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1916 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1917 emitError(
"position out of bounds: ") << idx;
1920 llvmType = arrayType.getElementType();
1921 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1923 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1924 emitError(
"position out of bounds: ") << idx;
1927 llvmType = structType.getBody()[idx];
1929 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1940 for (
int64_t idx : position) {
1941 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1942 llvmType = structType.getBody()[idx];
1944 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1956 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
1957 ShapedType shapedType = elementsAttr.getShapedType();
1958 if (!shapedType.hasRank() || shapedType.getRank() != 1)
1960 if (
index <
static_cast<size_t>(elementsAttr.getNumElements()))
1964 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
1965 if (
index < arrayAttr.getValue().size())
1966 return arrayAttr[
index];
1969 if (isa<ZeroAttr, UndefAttr, PoisonAttr>(attr))
1974OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1975 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
1977 newPos.append(getPosition().begin(), getPosition().end());
1978 setPosition(newPos);
1979 getContainerMutable().set(extractValueOp.getContainer());
1985 for (
int64_t pos : getPosition()) {
1990 return containerAttr;
1993 Value container = getContainer();
1995 while (
auto insertValueOp = container.
getDefiningOp<InsertValueOp>()) {
1997 auto extractPosSize = extractPos.size();
1998 auto insertPosSize = insertPos.size();
2001 if (extractPos == insertPos)
2002 return insertValueOp.getValue();
2016 if (extractPosSize > insertPosSize &&
2017 extractPos.take_front(insertPosSize) == insertPos) {
2018 container = insertValueOp.getValue();
2019 extractPos = extractPos.drop_front(insertPosSize);
2035 if (insertPosSize > extractPosSize &&
2036 extractPos == insertPos.take_front(extractPosSize))
2041 container = insertValueOp.getContainer();
2047 if (container == getContainer())
2049 setPosition(extractPos);
2050 getContainerMutable().assign(container);
2054LogicalResult ExtractValueOp::verify() {
2061 if (getRes().
getType() != valueType)
2062 return emitOpError() <<
"Type mismatch: extracting from "
2063 << getContainer().getType() <<
" should produce "
2064 << valueType <<
" but this op returns "
2065 << getRes().getType();
2071 build(builder, state,
2110 LogicalResult matchAndRewrite(InsertValueOp insertOp,
2111 PatternRewriter &rewriter)
const override {
2112 bool changed =
false;
2118 auto insertBaseIdx = insertOp.getPosition()[0];
2119 for (
auto &use : insertOp->getUses()) {
2120 if (
auto extractOp = dyn_cast<ExtractValueOp>(use.getOwner())) {
2121 auto baseIdx = extractOp.getPosition()[0];
2124 if (baseIdx == insertBaseIdx)
2126 posToExtractOps[baseIdx].push_back(extractOp);
2131 Value nextContainer = insertOp.getContainer();
2132 while (!posToExtractOps.empty()) {
2134 dyn_cast_or_null<InsertValueOp>(nextContainer.
getDefiningOp());
2137 nextContainer = curInsert.getContainer();
2140 auto curInsertBaseIdx = curInsert.getPosition()[0];
2141 auto it = posToExtractOps.find(curInsertBaseIdx);
2142 if (it == posToExtractOps.end())
2146 for (
auto &extractOp : it->second) {
2148 extractOp.getContainerMutable().assign(curInsert);
2153 assert(!it->second.empty());
2155 posToExtractOps.erase(it);
2159 for (
auto &[baseIdx, extracts] : posToExtractOps) {
2160 for (
auto &extractOp : extracts) {
2162 extractOp.getContainerMutable().assign(nextContainer);
2165 assert(!extracts.empty() &&
"Empty list in map");
2175 patterns.
add<ResolveExtractValueSource>(context);
2184 [&](StringRef msg) {
2197LogicalResult InsertValueOp::verify() {
2204 if (getValue().
getType() != valueType)
2205 return emitOpError() <<
"Type mismatch: cannot insert "
2206 << getValue().getType() <<
" into "
2207 << getContainer().getType();
2216LogicalResult ReturnOp::verify() {
2217 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2221 Type expectedType = parent.getFunctionType().getReturnType();
2222 if (llvm::isa<LLVMVoidType>(expectedType)) {
2226 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2230 if (llvm::isa<LLVMVoidType>(expectedType))
2233 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2236 if (expectedType != getArg().
getType()) {
2238 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2249 return dyn_cast_or_null<GlobalOp>(
2254 return dyn_cast_or_null<LLVMFuncOp>(
2259 return dyn_cast_or_null<AliasOp>(
2264 return dyn_cast_or_null<IFuncOp>(
2273 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2274 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2275 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2276 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2278 if (!global && !function && !alias && !ifunc)
2279 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2280 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2282 LLVMPointerType type =
getType();
2283 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2284 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2285 return emitOpError(
"pointer address space must match address space of the "
2286 "referenced global or alias");
2293 return getGlobalNameAttr();
2314 getFunctionNameAttr());
2315 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2316 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2318 if (!function && !alias)
2320 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2323 if (alias.getInitializer()
2324 .walk([&](AddressOfOp addrOp) {
2325 if (addrOp.getGlobal(symbolTable))
2326 return WalkResult::interrupt();
2327 return WalkResult::advance();
2330 return emitOpError(
"must reference an alias to a function");
2333 if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2334 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2336 "target function with 'extern_weak' linkage not allowed");
2344 return DSOLocalEquivalentAttr::get(
getContext(), getFunctionNameAttr());
2352 StringRef symName) {
2355 Region *body =
result.addRegion();
2359LogicalResult ComdatOp::verifyRegions() {
2360 Region &body = getBody();
2361 for (Operation &op : body.
getOps())
2362 if (!isa<ComdatSelectorOp>(op))
2363 return op.emitError(
2364 "only comdat selector symbols can appear in a comdat region");
2374 bool isConstant, Linkage linkage, StringRef name,
2375 Attribute value, uint64_t alignment,
unsigned addrSpace,
2376 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2381 result.addAttribute(getGlobalTypeAttrName(
result.name), TypeAttr::get(type));
2386 result.addAttribute(getValueAttrName(
result.name), value);
2391 result.addAttribute(getThreadLocal_AttrName(
result.name),
2394 result.addAttribute(getComdatAttrName(
result.name), comdat);
2404 LinkageAttr::get(builder.
getContext(), linkage));
2408 result.attributes.append(attrs.begin(), attrs.end());
2410 if (!dbgExprs.empty())
2412 ArrayAttr::get(builder.
getContext(), dbgExprs));
2417template <
typename OpType>
2419 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2420 StringRef visibility = stringifyVisibility(op.getVisibility_());
2421 if (!visibility.empty())
2422 p << visibility <<
' ';
2423 if (op.getThreadLocal_())
2424 p <<
"thread_local ";
2425 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2426 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2438 if (
auto value = getValueOrNull())
2441 if (
auto comdat = getComdat())
2442 p <<
" comdat(" << *comdat <<
')';
2448 {SymbolTable::getSymbolAttrName(),
2449 getGlobalTypeAttrName(), getConstantAttrName(),
2450 getValueAttrName(), getLinkageAttrName(),
2451 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2452 getVisibility_AttrName(), getComdatAttrName()});
2455 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2459 Region &initializer = getInitializerRegion();
2460 if (!initializer.
empty()) {
2467 std::optional<SymbolRefAttr> attr) {
2472 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2473 return op->
emitError() <<
"expected comdat symbol";
2483 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2484 if (blockTags.contains(blockTagOp.getTag())) {
2485 blockTagOp.emitError()
2486 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2487 <<
"' in the same function: ";
2490 blockTags.insert(blockTagOp.getTag());
2499template <
typename OpType>
2505 OpType::getLinkageAttrName(
result.name),
2507 parser, LLVM::Linkage::External)));
2510 result.addAttribute(OpType::getVisibility_AttrName(
result.name),
2513 parser, LLVM::Visibility::Default)));
2516 result.addAttribute(OpType::getThreadLocal_AttrName(
result.name),
2520 result.addAttribute(OpType::getUnnamedAddrAttrName(
result.name),
2523 parser, LLVM::UnnamedAddr::None)));
2560 SymbolRefAttr comdat;
2565 result.addAttribute(getComdatAttrName(
result.name), comdat);
2573 if (types.size() > 1)
2577 if (types.empty()) {
2578 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2580 auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2581 strAttr.getValue().size());
2582 types.push_back(arrayType);
2585 "type can only be omitted for string globals");
2595 result.addAttribute(getGlobalTypeAttrName(
result.name),
2596 TypeAttr::get(types[0]));
2601 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2602 return intValue.getValue().isZero();
2603 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2604 return fpValue.getValue().isZero();
2605 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2607 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2609 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2614LogicalResult GlobalOp::verify() {
2616 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2618 :
llvm::isa<PointerElementTypeInterface>(
getType());
2621 "expects type to be a valid element type for an LLVM global");
2623 return emitOpError(
"must appear at the module level");
2625 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2626 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2627 IntegerType elementType =
2628 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) :
nullptr;
2629 if (!elementType || elementType.getWidth() != 8 ||
2630 type.getNumElements() != strAttr.getValue().size())
2632 "requires an i8 array type of the length equal to that of the string "
2636 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2637 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2639 <<
"this target extension type cannot be used in a global";
2642 return emitOpError() <<
"global with target extension type can only be "
2643 "initialized with zero-initializer";
2646 if (getLinkage() == Linkage::Common) {
2647 if (
Attribute value = getValueOrNull()) {
2650 <<
"expected zero value for '"
2651 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2656 if (getLinkage() == Linkage::Appending) {
2657 if (!llvm::isa<LLVMArrayType>(
getType())) {
2658 return emitOpError() <<
"expected array type for '"
2659 << stringifyLinkage(Linkage::Appending)
2667 std::optional<uint64_t> alignAttr = getAlignment();
2668 if (alignAttr.has_value()) {
2669 uint64_t value = alignAttr.value();
2670 if (!llvm::isPowerOf2_64(value))
2671 return emitError() <<
"alignment attribute is not a power of 2";
2677LogicalResult GlobalOp::verifyRegions() {
2678 if (
Block *
b = getInitializerBlock()) {
2679 ReturnOp ret = cast<ReturnOp>(
b->getTerminator());
2680 if (ret.operand_type_begin() == ret.operand_type_end())
2681 return emitOpError(
"initializer region cannot return void");
2682 if (*ret.operand_type_begin() !=
getType())
2684 << *ret.operand_type_begin() <<
" does not match global type "
2688 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2689 if (!iface || !iface.hasNoEffect())
2690 return op.emitError()
2691 <<
"ops with side effects not allowed in global initializers";
2694 if (getValueOrNull())
2695 return emitOpError(
"cannot have both initializer value and region");
2710 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2713 return op->
emitError(
"data element must be symbol or #llvm.zero");
2726LogicalResult GlobalCtorsOp::verify() {
2730 if (getCtors().size() == getPriorities().size() &&
2731 getCtors().size() == getData().size())
2734 "ctors, priorities, and data must have the same number of elements");
2751LogicalResult GlobalDtorsOp::verify() {
2755 if (getDtors().size() == getPriorities().size() &&
2756 getDtors().size() == getData().size())
2759 "dtors, priorities, and data must have the same number of elements");
2767 Linkage linkage, StringRef name,
bool dsoLocal,
2771 result.addAttribute(getAliasTypeAttrName(
result.name), TypeAttr::get(type));
2776 result.addAttribute(getThreadLocal_AttrName(
result.name),
2780 LinkageAttr::get(builder.
getContext(), linkage));
2781 result.attributes.append(attrs.begin(), attrs.end());
2791 {SymbolTable::getSymbolAttrName(),
2792 getAliasTypeAttrName(), getLinkageAttrName(),
2793 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2794 getVisibility_AttrName()});
2797 p <<
" : " <<
getType() <<
' ';
2823 if (types.size() > 1)
2831 TypeAttr::get(types[0]));
2835LogicalResult AliasOp::verify() {
2837 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2839 :
llvm::isa<PointerElementTypeInterface>(
getType());
2842 "expects type to be a valid element type for an LLVM global alias");
2845 switch (getLinkage()) {
2846 case Linkage::External:
2847 case Linkage::Internal:
2848 case Linkage::Private:
2850 case Linkage::WeakODR:
2851 case Linkage::Linkonce:
2852 case Linkage::LinkonceODR:
2853 case Linkage::AvailableExternally:
2857 <<
"'" << stringifyLinkage(getLinkage())
2858 <<
"' linkage not supported in aliases, available options: private, "
2859 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2860 "available_externally";
2866LogicalResult AliasOp::verifyRegions() {
2867 Block &
b = getInitializerBlock();
2868 auto ret = cast<ReturnOp>(
b.getTerminator());
2869 if (ret.getNumOperands() == 0 ||
2870 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2871 return emitOpError(
"initializer region must always return a pointer");
2874 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2875 if (!iface || !iface.hasNoEffect())
2876 return op.emitError()
2877 <<
"ops with side effects are not allowed in alias initializers";
2883unsigned AliasOp::getAddrSpace() {
2884 Block &initializer = getInitializerBlock();
2886 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2887 return ptrTy.getAddressSpace();
2895 Type iFuncType, StringRef resolverName,
Type resolverType,
2896 Linkage linkage, LLVM::Visibility visibility) {
2897 return build(builder,
result, name, iFuncType, resolverName, resolverType,
2899 UnnamedAddr::None, visibility);
2906 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2907 auto alias = dyn_cast<AliasOp>(symbol);
2909 Block &initBlock = alias.getInitializerBlock();
2911 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
2918 resolver = addrOp.getFunction(symbolTable);
2919 alias = addrOp.getAlias(symbolTable);
2922 return emitOpError(
"must have a function resolver");
2923 Linkage linkage = resolver.getLinkage();
2924 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
2925 return emitOpError(
"resolver must be a definition");
2926 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
2927 return emitOpError(
"resolver must return a pointer");
2928 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
2929 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
2930 return emitOpError(
"resolver has incorrect type");
2934LogicalResult IFuncOp::verify() {
2935 switch (getLinkage()) {
2936 case Linkage::External:
2937 case Linkage::Internal:
2938 case Linkage::Private:
2940 case Linkage::WeakODR:
2941 case Linkage::Linkonce:
2942 case Linkage::LinkonceODR:
2945 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
2946 <<
"' linkage not supported in ifuncs, available "
2947 "options: private, internal, linkonce, weak, "
2948 "linkonce_odr, weak_odr, or external linkage";
2960 auto containerType = v1.
getType();
2964 build(builder, state, vType, v1, v2, mask);
2978 "expected an LLVM compatible vector type");
2989LogicalResult ShuffleVectorOp::verify() {
2991 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2992 return emitOpError(
"expected a splat operation for scalable vectors");
2998OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
3000 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
3001 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
3005 if (getMask().size() != 1 || getMask()[0] != 0)
3016 assert(empty() &&
"function already has an entry block");
3021 LLVMFunctionType type = getFunctionType();
3022 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
3023 entry->
addArgument(type.getParamType(i), getLoc());
3028 StringRef name,
Type type, LLVM::Linkage linkage,
3029 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
3032 std::optional<uint64_t> functionEntryCount) {
3036 result.addAttribute(getFunctionTypeAttrName(
result.name),
3037 TypeAttr::get(type));
3039 LinkageAttr::get(builder.
getContext(), linkage));
3041 CConvAttr::get(builder.
getContext(), cconv));
3042 result.attributes.append(attrs.begin(), attrs.end());
3047 result.addAttribute(getComdatAttrName(
result.name), comdat);
3048 if (functionEntryCount)
3049 result.addAttribute(getFunctionEntryCountAttrName(
result.name),
3050 FunctionEntryCountAttr::get(
3054 std::optional<NamedAttribute> duplicate =
result.attributes.findDuplicate();
3055 if (duplicate.has_value()) {
3056 llvm::report_fatal_error(
3057 Twine(
"LLVMFuncOp propagated an attribute that is meant "
3058 "to be constructed by the builder: ") +
3059 duplicate->getName().str());
3062 if (argAttrs.empty())
3065 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
3066 "expected as many argument attribute lists as arguments");
3068 builder,
result, argAttrs, {},
3069 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3080 if (outputs.size() > 1) {
3081 parser.
emitError(loc,
"failed to construct function type: expected zero or "
3082 "one function result");
3088 for (
auto t : inputs) {
3090 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3091 "type for function arguments");
3094 llvmInputs.push_back(t);
3099 outputs.empty() ? LLVMVoidType::get(
b.getContext()) : outputs.front();
3101 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3102 "type for function results")
3106 return LLVMFunctionType::get(llvmOutput, llvmInputs,
3122 parser, LLVM::Linkage::External)));
3125 result.addAttribute(getVisibility_AttrName(
result.name),
3128 parser, LLVM::Visibility::Default)));
3131 result.addAttribute(getUnnamedAddrAttrName(
result.name),
3134 parser, LLVM::UnnamedAddr::None)));
3138 getCConvAttrName(
result.name),
3142 StringAttr nameAttr;
3152 parser,
true, entryArgs, isVariadic, resultTypes,
3157 for (
auto &arg : entryArgs)
3158 argTypes.push_back(arg.type);
3164 result.addAttribute(getFunctionTypeAttrName(
result.name),
3165 TypeAttr::get(type));
3173 auto intTy = IntegerType::get(parser.
getContext(), 32);
3175 getVscaleRangeAttrName(
result.name),
3176 LLVM::VScaleRangeAttr::get(parser.
getContext(),
3177 IntegerAttr::get(intTy, minRange),
3178 IntegerAttr::get(intTy, maxRange)));
3182 SymbolRefAttr comdat;
3187 result.addAttribute(getComdatAttrName(
result.name), comdat);
3194 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3196 auto *body =
result.addRegion();
3207 if (getLinkage() != LLVM::Linkage::External)
3208 p << stringifyLinkage(getLinkage()) <<
' ';
3209 StringRef visibility = stringifyVisibility(getVisibility_());
3210 if (!visibility.empty())
3211 p << visibility <<
' ';
3212 if (
auto unnamedAddr = getUnnamedAddr()) {
3213 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3217 if (getCConv() != LLVM::CConv::C)
3218 p << stringifyCConv(getCConv()) <<
' ';
3222 LLVMFunctionType fnType = getFunctionType();
3225 argTypes.reserve(fnType.getNumParams());
3226 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3227 argTypes.push_back(fnType.getParamType(i));
3229 Type returnType = fnType.getReturnType();
3230 if (!llvm::isa<LLVMVoidType>(returnType))
3231 resTypes.push_back(returnType);
3234 isVarArg(), resTypes);
3237 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3238 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3239 << vscale->getMaxRange().getInt() <<
')';
3242 if (
auto comdat = getComdat())
3243 p <<
" comdat(" << *comdat <<
')';
3247 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3248 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3249 getComdatAttrName(), getUnnamedAddrAttrName(),
3250 getVscaleRangeAttrName()});
3253 Region &body = getBody();
3254 if (!body.empty()) {
3265LogicalResult LLVMFuncOp::verify() {
3266 if (getLinkage() == LLVM::Linkage::Common)
3268 << stringifyLinkage(LLVM::Linkage::Common)
3275 if (getLinkage() != LLVM::Linkage::External &&
3276 getLinkage() != LLVM::Linkage::ExternWeak)
3277 return emitOpError() <<
"external functions must have '"
3278 << stringifyLinkage(LLVM::Linkage::External)
3280 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3286 if (isNoInline() && isAlwaysInline())
3287 return emitError(
"no_inline and always_inline attributes are incompatible");
3289 if (isOptimizeNone() && !isNoInline())
3290 return emitOpError(
"with optimize_none must also be no_inline");
3292 Type landingpadResultTy;
3293 StringRef diagnosticMessage;
3294 bool isLandingpadTypeConsistent =
3296 const auto checkType = [&](
Type type, StringRef errorMessage) {
3297 if (!landingpadResultTy) {
3298 landingpadResultTy = type;
3301 if (landingpadResultTy != type) {
3302 diagnosticMessage = errorMessage;
3308 .Case([&](LandingpadOp landingpad) {
3309 constexpr StringLiteral errorMessage =
3310 "'llvm.landingpad' should have a consistent result type "
3311 "inside a function";
3312 return checkType(landingpad.getType(), errorMessage);
3314 .Case([&](ResumeOp resume) {
3315 constexpr StringLiteral errorMessage =
3316 "'llvm.resume' should have a consistent input type inside a "
3318 return checkType(resume.getValue().getType(), errorMessage);
3321 }).wasInterrupted();
3322 if (!isLandingpadTypeConsistent) {
3323 assert(!diagnosticMessage.empty() &&
3324 "Expecting a non-empty diagnostic message");
3336LogicalResult LLVMFuncOp::verifyRegions() {
3340 unsigned numArguments = getFunctionType().getNumParams();
3341 Block &entryBlock = front();
3342 for (
unsigned i = 0; i < numArguments; ++i) {
3346 << i <<
" is not of LLVM type";
3352Region *LLVMFuncOp::getCallableRegion() {
3381OpFoldResult LLVM::MetadataAsValueOp::fold(FoldAdaptor) {
3382 return getMetadataAttr();
3389LogicalResult LLVM::ZeroOp::verify() {
3390 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3391 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3393 <<
"target extension type does not support zero-initializer";
3415 if (
auto vecType = dyn_cast<VectorType>(t)) {
3416 assert(!vecType.isScalable() &&
3417 "number of elements of a scalable vector type is unknown");
3418 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3420 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3421 return arrayType.getNumElements() *
3429 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3430 type = arrayType.getElementType();
3431 if (
auto vecType = dyn_cast<VectorType>(type))
3432 return vecType.getElementType();
3433 if (
auto tenType = dyn_cast<TensorType>(type))
3434 return tenType.getElementType();
3441 if (
auto vecType = dyn_cast<VectorType>(t)) {
3442 if (vecType.isScalable())
3446 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3454 LLVM::LLVMArrayType arrayType,
3456 if (arrayType.getNumElements() != arrayAttr.size())
3457 return op.emitOpError()
3458 <<
"array attribute size does not match array type size in "
3460 << dim <<
": " << arrayAttr.size() <<
" vs. "
3461 << arrayType.getNumElements();
3466 if (
auto subArrayType =
3467 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3468 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3469 if (elementsVerified.insert(elementAttr).second) {
3470 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3472 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3474 return op.emitOpError()
3475 <<
"nested attribute for sub-array in dimension " << dim
3476 <<
" at index " << idx
3477 <<
" must be a zero, or undef, or array attribute";
3491 Type elementType = arrayType.getElementType();
3492 if (isa<LLVM::LLVMPointerType>(elementType)) {
3493 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3495 LLVM::PoisonAttr>(elementAttr))
3497 return op.emitOpError()
3498 <<
"pointer array element at index " << idx
3499 <<
" must be a flat symbol reference, zero, undef, or poison";
3503 auto structType = dyn_cast<LLVM::LLVMStructType>(elementType);
3505 return op.emitOpError() <<
"for array with an array attribute must have a "
3506 "struct element type";
3510 size_t numStructElements = structType.getBody().size();
3511 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3512 if (elementsVerified.insert(elementAttr).second) {
3513 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3515 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3517 return op.emitOpError()
3518 <<
"nested attribute for struct element at index " << idx
3519 <<
" must be a zero, or undef, or array attribute";
3520 if (subArrayAttr.size() != numStructElements)
3521 return op.emitOpError()
3522 <<
"nested array attribute size for struct element at index "
3523 << idx <<
" must match struct size: " << subArrayAttr.size()
3524 <<
" vs. " << numStructElements;
3531LogicalResult LLVM::ConstantOp::verify() {
3532 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3533 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3534 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3535 !arrayType.getElementType().isInteger(8)) {
3537 << sAttr.getValue().size()
3538 <<
" i8 elements for the string constant";
3542 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3543 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3545 return emitOpError() <<
"expected array attribute for struct type";
3548 if (arrayAttr.size() != elementTypes.size()) {
3549 return emitOpError() <<
"expected array attribute of size "
3550 << elementTypes.size();
3552 for (
auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3554 return emitOpError() <<
"expected struct element types to be floating "
3555 "point type or integer type";
3557 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3558 return emitOpError() <<
"expected element of array attribute to be "
3559 "floating point or integer";
3561 if (cast<TypedAttr>(attr).
getType() != type)
3563 <<
"struct element at index " << i <<
" is of wrong type";
3568 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3569 return emitOpError() <<
"does not support target extension type.";
3580 auto verifyFloatSemantics =
3581 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3582 Type constantElementType) -> LogicalResult {
3583 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3584 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3586 <<
"attribute and type have different float semantics";
3590 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3591 if (isa<IntegerType>(constantElementType)) {
3592 if (!constantElementType.isInteger(floatWidth))
3593 return emitOpError() <<
"expected integer type of width " << floatWidth;
3601 if (isa<IntegerAttr>(getValue())) {
3602 if (!llvm::isa<IntegerType>(
getType()))
3604 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3605 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3606 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3610 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3611 if (!splatElementsAttr)
3613 <<
"scalable vector type requires a splat attribute";
3616 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3617 return emitOpError() <<
"expected vector or array type";
3620 int64_t attrNumElements = elementsAttr.getNumElements();
3623 <<
"type and attribute have a different number of elements: "
3629 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3630 return verifyFloatSemantics(floatType.getFloatSemantics(), resultElmType);
3632 if (isa<IntegerType>(attrElmType) && !isa<IntegerType>(resultElmType)) {
3634 "expected integer element type for integer elements attribute");
3636 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3639 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3642 <<
"expected array or struct type for array attribute";
3649 <<
"only supports integer, float, string or elements attributes";
3655bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3657 auto typedAttr = dyn_cast<TypedAttr>(value);
3664 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3669 if (isBuildableWith(value, type))
3670 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3675OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3683 AtomicOrdering ordering, StringRef syncscope,
3684 unsigned alignment,
bool isVolatile) {
3685 build(builder, state, val.
getType(), binOp,
ptr, val, ordering,
3686 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3689 nullptr,
nullptr,
nullptr);
3692LogicalResult AtomicRMWOp::verify() {
3693 auto valType = getVal().getType();
3694 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3695 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3696 getBinOp() == AtomicBinOp::fminimum ||
3697 getBinOp() == AtomicBinOp::fmaximum ||
3698 getBinOp() == AtomicBinOp::fminimumnum ||
3699 getBinOp() == AtomicBinOp::fmaximumnum) {
3702 return emitOpError(
"expected LLVM IR fixed vector type");
3703 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3706 "expected LLVM IR floating point type for vector element");
3708 return emitOpError(
"expected LLVM IR floating point type");
3710 }
else if (getBinOp() == AtomicBinOp::xchg) {
3713 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3715 auto intType = llvm::dyn_cast<IntegerType>(valType);
3716 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3717 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3719 return emitOpError(
"expected LLVM IR integer type");
3722 if (
static_cast<unsigned>(getOrdering()) <
3723 static_cast<unsigned>(AtomicOrdering::monotonic))
3725 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3737 auto boolType = IntegerType::get(valType.
getContext(), 1);
3738 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3743 AtomicOrdering successOrdering,
3744 AtomicOrdering failureOrdering, StringRef syncscope,
3745 unsigned alignment,
bool isWeak,
bool isVolatile) {
3747 successOrdering, failureOrdering,
3748 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3750 isVolatile,
nullptr,
3751 nullptr,
nullptr,
nullptr);
3754LogicalResult AtomicCmpXchgOp::verify() {
3755 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3757 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3758 auto valType = getVal().getType();
3762 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3763 getFailureOrdering() < AtomicOrdering::monotonic)
3764 return emitOpError(
"ordering must be at least 'monotonic'");
3765 if (getFailureOrdering() == AtomicOrdering::release ||
3766 getFailureOrdering() == AtomicOrdering::acq_rel)
3767 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3776 AtomicOrdering ordering, StringRef syncscope) {
3777 build(builder, state, ordering,
3778 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3781LogicalResult FenceOp::verify() {
3782 if (getOrdering() == AtomicOrdering::not_atomic ||
3783 getOrdering() == AtomicOrdering::unordered ||
3784 getOrdering() == AtomicOrdering::monotonic)
3785 return emitOpError(
"can be given only acquire, release, acq_rel, "
3786 "and seq_cst orderings");
3796template <
class ExtOp>
3798 IntegerType inputType, outputType;
3801 return op.emitError(
3802 "input type is a vector but output type is an integer");
3805 return op.emitError(
"input and output vectors are of incompatible shape");
3808 inputType = cast<IntegerType>(
3809 cast<VectorType>(op.getArg().getType()).getElementType());
3810 outputType = cast<IntegerType>(
3811 cast<VectorType>(op.getResult().getType()).getElementType());
3815 inputType = cast<IntegerType>(op.getArg().getType());
3816 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3818 return op.emitError(
3819 "input type is an integer but output type is a vector");
3822 if (outputType.getWidth() <= inputType.getWidth())
3823 return op.emitError(
"integer width of the output type is smaller or "
3824 "equal to the integer width of the input type");
3835 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3839 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3840 return IntegerAttr::get(
getType(), arg.getValue().zext(targetSize));
3854template <
typename T>
3856 typename T::FoldAdaptor adaptor) {
3858 if (castOp.getArg().getType() == castOp.getType())
3859 return castOp.getArg();
3860 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3862 if (prev.getArg().getType() == castOp.getType())
3863 return prev.getArg();
3865 castOp.getArgMutable().set(prev.getArg());
3866 return Value{castOp};
3871OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3875LogicalResult LLVM::BitcastOp::verify() {
3881 if (isa<LLVMByteType>(srcElemType) || isa<LLVMByteType>(dstElemType))
3884 auto resultType = llvm::dyn_cast<LLVMPointerType>(dstElemType);
3885 auto sourceType = llvm::dyn_cast<LLVMPointerType>(srcElemType);
3889 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3890 return emitOpError(
"can only cast pointers from and to pointers");
3895 auto isVector = llvm::IsaPred<VectorType>;
3899 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3900 return emitOpError(
"cannot cast pointer to vector of pointers");
3902 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3903 return emitOpError(
"cannot cast vector of pointers to pointer");
3907 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3908 return emitOpError(
"cannot cast pointers of different address spaces, "
3909 "use 'llvm.addrspacecast' instead");
3914LogicalResult LLVM::PtrToAddrOp::verify() {
3921 assert(width &&
"pointers always return an index bitwidth");
3922 if (width != integerType.getWidth())
3923 return emitOpError(
"bit-width of integer result type ")
3924 << integerType <<
" must match the pointer bitwidth (" << *width
3925 <<
") specified in the datalayout";
3934OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3938Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3946 adaptor.getDynamicIndices());
3950 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(
indices[0]))
3951 if (integer.getValue().isZero())
3955 bool changed =
false;
3957 for (
auto iter : llvm::enumerate(
indices)) {
3958 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3961 if (!
indices.isDynamicIndex(iter.index()) || !integer ||
3965 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3966 gepArgs.emplace_back(val);
3968 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3974 gepArgs.emplace_back(integer.getInt());
3982 getDynamicIndicesMutable().assign(dynamicIndices);
3983 setRawConstantIndices(rawConstantIndices);
3984 return Value{*
this};
3990Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3997 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4001 if (
rhs.getValue().getZExtValue() >=
4002 getLhs().
getType().getIntOrFloatBitWidth())
4005 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4009 return IntegerAttr::get(
getType(),
lhs.getValue().shl(
rhs.getValue()));
4017 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4021 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4025 return IntegerAttr::get(
getType(),
lhs.getValue() |
rhs.getValue());
4032LogicalResult CallIntrinsicOp::verify() {
4033 if (!getIntrin().starts_with(
"llvm."))
4034 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
4042 build(builder, state,
TypeRange{}, intrin, args,
4043 FastmathFlagsAttr{},
4050 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4051 build(builder, state,
TypeRange{}, intrin, args,
4058 mlir::Type resultType, mlir::StringAttr intrin,
4060 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
4068 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4069 build(builder, state, resultTypes, intrin, args, fastMathFlags,
4074ParseResult CallIntrinsicOp::parse(
OpAsmParser &parser,
4076 StringAttr intrinAttr;
4086 result.addAttribute(CallIntrinsicOp::getIntrinAttrName(
result.name),
4094 return mlir::failure();
4097 return mlir::failure();
4102 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
4105 if (opBundleTags && !opBundleTags.empty())
4107 CallIntrinsicOp::getOpBundleTagsAttrName(
result.name).getValue(),
4111 return mlir::failure();
4116 operands, argAttrs, resultAttrs))
4120 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
4123 opBundleOperandTypes,
4124 getOpBundleSizesAttrName(
result.name)))
4127 int32_t numOpBundleOperands = 0;
4128 for (
const auto &operands : opBundleOperands)
4129 numOpBundleOperands += operands.size();
4132 CallIntrinsicOp::getOperandSegmentSizeAttr(),
4134 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
4136 return mlir::success();
4144 p <<
"(" << args <<
")";
4147 if (!getOpBundleOperands().empty()) {
4150 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
4154 {getOperandSegmentSizesAttrName(),
4155 getOpBundleSizesAttrName(), getIntrinAttrName(),
4156 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
4157 getResAttrsAttrName()});
4163 p, args.
getTypes(), getArgAttrsAttr(),
4164 false, getResultTypes(), getResAttrsAttr());
4171LogicalResult LinkerOptionsOp::verify() {
4174 return emitOpError(
"must appear at the module level");
4182LogicalResult ModuleFlagsOp::verify() {
4185 return emitOpError(
"must appear at the module level");
4189 auto moduleFlag = dyn_cast<ModuleFlagAttrInterface>(flag);
4191 return emitOpError(
"expected a module flag attribute");
4193 moduleFlag.getModuleFlagKey(), moduleFlag.getModuleFlagValue(),
4194 [&] { return emitOpError(); })))
4196 if (moduleFlag.getModuleFlagBehavior() == ModFlagBehavior::Require)
4198 StringAttr key = moduleFlag.getModuleFlagKey();
4199 if (!seenNonRequireKeys.insert(key).second)
4201 << key.getValue() <<
"' to be unique for non-require flags";
4210void InlineAsmOp::getEffects(
4213 if (getHasSideEffects()) {
4226 getBlockAddr().getFunction());
4227 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
4230 return emitOpError(
"must reference a function defined by 'llvm.func'");
4240BlockTagOp BlockAddressOp::getBlockTagOp() {
4245 auto funcOp = dyn_cast<LLVMFuncOp>(sym);
4248 BlockTagOp blockTagOp =
nullptr;
4249 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4250 if (labelOp.getTag() == getBlockAddr().getTag()) {
4251 blockTagOp = labelOp;
4259LogicalResult BlockAddressOp::verify() {
4260 if (!getBlockTagOp())
4262 "expects an existing block label target in the referenced function");
4269OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4276 assert(
index < getNumSuccessors() &&
"invalid successor index");
4288 rangeSegments.push_back(range.size());
4302 Block *destination = nullptr;
4303 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4304 SmallVector<Type> operandTypes;
4306 if (parser.parseSuccessor(destination).failed())
4309 if (succeeded(parser.parseOptionalLParen())) {
4310 if (failed(parser.parseOperandList(
4311 operands, OpAsmParser::Delimiter::None)) ||
4312 failed(parser.parseColonTypeList(operandTypes)) ||
4313 failed(parser.parseRParen()))
4316 succOperandBlocks.push_back(destination);
4317 succOperands.emplace_back(operands);
4318 succOperandsTypes.emplace_back(operandTypes);
4321 "successor blocks")))
4332 llvm::zip(succs, succOperands),
4338 if (!succOperands.empty())
4347LogicalResult LLVM::SincosOp::verify() {
4348 auto operandType = getOperand().getType();
4349 auto resultType = getResult().getType();
4350 auto resultStructType =
4351 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4352 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4353 resultStructType.getBody()[0] != operandType ||
4354 resultStructType.getBody()[1] != operandType) {
4355 return emitOpError(
"expected result type to be an homogeneous struct with "
4356 "two elements matching the operand type, but got ")
4368 return build(builder, state, cond, {},
4380 return build(builder, state, cond,
"align",
ValueRange{
ptr, align});
4386 return build(builder, state, cond,
"separate_storage",
4396LogicalResult LLVM::masked_gather::verify() {
4397 auto ptrsVectorType = getPtrs().getType();
4398 Type expectedPtrsVectorType =
4403 if (ptrsVectorType != expectedPtrsVectorType)
4404 return emitOpError(
"expected operand #1 type to be ")
4405 << expectedPtrsVectorType;
4413LogicalResult LLVM::masked_scatter::verify() {
4414 auto ptrsVectorType = getPtrs().getType();
4415 Type expectedPtrsVectorType =
4420 if (ptrsVectorType != expectedPtrsVectorType)
4421 return emitOpError(
"expected operand #2 type to be ")
4422 << expectedPtrsVectorType;
4435 build(builder, state, resTys,
ptr, mask, passthru, argAttrs,
4443void LLVM::masked_compressstore::build(
OpBuilder &builder,
4448 build(builder, state, value,
ptr, mask, argAttrs,
4456LogicalResult InlineAsmOp::verify() {
4457 if (!getTailCallKindAttr())
4460 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4462 "tail call kind 'musttail' is not supported by this operation");
4472 Value divisor = getRhs();
4487 Value divisor = getRhs();
4499void LLVMDialect::initialize() {
4500 registerAttributes();
4503 addTypes<LLVMVoidType,
4505 LLVMMetadataType>();
4511#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4515#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4520 allowUnknownOperations();
4521 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4525#define GET_OP_CLASSES
4526#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4528#define GET_OP_CLASSES
4529#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4531LogicalResult LLVMDialect::verifyDataLayoutString(
4534 llvm::DataLayout::parse(descr);
4535 if (maybeDataLayout)
4538 std::string message;
4539 llvm::raw_string_ostream messageStream(message);
4540 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4541 reportError(
"invalid data layout descriptor: " + message);
4546LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4552 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4554 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4555 return verifyDataLayoutString(
4556 stringAttr.getValue(),
4557 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4560 << LLVM::LLVMDialect::getDataLayoutAttrName()
4561 <<
"' to be a string attributes";
4564LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4572 StringAttr name = paramAttr.
getName();
4574 auto checkUnitAttrType = [&]() -> LogicalResult {
4575 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4576 return op->
emitError() << name <<
" should be a unit attribute";
4579 auto checkTypeAttrType = [&]() -> LogicalResult {
4580 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4581 return op->
emitError() << name <<
" should be a type attribute";
4584 auto checkIntegerAttrType = [&]() -> LogicalResult {
4585 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4586 return op->
emitError() << name <<
" should be an integer attribute";
4589 auto checkPointerType = [&]() -> LogicalResult {
4590 if (!llvm::isa<LLVMPointerType>(paramType))
4592 << name <<
" attribute attached to non-pointer LLVM type";
4595 auto checkIntegerType = [&]() -> LogicalResult {
4596 if (!llvm::isa<IntegerType>(paramType))
4598 << name <<
" attribute attached to non-integer LLVM type";
4601 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4602 if (
failed(checkPointerType()))
4609 if (name == LLVMDialect::getNoAliasAttrName() ||
4610 name == LLVMDialect::getReadonlyAttrName() ||
4611 name == LLVMDialect::getReadnoneAttrName() ||
4612 name == LLVMDialect::getWriteOnlyAttrName() ||
4613 name == LLVMDialect::getNestAttrName() ||
4614 name == LLVMDialect::getNoCaptureAttrName() ||
4615 name == LLVMDialect::getNoFreeAttrName() ||
4616 name == LLVMDialect::getNonNullAttrName()) {
4617 if (
failed(checkUnitAttrType()))
4619 if (verifyValueType &&
failed(checkPointerType()))
4625 if (name == LLVMDialect::getStructRetAttrName() ||
4626 name == LLVMDialect::getByValAttrName() ||
4627 name == LLVMDialect::getByRefAttrName() ||
4628 name == LLVMDialect::getElementTypeAttrName() ||
4629 name == LLVMDialect::getInAllocaAttrName() ||
4630 name == LLVMDialect::getPreallocatedAttrName()) {
4631 if (
failed(checkTypeAttrType()))
4633 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4639 if (name == LLVMDialect::getSExtAttrName() ||
4640 name == LLVMDialect::getZExtAttrName()) {
4641 if (
failed(checkUnitAttrType()))
4643 if (verifyValueType &&
failed(checkIntegerType()))
4649 if (name == LLVMDialect::getAlignAttrName() ||
4650 name == LLVMDialect::getDereferenceableAttrName() ||
4651 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4652 if (
failed(checkIntegerAttrType()))
4654 if (verifyValueType &&
failed(checkPointerType()))
4660 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4661 if (
failed(checkIntegerAttrType()))
4667 if (name == LLVMDialect::getNoUndefAttrName() ||
4668 name == LLVMDialect::getInRegAttrName() ||
4669 name == LLVMDialect::getReturnedAttrName())
4670 return checkUnitAttrType();
4676LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4680 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4683 Type argType = funcOp.getArgumentTypes()[argIdx];
4685 return verifyParameterAttribute(op, argType, argAttr);
4688LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4692 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4695 Type resType = funcOp.getResultTypes()[resIdx];
4699 if (llvm::isa<LLVMVoidType>(resType))
4700 return op->
emitError() <<
"cannot attach result attributes to functions "
4701 "with a void return";
4705 auto name = resAttr.
getName();
4706 if (name == LLVMDialect::getAllocAlignAttrName() ||
4707 name == LLVMDialect::getAllocatedPointerAttrName() ||
4708 name == LLVMDialect::getByValAttrName() ||
4709 name == LLVMDialect::getByRefAttrName() ||
4710 name == LLVMDialect::getInAllocaAttrName() ||
4711 name == LLVMDialect::getNestAttrName() ||
4712 name == LLVMDialect::getNoCaptureAttrName() ||
4713 name == LLVMDialect::getNoFreeAttrName() ||
4714 name == LLVMDialect::getPreallocatedAttrName() ||
4715 name == LLVMDialect::getReadnoneAttrName() ||
4716 name == LLVMDialect::getReadonlyAttrName() ||
4717 name == LLVMDialect::getReturnedAttrName() ||
4718 name == LLVMDialect::getStackAlignmentAttrName() ||
4719 name == LLVMDialect::getStructRetAttrName() ||
4720 name == LLVMDialect::getWriteOnlyAttrName())
4721 return op->
emitError() << name <<
" is not a valid result attribute";
4722 return verifyParameterAttribute(op, resType, resAttr);
4730 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4731 if (isa<LLVM::LLVMPointerType>(type))
4732 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4733 if (isa<LLVM::UndefAttr>(value))
4734 return LLVM::UndefOp::create(builder, loc, type);
4735 if (isa<LLVM::PoisonAttr>(value))
4736 return LLVM::PoisonOp::create(builder, loc, type);
4737 if (isa<LLVM::ZeroAttr>(value))
4738 return LLVM::ZeroOp::create(builder, loc, type);
4739 if (isa<LLVM::MDStringAttr, LLVM::MDConstantAttr, LLVM::MDFuncAttr,
4740 LLVM::MDNodeAttr>(value))
4741 if (isa<LLVM::LLVMMetadataType>(type))
4742 return LLVM::MetadataAsValueOp::create(builder, loc, type, value);
4744 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4752 StringRef name, StringRef value,
4753 LLVM::Linkage linkage) {
4756 "expected builder to point to a block constrained in an op");
4758 builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4759 assert(module &&
"builder points to an op outside of a module");
4764 auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4765 auto global = LLVM::GlobalOp::create(
4766 moduleBuilder, loc, type,
true, linkage, name,
4769 LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4772 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4773 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4785 module = module->getParentOp();
4786 assert(module &&
"unexpected operation outside of a module");
p<< " : "<< getMemRefType()<< ", "<< getType();}static LogicalResult verifyVectorMemoryOp(Operation *op, MemRefType memrefType, VectorType vectorType) { if(memrefType.getElementType() !=vectorType.getElementType()) return op-> emitOpError("requires memref and vector types of the same elemental type")
Given a list of lists of parsed operands, populates uniqueOperands with unique operands.
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
static int parseOptionalKeywordAlternative(OpAsmParser &parser, ArrayRef< StringRef > keywords)
static ArrayAttr getLLVMAlignParamForCompressExpand(OpBuilder &builder, bool isExpandLoad, uint64_t alignment=1)
static LogicalResult verifyAtomicMemOp(OpTy memOp, Type valueType, ArrayRef< AtomicOrdering > unsupportedOrderings)
Verifies the attributes and the type of atomic memory access operations.
static RetTy parseOptionalLLVMKeyword(OpAsmParser &parser, EnumTy defaultValue)
Parse an enum from the keyword, or default to the provided default value.
static LogicalResult checkGlobalXtorData(Operation *op, ArrayAttr data)
static ParseResult parseGEPIndices(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &indices, DenseI32ArrayAttr &rawConstantIndices)
static LogicalResult verifyOperandBundles(OpType &op)
static ParseResult parseCmpOp(OpAsmParser &parser, OperationState &result)
static void printOneOpBundle(OpAsmPrinter &p, OperandRange operands, TypeRange operandTypes, StringRef tag)
static LogicalResult verifyComdat(Operation *op, std::optional< SymbolRefAttr > attr)
static LLVMFunctionType getLLVMFuncType(MLIRContext *context, TypeRange results, ValueRange args)
Constructs a LLVMFunctionType from MLIR results and args.
static void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type flagType, DenseIntElementsAttr caseValues, SuccessorRange caseDestinations, OperandRangeRange caseOperands, const TypeRangeRange &caseOperandTypes)
static ParseResult parseSwitchOpCases(OpAsmParser &parser, Type flagType, DenseIntElementsAttr &caseValues, SmallVectorImpl< Block * > &caseDestinations, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand > > &caseOperands, SmallVectorImpl< SmallVector< Type > > &caseOperandTypes)
<cases> ::= [ (case (, case )* )?
static LogicalResult verifyCallOpVarCalleeType(OpTy callOp)
Verify that the parameter and return types of the variadic callee type match the callOp argument and ...
static ParseResult parseOptionalCallFuncPtr(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operands)
Parses an optional function pointer operand before the call argument list for indirect calls,...
static bool isZeroAttribute(Attribute value)
static void printGEPIndices(OpAsmPrinter &printer, LLVM::GEPOp gepOp, OperandRange indices, DenseI32ArrayAttr rawConstantIndices)
static std::optional< ParseResult > parseOpBundles(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand > > &opBundleOperands, SmallVector< SmallVector< Type > > &opBundleOperandTypes, ArrayAttr &opBundleTags)
static LLVMStructType getValAndBoolStructType(Type valType)
Returns an LLVM struct type that contains a value type and a boolean type.
static void printOpBundles(OpAsmPrinter &p, Operation *op, OperandRangeRange opBundleOperands, TypeRangeRange opBundleOperandTypes, std::optional< ArrayAttr > opBundleTags)
static void printShuffleType(AsmPrinter &printer, Operation *op, Type v1Type, Type resType, DenseI32ArrayAttr mask)
Nothing to do when the result type is inferred.
static LogicalResult verifyBlockTags(LLVMFuncOp funcOp)
static Type buildLLVMFunctionType(OpAsmParser &parser, SMLoc loc, ArrayRef< Type > inputs, ArrayRef< Type > outputs, function_interface_impl::VariadicFlag variadicFlag)
static auto processFMFAttr(ArrayRef< NamedAttribute > attrs)
static TypeAttr getCallOpVarCalleeType(LLVMFunctionType calleeType)
Gets the variadic callee type for a LLVMFunctionType.
static Type getInsertExtractValueElementType(function_ref< InFlightDiagnostic(StringRef)> emitError, Type containerType, ArrayRef< int64_t > position)
Extract the type at position in the LLVM IR aggregate type containerType.
static ParseResult parseOneOpBundle(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand > > &opBundleOperands, SmallVector< SmallVector< Type > > &opBundleOperandTypes, SmallVector< Attribute > &opBundleTags)
static Type getElementType(Type type)
Determine the element type of type.
static void printIndirectBrOpSucessors(OpAsmPrinter &p, IndirectBrOp op, Type flagType, SuccessorRange succs, OperandRangeRange succOperands, const TypeRangeRange &succOperandsTypes)
static ParseResult resolveOpBundleOperands(OpAsmParser &parser, SMLoc loc, OperationState &state, ArrayRef< SmallVector< OpAsmParser::UnresolvedOperand > > opBundleOperands, ArrayRef< SmallVector< Type > > opBundleOperandTypes, StringAttr opBundleSizesAttrName)
static void printLLVMLinkage(OpAsmPrinter &p, Operation *, LinkageAttr val)
static LogicalResult verifyStructArrayConstant(LLVM::ConstantOp op, LLVM::LLVMArrayType arrayType, ArrayAttr arrayAttr, int dim)
Verifies the constant array represented by arrayAttr matches the provided arrayType.
static ParseResult parseCallTypeAndResolveOperands(OpAsmParser &parser, OperationState &result, bool isDirect, ArrayRef< OpAsmParser::UnresolvedOperand > operands, SmallVectorImpl< DictionaryAttr > &argAttrs, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses the type of a call operation and resolves the operands if the parsing succeeds.
static LogicalResult verifySymbolAttrUse(FlatSymbolRefAttr symbol, Operation *op, SymbolTableCollection &symbolTable)
Verifies symbol's use in op to ensure the symbol is a valid and fully defined llvm....
static Type extractVectorElementType(Type type)
Returns the elemental type of any LLVM-compatible vector type or self.
static bool hasScalableVectorType(Type t)
Check if the given type is a scalable vector type or a vector/array type that contains a nested scala...
static SmallVector< Type, 1 > getCallOpResultTypes(LLVMFunctionType calleeType)
Gets the MLIR Op-like result types of a LLVMFunctionType.
static OpFoldResult foldChainableCast(T castOp, typename T::FoldAdaptor adaptor)
Folds a cast op that can be chained.
static void destructureIndices(Type currType, ArrayRef< GEPArg > indices, SmallVectorImpl< int32_t > &rawConstantIndices, SmallVectorImpl< Value > &dynamicIndices)
Destructures the 'indices' parameter into 'rawConstantIndices' and 'dynamicIndices',...
static ParseResult parseCommonGlobalAndAlias(OpAsmParser &parser, OperationState &result)
Parse common attributes that might show up in the same order in both GlobalOp and AliasOp.
static Type getI1SameShape(Type type)
Returns a boolean type that has the same shape as type.
static void printCommonGlobalAndAlias(OpAsmPrinter &p, OpType op)
static ParseResult parseLLVMLinkage(OpAsmParser &p, LinkageAttr &val)
static Attribute getBoolAttribute(Type type, MLIRContext *ctx, bool value)
Returns a scalar or vector boolean attribute of the given type.
static LogicalResult verifyCallOpDebugInfo(CallOp callOp, LLVMFuncOp callee)
Verify that an inlinable callsite of a debug-info-bearing function in a debug-info-bearing function h...
static ParseResult parseShuffleType(AsmParser &parser, Type v1Type, Type &resType, DenseI32ArrayAttr mask)
Build the result type of a shuffle vector operation.
static LogicalResult verifyExtOp(ExtOp op)
Verifies that the given extension operation operates on consistent scalars or vectors,...
static constexpr const char kElemTypeAttrName[]
static ParseResult parseInsertExtractValueElementType(AsmParser &parser, Type &valueType, Type containerType, DenseI64ArrayAttr position)
Infer the value type from the container type and position.
static LogicalResult verifyStructIndices(Type baseGEPType, unsigned indexPos, GEPIndicesAdaptor< ValueRange > indices, function_ref< InFlightDiagnostic()> emitOpError)
For the given indices, check if they comply with baseGEPType, especially check against LLVMStructType...
static Attribute extractElementAt(Attribute attr, size_t index)
Extracts the element at the given index from an attribute.
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
static void printInsertExtractValueElementType(AsmPrinter &printer, Operation *op, Type valueType, Type containerType, DenseI64ArrayAttr position)
Nothing to print for an inferred type.
static ParseResult parseIndirectBrOpSucessors(OpAsmParser &parser, Type &flagType, SmallVectorImpl< Block * > &succOperandBlocks, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand > > &succOperands, SmallVectorImpl< SmallVector< Type > > &succOperandsTypes)
#define REGISTER_ENUM_TYPE(Ty)
static std::string diag(const llvm::Value &value)
This base class exposes generic asm parser hooks, usable across the various derived parsers.
ParseResult parseSymbolName(StringAttr &result)
Parse an -identifier and store it (without the '@' symbol) in a string attribute.
@ Paren
Parens surrounding zero or more operands.
@ None
Zero or more operands with no delimiters.
@ Square
Square brackets surrounding zero or more operands.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseColonTypeList(SmallVectorImpl< Type > &result)=0
Parse a colon followed by a type list, which must have at least one type.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseOptionalColonTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional colon followed by a type list, which if present must have at least one type.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
virtual ParseResult parseCustomAttributeWithFallback(Attribute &result, Type type, function_ref< ParseResult(Attribute &result, Type type)> parseAttribute)=0
Parse a custom attribute with the provided callback, unless the next token is #, in which case the ge...
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
virtual ParseResult parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
virtual void printAttribute(Attribute attr)
virtual void printNewline()
Print a newline and indent the printer to the start of the current operation/attribute/type.
Attributes are known-constant values of operations.
MLIRContext * getContext() const
Return the context this attribute belongs to.
This class provides an abstraction over the different types of ranges over Blocks.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
static BoolAttr get(MLIRContext *context, bool value)
This class is a general helper class for creating context-global objects like types,...
IntegerAttr getI32IntegerAttr(int32_t value)
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
IntegerAttr getI64IntegerAttr(int64_t value)
Ty getType(Args &&...args)
Get or construct an instance of the type Ty with provided arguments.
StringAttr getStringAttr(const Twine &bytes)
TypedAttr getZeroAttr(Type type)
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
MLIRContext * getContext() const
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
NamedAttribute getNamedAttr(StringRef name, Attribute val)
ArrayAttr getStrArrayAttr(ArrayRef< StringRef > values)
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
The main mechanism for performing data layout queries.
static DataLayout closest(Operation *op)
Returns the layout of the closest parent operation carrying layout info.
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.
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.