27#include "llvm/ADT/APFloat.h"
28#include "llvm/ADT/DenseSet.h"
29#include "llvm/ADT/TypeSwitch.h"
30#include "llvm/IR/DataLayout.h"
31#include "llvm/Support/Error.h"
40using mlir::LLVM::cconv::getMaxEnumValForCConv;
41using mlir::LLVM::linkage::getMaxEnumValForLinkage;
42using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
44#include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
55 if (attr.
getName() ==
"fastmathFlags") {
75 << name <<
"' does not reference a valid LLVM function";
76 if (
func.isExternal())
77 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
95 for (
const auto &en : llvm::enumerate(keywords)) {
103template <
typename Ty>
106#define REGISTER_ENUM_TYPE(Ty) \
108 struct EnumTraits<Ty> { \
109 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
110 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
123template <
typename EnumTy,
typename RetTy = EnumTy>
125 EnumTy defaultValue) {
127 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
128 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
132 return static_cast<RetTy
>(defaultValue);
133 return static_cast<RetTy
>(
index);
137 p << stringifyLinkage(val.getLinkage());
141 val = LinkageAttr::get(
149 uint64_t alignment = 1) {
155 if (alignment == 1) {
162 builder.
getNamedAttr(LLVMDialect::getAlignAttrName(), alignmentAttr);
172 int pos = isExpandLoad ? 0 : 1;
174 {alignDictAttr, emptyDictAttr, emptyDictAttr})
176 {emptyDictAttr, alignDictAttr, emptyDictAttr});
188 if (!operands.empty()) {
191 llvm::interleaveComma(operandTypes, p);
200 std::optional<ArrayAttr> opBundleTags) {
201 if (opBundleOperands.empty())
203 assert(opBundleTags &&
"expect operand bundle tags");
206 llvm::interleaveComma(
207 llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
209 auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
227 return p.
emitError(currentParserLoc,
"expect operand bundle tag");
238 opBundleOperands.push_back(std::move(operands));
239 opBundleOperandTypes.push_back(std::move(types));
240 opBundleTags.push_back(StringAttr::get(p.
getContext(), tag));
257 auto bundleParser = [&] {
267 opBundleTags = ArrayAttr::get(p.
getContext(), opBundleTagAttrs);
277 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
278 <<
", " << getOperand(1);
280 p <<
" : " << getLhs().getType();
284 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
285 <<
", " << getOperand(1);
287 p <<
" : " << getLhs().getType();
294template <
typename CmpPredicateType>
296 StringAttr predicateAttr;
299 SMLoc predicateLoc, trailingTypeLoc;
312 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
313 std::optional<ICmpPredicate> predicate =
314 symbolizeICmpPredicate(predicateAttr.getValue());
317 <<
"'" << predicateAttr.getValue()
318 <<
"' is an incorrect value of the 'predicate' attribute";
319 predicateValue =
static_cast<int64_t>(*predicate);
321 std::optional<FCmpPredicate> predicate =
322 symbolizeFCmpPredicate(predicateAttr.getValue());
325 <<
"'" << predicateAttr.getValue()
326 <<
"' is an incorrect value of the 'predicate' attribute";
327 predicateValue =
static_cast<int64_t>(*predicate);
330 result.attributes.set(
"predicate",
337 "expected LLVM dialect-compatible type");
353 ShapedType shapedType = dyn_cast<ShapedType>(type);
360 if (getPredicate() != ICmpPredicate::eq &&
361 getPredicate() != ICmpPredicate::ne)
365 if (getLhs() == getRhs())
367 getPredicate() == ICmpPredicate::eq);
370 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
372 getPredicate() == ICmpPredicate::ne);
375 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
378 getLhsMutable().assign(
rhs);
379 getRhsMutable().assign(
lhs);
397 p <<
' ' << getArraySize() <<
" x " << getElemType();
398 if (getAlignment() && *getAlignment() != 0)
400 {kElemTypeAttrName, getInallocaAttrName()});
404 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
405 p <<
" : " << funcTy;
413 SMLoc trailingTypeLoc;
425 std::optional<NamedAttribute> alignmentAttr =
426 result.attributes.getNamed(
"alignment");
427 if (alignmentAttr.has_value()) {
428 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
431 "expected integer alignment");
432 if (alignmentInt.getValue().isZero())
433 result.attributes.erase(
"alignment");
437 auto funcType = llvm::dyn_cast<FunctionType>(type);
438 if (!funcType || funcType.getNumInputs() != 1 ||
439 funcType.getNumResults() != 1)
442 "expected trailing function type with one argument and one result");
447 Type resultType = funcType.getResult(0);
448 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
451 result.addTypes({funcType.getResult(0)});
455LogicalResult AllocaOp::verify() {
457 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
458 targetExtType && !targetExtType.supportsMemOps())
460 <<
"this target extension type cannot be used in alloca";
470 assert(
index == 0 &&
"invalid successor index");
479 assert(
index < getNumSuccessors() &&
"invalid successor index");
481 : getFalseDestOperandsMutable());
487 std::optional<std::pair<uint32_t, uint32_t>> weights) {
492 static_cast<int32_t
>(weights->second)});
494 build(builder,
result, condition, trueOperands, falseOperands, weightsAttr,
495 {}, trueDest, falseDest);
509 if (!branchWeights.empty())
512 build(builder,
result, value, defaultOperands, caseOperands, caseValues,
513 weightsAttr, defaultDestination, caseDestinations);
522 if (!caseValues.empty()) {
523 ShapedType caseValueType = VectorType::get(
528 build(builder,
result, value, defaultDestination, defaultOperands,
529 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
538 if (!caseValues.empty()) {
539 ShapedType caseValueType = VectorType::get(
544 build(builder,
result, value, defaultDestination, defaultOperands,
545 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
561 auto parseCase = [&]() {
565 values.push_back(APInt(bitWidth, value,
true));
578 caseDestinations.push_back(destination);
579 caseOperands.emplace_back(operands);
580 caseOperandTypes.emplace_back(operandTypes);
586 ShapedType caseValueType =
587 VectorType::get(
static_cast<int64_t>(values.size()), flagType);
606 llvm::zip(caseValues, caseDestinations),
621LogicalResult SwitchOp::verify() {
622 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
624 getCaseValues()->size() !=
625 static_cast<int64_t>(getCaseDestinations().size())))
626 return emitOpError(
"expects number of case values to match number of "
627 "case destinations");
628 if (getCaseValues() &&
630 return emitError(
"expects case value type to match condition value type");
635 assert(
index < getNumSuccessors() &&
"invalid successor index");
637 : getCaseOperandsMutable(
index - 1));
646 getDynamicIndices());
651 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
652 return vectorType.getElementType();
669 bool requiresConst = !rawConstantIndices.empty() &&
670 isa_and_nonnull<LLVMStructType>(currType);
671 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
675 rawConstantIndices.push_back(intC.getSExtValue());
677 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
678 dynamicIndices.push_back(val);
681 rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
686 if (rawConstantIndices.size() == 1 || !currType)
690 .Case<VectorType, LLVMArrayType>([](
auto containerType) {
691 return containerType.getElementType();
693 .Case([&](LLVMStructType structType) ->
Type {
694 int64_t memberIndex = rawConstantIndices.back();
695 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
696 structType.getBody().size())
697 return structType.getBody()[memberIndex];
706 GEPNoWrapFlags noWrapFlags,
712 result.addTypes(resultType);
713 result.addAttributes(attributes);
714 result.getOrAddProperties<Properties>().rawConstantIndices =
716 result.getOrAddProperties<Properties>().noWrapFlags = noWrapFlags;
717 result.getOrAddProperties<Properties>().elem_type =
718 TypeAttr::get(elementType);
719 result.addOperands(basePtr);
720 result.addOperands(dynamicIndices);
725 GEPNoWrapFlags noWrapFlags,
727 build(builder,
result, resultType, elementType, basePtr,
737 auto idxParser = [&]() -> ParseResult {
738 int32_t constantIndex;
742 if (failed(parsedInteger.
value()))
744 constantIndices.push_back(constantIndex);
748 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
762 llvm::interleaveComma(
765 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
768 printer << cast<IntegerAttr>(cst).getInt();
778 if (indexPos >=
indices.size())
783 .Case([&](LLVMStructType structType) -> LogicalResult {
784 auto attr = dyn_cast<IntegerAttr>(
indices[indexPos]);
786 return emitOpError() <<
"expected index " << indexPos
787 <<
" indexing a struct to be constant";
789 int32_t gepIndex = attr.getInt();
792 static_cast<size_t>(gepIndex) >= elementTypes.size())
794 <<
" indexing a struct is out of bounds";
801 .Case<VectorType, LLVMArrayType>(
802 [&](
auto containerType) -> LogicalResult {
806 .Default([&](
auto otherType) -> LogicalResult {
808 <<
"type " << otherType <<
" cannot be indexed (index #"
820LogicalResult LLVM::GEPOp::verify() {
821 if (
static_cast<size_t>(
822 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
823 getDynamicIndices().size())
824 return emitOpError(
"expected as many dynamic indices as specified in '")
825 << getRawConstantIndicesAttrName().getValue() <<
"'";
827 if (getNoWrapFlags() == GEPNoWrapFlags::inboundsFlag)
828 return emitOpError(
"'inbounds_flag' cannot be used directly.");
838void LoadOp::getEffects(
847 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
848 getOrdering() != AtomicOrdering::unordered)) {
859 if (!isa<IntegerType, LLVMPointerType>(type))
864 if (bitWidth.isScalable())
867 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
871template <
typename OpTy>
875 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
878 return memOp.emitOpError(
"unsupported type ")
879 << valueType <<
" for atomic access";
880 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
881 return memOp.emitOpError(
"unsupported ordering '")
882 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
883 if (!memOp.getAlignment())
884 return memOp.emitOpError(
"expected alignment for atomic access");
887 if (memOp.getSyncscope())
888 return memOp.emitOpError(
889 "expected syncscope to be null for non-atomic access");
893LogicalResult LoadOp::verify() {
894 Type valueType = getResult().getType();
896 {AtomicOrdering::release, AtomicOrdering::acq_rel});
900 Value addr,
unsigned alignment,
bool isVolatile,
901 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
902 AtomicOrdering ordering, StringRef syncscope) {
903 build(builder, state, type, addr,
905 isNonTemporal, isInvariant, isInvariantGroup, ordering,
906 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
917void StoreOp::getEffects(
926 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
927 getOrdering() != AtomicOrdering::unordered)) {
933LogicalResult StoreOp::verify() {
934 Type valueType = getValue().getType();
936 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
940 Value addr,
unsigned alignment,
bool isVolatile,
941 bool isNonTemporal,
bool isInvariantGroup,
942 AtomicOrdering ordering, StringRef syncscope) {
943 build(builder, state, value, addr,
945 isNonTemporal, isInvariantGroup, ordering,
946 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
948 nullptr,
nullptr,
nullptr);
958 Type resultType = calleeType.getReturnType();
959 if (!isa<LLVM::LLVMVoidType>(resultType))
960 results.push_back(resultType);
966 return calleeType.isVarArg() ? TypeAttr::get(calleeType) :
nullptr;
974 resultType = LLVMVoidType::get(context);
976 resultType = results.front();
977 return LLVMFunctionType::get(resultType, llvm::to_vector(args.
getTypes()),
983 build(builder, state, results, builder.
getStringAttr(callee), args);
988 build(builder, state, results, SymbolRefAttr::get(callee), args);
993 assert(callee &&
"expected non-null callee in direct call builder");
994 build(builder, state, results,
995 nullptr, callee, args,
nullptr,
998 nullptr,
nullptr,
nullptr,
999 nullptr,
nullptr,
nullptr,
1003 nullptr,
nullptr,
nullptr,
1017 LLVMFunctionType calleeType, StringRef callee,
1019 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1023 LLVMFunctionType calleeType, StringAttr callee,
1025 build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
1043 nullptr,
nullptr,
nullptr,
1051 nullptr,
nullptr,
nullptr,
1057 LLVMFunctionType calleeType,
ValueRange args) {
1062 nullptr,
nullptr,
nullptr,
1063 nullptr,
nullptr,
nullptr,
1069 nullptr,
nullptr,
nullptr,
1084 auto calleeType =
func.getFunctionType();
1088 nullptr,
nullptr,
nullptr,
1089 nullptr,
nullptr,
nullptr,
1095 nullptr,
nullptr,
nullptr,
1113 return getOperand(0);
1119 auto symRef = cast<SymbolRefAttr>(callee);
1120 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1123 return setOperand(0, cast<Value>(callee));
1127 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1132 getCalleeOperands().size());
1139 if (callee.isExternal())
1141 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1145 auto hasSubprogram = [](
Operation *op) {
1150 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1152 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1154 return callOp.emitError()
1155 <<
"inlinable function call in a function with a DISubprogram "
1156 "location must have a debug location";
1162template <
typename OpTy>
1164 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1169 if (!varCalleeType->isVarArg())
1170 return callOp.emitOpError(
1171 "expected var_callee_type to be a variadic function type");
1175 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1176 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1177 << callOp.getArgOperands().size() <<
" parameters";
1180 for (
auto [paramType, operand] :
1181 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1182 if (paramType != operand.getType())
1183 return callOp.emitOpError()
1184 <<
"var_callee_type parameter type mismatch: " << paramType
1185 <<
" != " << operand.getType();
1188 if (!callOp.getNumResults()) {
1189 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1190 return callOp.emitOpError(
"expected var_callee_type to return void");
1192 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1193 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1194 << varCalleeType->getReturnType()
1195 <<
" != " << callOp.getResult().getType();
1200template <
typename OpType>
1203 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1205 auto isStringAttr = [](
Attribute tagAttr) {
1206 return isa<StringAttr>(tagAttr);
1208 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1209 return op.emitError(
"operand bundle tag must be a StringAttr");
1211 size_t numOpBundles = opBundleOperands.size();
1212 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1213 if (numOpBundles != numOpBundleTags)
1214 return op.emitError(
"expected ")
1215 << numOpBundles <<
" operand bundle tags, but actually got "
1231 bool isIndirect =
false;
1237 if (!getNumOperands())
1239 "must have either a `callee` attribute or at least an operand");
1240 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1242 return emitOpError(
"indirect call expects a pointer as callee: ")
1243 << getOperand(0).getType();
1252 <<
"' does not reference a symbol in the current scope";
1253 if (
auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1256 fnType = fn.getFunctionType();
1257 }
else if (
auto ifunc = dyn_cast<IFuncOp>(callee)) {
1258 fnType = ifunc.getIFuncType();
1259 }
else if (isa<AliasOp>(callee)) {
1263 fnType = getCalleeFunctionType();
1267 <<
"' does not reference a valid LLVM function, IFunc, or alias";
1271 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1273 return emitOpError(
"callee does not have a functional type: ") << fnType;
1275 if (funcType.isVarArg() && !getVarCalleeType())
1276 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1280 if (!funcType.isVarArg() &&
1281 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1282 return emitOpError() <<
"incorrect number of operands ("
1283 << (getCalleeOperands().size() - isIndirect)
1284 <<
") for callee (expecting: "
1285 << funcType.getNumParams() <<
")";
1287 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1288 return emitOpError() <<
"incorrect number of operands ("
1289 << (getCalleeOperands().size() - isIndirect)
1290 <<
") for varargs callee (expecting at least: "
1291 << funcType.getNumParams() <<
")";
1293 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1294 if (getOperand(i + isIndirect).
getType() != funcType.getParamType(i))
1295 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1296 << getOperand(i + isIndirect).getType()
1297 <<
" != " << funcType.getParamType(i);
1299 if (getNumResults() == 0 &&
1300 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1301 return emitOpError() <<
"expected function call to produce a value";
1303 if (getNumResults() != 0 &&
1304 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1306 <<
"calling function with void result must not produce values";
1308 if (getNumResults() > 1)
1310 <<
"expected LLVM function call to produce 0 or 1 result";
1312 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1313 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1314 <<
" != " << funcType.getReturnType();
1320 auto callee = getCallee();
1321 bool isDirect = callee.has_value();
1326 if (getCConv() != LLVM::CConv::C)
1327 p << stringifyCConv(getCConv()) <<
' ';
1329 if (getTailCallKind() != LLVM::TailCallKind::None)
1330 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1339 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1340 p <<
'(' << args <<
')';
1343 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1344 p <<
" vararg(" << *varCalleeType <<
")";
1346 if (!getOpBundleOperands().empty()) {
1349 getOpBundleOperands().getTypes(), getOpBundleTags());
1353 {getCalleeAttrName(), getTailCallKindAttrName(),
1354 getVarCalleeTypeAttrName(), getCConvAttrName(),
1355 getOperandSegmentSizesAttrName(),
1356 getOpBundleSizesAttrName(),
1357 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1358 getResAttrsAttrName()});
1362 p << getOperand(0).getType() <<
", ";
1366 p, args.getTypes(), getArgAttrsAttr(),
1367 false, getResultTypes(), getResAttrsAttr());
1382 types.emplace_back();
1387 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1392 resTypes, resultAttrs)) {
1394 return parser.
emitError(trailingTypesLoc,
1395 "expected direct call to have 1 trailing types");
1396 return parser.
emitError(trailingTypesLoc,
1397 "expected trailing function type");
1400 if (resTypes.size() > 1)
1401 return parser.
emitError(trailingTypesLoc,
1402 "expected function with 0 or 1 result");
1403 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1404 return parser.
emitError(trailingTypesLoc,
1405 "expected a non-void result type");
1411 llvm::append_range(types, argTypes);
1415 if (!resTypes.empty())
1416 result.addTypes(resTypes);
1429 if (failed(*parseResult))
1430 return *parseResult;
1431 operands.push_back(funcPtrOperand);
1440 StringAttr opBundleSizesAttrName) {
1441 unsigned opBundleIndex = 0;
1442 for (
const auto &[operands, types] :
1443 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1444 if (operands.size() != types.size())
1445 return parser.
emitError(loc,
"expected ")
1447 <<
" types for operand bundle operands for operand bundle #"
1448 << opBundleIndex <<
", but actually got " << types.size();
1454 opBundleSizes.reserve(opBundleOperands.size());
1455 for (
const auto &operands : opBundleOperands)
1456 opBundleSizes.push_back(operands.size());
1459 opBundleSizesAttrName,
1471 SymbolRefAttr funcAttr;
1472 TypeAttr varCalleeType;
1480 getCConvAttrName(
result.name),
1485 getTailCallKindAttrName(
result.name),
1488 parser, LLVM::TailCallKind::None)));
1493 bool isDirect = operands.empty();
1506 StringAttr varCalleeTypeAttrName =
1507 CallOp::getVarCalleeTypeAttrName(
result.name);
1519 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1522 if (opBundleTags && !opBundleTags.empty())
1523 result.addAttribute(CallOp::getOpBundleTagsAttrName(
result.name).getValue(),
1533 argAttrs, resultAttrs))
1537 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1539 opBundleOperandTypes,
1540 getOpBundleSizesAttrName(
result.name)))
1543 int32_t numOpBundleOperands = 0;
1544 for (
const auto &operands : opBundleOperands)
1545 numOpBundleOperands += operands.size();
1548 CallOp::getOperandSegmentSizeAttr(),
1550 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1554LLVMFunctionType CallOp::getCalleeFunctionType() {
1555 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1556 return *varCalleeType;
1567 auto calleeType =
func.getFunctionType();
1570 nullptr,
nullptr, normalOps, unwindOps,
1571 nullptr,
nullptr, {}, {}, normal, unwind);
1578 build(builder, state, tys,
1579 nullptr, callee, ops,
nullptr,
1580 nullptr, normalOps, unwindOps,
nullptr,
nullptr, {}, {},
1590 nullptr,
nullptr, normalOps, unwindOps,
1591 nullptr,
nullptr, {}, {}, normal, unwind);
1595 assert(
index < getNumSuccessors() &&
"invalid successor index");
1597 : getUnwindDestOperandsMutable());
1605 return getOperand(0);
1611 auto symRef = cast<SymbolRefAttr>(callee);
1612 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1615 return setOperand(0, cast<Value>(callee));
1619 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1624 getCalleeOperands().size());
1627LogicalResult InvokeOp::verify() {
1631 Block *unwindDest = getUnwindDest();
1632 if (unwindDest->
empty())
1633 return emitError(
"must have at least one operation in unwind destination");
1636 if (!isa<LandingpadOp>(unwindDest->
front()))
1637 return emitError(
"first operation in unwind destination should be a "
1638 "llvm.landingpad operation");
1647 auto callee = getCallee();
1648 bool isDirect = callee.has_value();
1653 if (getCConv() != LLVM::CConv::C)
1654 p << stringifyCConv(getCConv()) <<
' ';
1662 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1669 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1670 p <<
" vararg(" << *varCalleeType <<
")";
1672 if (!getOpBundleOperands().empty()) {
1675 getOpBundleOperands().getTypes(), getOpBundleTags());
1679 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1680 getCConvAttrName(), getVarCalleeTypeAttrName(),
1681 getOpBundleSizesAttrName(),
1682 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1683 getResAttrsAttrName()});
1687 p << getOperand(0).getType() <<
", ";
1689 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1691 false, getResultTypes(), getResAttrsAttr());
1704 SymbolRefAttr funcAttr;
1705 TypeAttr varCalleeType;
1709 Block *normalDest, *unwindDest;
1715 getCConvAttrName(
result.name),
1722 bool isDirect = operands.empty();
1738 StringAttr varCalleeTypeAttrName =
1739 InvokeOp::getVarCalleeTypeAttrName(
result.name);
1751 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1754 if (opBundleTags && !opBundleTags.empty())
1756 InvokeOp::getOpBundleTagsAttrName(
result.name).getValue(),
1766 argAttrs, resultAttrs))
1770 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1773 opBundleOperandTypes,
1774 getOpBundleSizesAttrName(
result.name)))
1777 result.addSuccessors({normalDest, unwindDest});
1778 result.addOperands(normalOperands);
1779 result.addOperands(unwindOperands);
1781 int32_t numOpBundleOperands = 0;
1782 for (
const auto &operands : opBundleOperands)
1783 numOpBundleOperands += operands.size();
1786 InvokeOp::getOperandSegmentSizeAttr(),
1788 static_cast<int32_t>(normalOperands.size()),
1789 static_cast<int32_t>(unwindOperands.size()),
1790 numOpBundleOperands}));
1794LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1795 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1796 return *varCalleeType;
1804LogicalResult LandingpadOp::verify() {
1806 if (LLVMFuncOp
func = (*this)->getParentOfType<LLVMFuncOp>()) {
1807 if (!
func.getPersonality())
1809 "llvm.landingpad needs to be in a function with a personality");
1815 if (!getCleanup() && getOperands().empty())
1816 return emitError(
"landingpad instruction expects at least one clause or "
1817 "cleanup attribute");
1819 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1820 value = getOperand(idx);
1821 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1828 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1831 <<
"global addresses expected as operand to "
1832 "bitcast used in clauses for landingpad";
1840 << idx <<
" is not a known constant - null, addressof, bitcast";
1847 p << (getCleanup() ?
" cleanup " :
" ");
1850 for (
auto value : getOperands()) {
1853 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1854 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1901 Type llvmType = containerType;
1903 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1911 for (
int64_t idx : position) {
1912 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1913 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1914 emitError(
"position out of bounds: ") << idx;
1917 llvmType = arrayType.getElementType();
1918 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1920 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1921 emitError(
"position out of bounds: ") << idx;
1924 llvmType = structType.getBody()[idx];
1926 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1937 for (
int64_t idx : position) {
1938 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1939 llvmType = structType.getBody()[idx];
1941 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1953 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
1954 ShapedType shapedType = elementsAttr.getShapedType();
1955 if (!shapedType.hasRank() || shapedType.getRank() != 1)
1957 if (
index <
static_cast<size_t>(elementsAttr.getNumElements()))
1961 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
1962 if (
index < arrayAttr.getValue().size())
1963 return arrayAttr[
index];
1966 if (isa<ZeroAttr, UndefAttr, PoisonAttr>(attr))
1971OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1972 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
1974 newPos.append(getPosition().begin(), getPosition().end());
1975 setPosition(newPos);
1976 getContainerMutable().set(extractValueOp.getContainer());
1982 for (
int64_t pos : getPosition()) {
1987 return containerAttr;
1990 Value container = getContainer();
1992 while (
auto insertValueOp = container.
getDefiningOp<InsertValueOp>()) {
1994 auto extractPosSize = extractPos.size();
1995 auto insertPosSize = insertPos.size();
1998 if (extractPos == insertPos)
1999 return insertValueOp.getValue();
2013 if (extractPosSize > insertPosSize &&
2014 extractPos.take_front(insertPosSize) == insertPos) {
2015 container = insertValueOp.getValue();
2016 extractPos = extractPos.drop_front(insertPosSize);
2032 if (insertPosSize > extractPosSize &&
2033 extractPos == insertPos.take_front(extractPosSize))
2038 container = insertValueOp.getContainer();
2044 if (container == getContainer())
2046 setPosition(extractPos);
2047 getContainerMutable().assign(container);
2051LogicalResult ExtractValueOp::verify() {
2058 if (getRes().
getType() != valueType)
2059 return emitOpError() <<
"Type mismatch: extracting from "
2060 << getContainer().getType() <<
" should produce "
2061 << valueType <<
" but this op returns "
2062 << getRes().getType();
2068 build(builder, state,
2107 LogicalResult matchAndRewrite(InsertValueOp insertOp,
2108 PatternRewriter &rewriter)
const override {
2109 bool changed =
false;
2115 auto insertBaseIdx = insertOp.getPosition()[0];
2116 for (
auto &use : insertOp->getUses()) {
2117 if (
auto extractOp = dyn_cast<ExtractValueOp>(use.getOwner())) {
2118 auto baseIdx = extractOp.getPosition()[0];
2121 if (baseIdx == insertBaseIdx)
2123 posToExtractOps[baseIdx].push_back(extractOp);
2128 Value nextContainer = insertOp.getContainer();
2129 while (!posToExtractOps.empty()) {
2131 dyn_cast_or_null<InsertValueOp>(nextContainer.
getDefiningOp());
2134 nextContainer = curInsert.getContainer();
2137 auto curInsertBaseIdx = curInsert.getPosition()[0];
2138 auto it = posToExtractOps.find(curInsertBaseIdx);
2139 if (it == posToExtractOps.end())
2143 for (
auto &extractOp : it->second) {
2145 extractOp.getContainerMutable().assign(curInsert);
2150 assert(!it->second.empty());
2152 posToExtractOps.erase(it);
2156 for (
auto &[baseIdx, extracts] : posToExtractOps) {
2157 for (
auto &extractOp : extracts) {
2159 extractOp.getContainerMutable().assign(nextContainer);
2162 assert(!extracts.empty() &&
"Empty list in map");
2172 patterns.
add<ResolveExtractValueSource>(context);
2181 [&](StringRef msg) {
2194LogicalResult InsertValueOp::verify() {
2201 if (getValue().
getType() != valueType)
2202 return emitOpError() <<
"Type mismatch: cannot insert "
2203 << getValue().getType() <<
" into "
2204 << getContainer().getType();
2213LogicalResult ReturnOp::verify() {
2214 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2218 Type expectedType = parent.getFunctionType().getReturnType();
2219 if (llvm::isa<LLVMVoidType>(expectedType)) {
2223 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2227 if (llvm::isa<LLVMVoidType>(expectedType))
2230 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2233 if (expectedType != getArg().
getType()) {
2235 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2246 return dyn_cast_or_null<GlobalOp>(
2251 return dyn_cast_or_null<LLVMFuncOp>(
2256 return dyn_cast_or_null<AliasOp>(
2261 return dyn_cast_or_null<IFuncOp>(
2270 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2271 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2272 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2273 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2275 if (!global && !function && !alias && !ifunc)
2276 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2277 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2279 LLVMPointerType type =
getType();
2280 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2281 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2282 return emitOpError(
"pointer address space must match address space of the "
2283 "referenced global or alias");
2290 return getGlobalNameAttr();
2311 getFunctionNameAttr());
2312 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2313 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2315 if (!function && !alias)
2317 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2320 if (alias.getInitializer()
2321 .walk([&](AddressOfOp addrOp) {
2322 if (addrOp.getGlobal(symbolTable))
2323 return WalkResult::interrupt();
2324 return WalkResult::advance();
2327 return emitOpError(
"must reference an alias to a function");
2330 if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2331 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2333 "target function with 'extern_weak' linkage not allowed");
2341 return DSOLocalEquivalentAttr::get(
getContext(), getFunctionNameAttr());
2349 StringRef symName) {
2352 Region *body =
result.addRegion();
2356LogicalResult ComdatOp::verifyRegions() {
2357 Region &body = getBody();
2358 for (Operation &op : body.
getOps())
2359 if (!isa<ComdatSelectorOp>(op))
2360 return op.emitError(
2361 "only comdat selector symbols can appear in a comdat region");
2371 bool isConstant, Linkage linkage, StringRef name,
2372 Attribute value, uint64_t alignment,
unsigned addrSpace,
2373 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2378 result.addAttribute(getGlobalTypeAttrName(
result.name), TypeAttr::get(type));
2383 result.addAttribute(getValueAttrName(
result.name), value);
2388 result.addAttribute(getThreadLocal_AttrName(
result.name),
2391 result.addAttribute(getComdatAttrName(
result.name), comdat);
2401 LinkageAttr::get(builder.
getContext(), linkage));
2405 result.attributes.append(attrs.begin(), attrs.end());
2407 if (!dbgExprs.empty())
2409 ArrayAttr::get(builder.
getContext(), dbgExprs));
2414template <
typename OpType>
2416 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2417 StringRef visibility = stringifyVisibility(op.getVisibility_());
2418 if (!visibility.empty())
2419 p << visibility <<
' ';
2420 if (op.getThreadLocal_())
2421 p <<
"thread_local ";
2422 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2423 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2435 if (
auto value = getValueOrNull())
2438 if (
auto comdat = getComdat())
2439 p <<
" comdat(" << *comdat <<
')';
2445 {SymbolTable::getSymbolAttrName(),
2446 getGlobalTypeAttrName(), getConstantAttrName(),
2447 getValueAttrName(), getLinkageAttrName(),
2448 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2449 getVisibility_AttrName(), getComdatAttrName()});
2452 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2456 Region &initializer = getInitializerRegion();
2457 if (!initializer.
empty()) {
2464 std::optional<SymbolRefAttr> attr) {
2469 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2470 return op->
emitError() <<
"expected comdat symbol";
2480 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2481 if (blockTags.contains(blockTagOp.getTag())) {
2482 blockTagOp.emitError()
2483 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2484 <<
"' in the same function: ";
2487 blockTags.insert(blockTagOp.getTag());
2496template <
typename OpType>
2502 OpType::getLinkageAttrName(
result.name),
2504 parser, LLVM::Linkage::External)));
2507 result.addAttribute(OpType::getVisibility_AttrName(
result.name),
2510 parser, LLVM::Visibility::Default)));
2513 result.addAttribute(OpType::getThreadLocal_AttrName(
result.name),
2517 result.addAttribute(OpType::getUnnamedAddrAttrName(
result.name),
2520 parser, LLVM::UnnamedAddr::None)));
2557 SymbolRefAttr comdat;
2562 result.addAttribute(getComdatAttrName(
result.name), comdat);
2570 if (types.size() > 1)
2574 if (types.empty()) {
2575 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2577 auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2578 strAttr.getValue().size());
2579 types.push_back(arrayType);
2582 "type can only be omitted for string globals");
2592 result.addAttribute(getGlobalTypeAttrName(
result.name),
2593 TypeAttr::get(types[0]));
2598 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2599 return intValue.getValue().isZero();
2600 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2601 return fpValue.getValue().isZero();
2602 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2604 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2606 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2611LogicalResult GlobalOp::verify() {
2613 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2615 :
llvm::isa<PointerElementTypeInterface>(
getType());
2618 "expects type to be a valid element type for an LLVM global");
2620 return emitOpError(
"must appear at the module level");
2622 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2623 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2624 IntegerType elementType =
2625 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) :
nullptr;
2626 if (!elementType || elementType.getWidth() != 8 ||
2627 type.getNumElements() != strAttr.getValue().size())
2629 "requires an i8 array type of the length equal to that of the string "
2633 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2634 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2636 <<
"this target extension type cannot be used in a global";
2639 return emitOpError() <<
"global with target extension type can only be "
2640 "initialized with zero-initializer";
2643 if (getLinkage() == Linkage::Common) {
2644 if (
Attribute value = getValueOrNull()) {
2647 <<
"expected zero value for '"
2648 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2653 if (getLinkage() == Linkage::Appending) {
2654 if (!llvm::isa<LLVMArrayType>(
getType())) {
2655 return emitOpError() <<
"expected array type for '"
2656 << stringifyLinkage(Linkage::Appending)
2664 std::optional<uint64_t> alignAttr = getAlignment();
2665 if (alignAttr.has_value()) {
2666 uint64_t value = alignAttr.value();
2667 if (!llvm::isPowerOf2_64(value))
2668 return emitError() <<
"alignment attribute is not a power of 2";
2674LogicalResult GlobalOp::verifyRegions() {
2675 if (
Block *
b = getInitializerBlock()) {
2676 ReturnOp ret = cast<ReturnOp>(
b->getTerminator());
2677 if (ret.operand_type_begin() == ret.operand_type_end())
2678 return emitOpError(
"initializer region cannot return void");
2679 if (*ret.operand_type_begin() !=
getType())
2681 << *ret.operand_type_begin() <<
" does not match global type "
2685 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2686 if (!iface || !iface.hasNoEffect())
2687 return op.emitError()
2688 <<
"ops with side effects not allowed in global initializers";
2691 if (getValueOrNull())
2692 return emitOpError(
"cannot have both initializer value and region");
2707 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2710 return op->
emitError(
"data element must be symbol or #llvm.zero");
2723LogicalResult GlobalCtorsOp::verify() {
2727 if (getCtors().size() == getPriorities().size() &&
2728 getCtors().size() == getData().size())
2731 "ctors, priorities, and data must have the same number of elements");
2748LogicalResult GlobalDtorsOp::verify() {
2752 if (getDtors().size() == getPriorities().size() &&
2753 getDtors().size() == getData().size())
2756 "dtors, priorities, and data must have the same number of elements");
2764 Linkage linkage, StringRef name,
bool dsoLocal,
2768 result.addAttribute(getAliasTypeAttrName(
result.name), TypeAttr::get(type));
2773 result.addAttribute(getThreadLocal_AttrName(
result.name),
2777 LinkageAttr::get(builder.
getContext(), linkage));
2778 result.attributes.append(attrs.begin(), attrs.end());
2788 {SymbolTable::getSymbolAttrName(),
2789 getAliasTypeAttrName(), getLinkageAttrName(),
2790 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2791 getVisibility_AttrName()});
2794 p <<
" : " <<
getType() <<
' ';
2820 if (types.size() > 1)
2828 TypeAttr::get(types[0]));
2832LogicalResult AliasOp::verify() {
2834 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2836 :
llvm::isa<PointerElementTypeInterface>(
getType());
2839 "expects type to be a valid element type for an LLVM global alias");
2842 switch (getLinkage()) {
2843 case Linkage::External:
2844 case Linkage::Internal:
2845 case Linkage::Private:
2847 case Linkage::WeakODR:
2848 case Linkage::Linkonce:
2849 case Linkage::LinkonceODR:
2850 case Linkage::AvailableExternally:
2854 <<
"'" << stringifyLinkage(getLinkage())
2855 <<
"' linkage not supported in aliases, available options: private, "
2856 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2857 "available_externally";
2863LogicalResult AliasOp::verifyRegions() {
2864 Block &
b = getInitializerBlock();
2865 auto ret = cast<ReturnOp>(
b.getTerminator());
2866 if (ret.getNumOperands() == 0 ||
2867 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2868 return emitOpError(
"initializer region must always return a pointer");
2871 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2872 if (!iface || !iface.hasNoEffect())
2873 return op.emitError()
2874 <<
"ops with side effects are not allowed in alias initializers";
2880unsigned AliasOp::getAddrSpace() {
2881 Block &initializer = getInitializerBlock();
2883 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2884 return ptrTy.getAddressSpace();
2892 Type iFuncType, StringRef resolverName,
Type resolverType,
2893 Linkage linkage, LLVM::Visibility visibility) {
2894 return build(builder,
result, name, iFuncType, resolverName, resolverType,
2896 UnnamedAddr::None, visibility);
2903 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2904 auto alias = dyn_cast<AliasOp>(symbol);
2906 Block &initBlock = alias.getInitializerBlock();
2908 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
2915 resolver = addrOp.getFunction(symbolTable);
2916 alias = addrOp.getAlias(symbolTable);
2919 return emitOpError(
"must have a function resolver");
2920 Linkage linkage = resolver.getLinkage();
2921 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
2922 return emitOpError(
"resolver must be a definition");
2923 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
2924 return emitOpError(
"resolver must return a pointer");
2925 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
2926 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
2927 return emitOpError(
"resolver has incorrect type");
2931LogicalResult IFuncOp::verify() {
2932 switch (getLinkage()) {
2933 case Linkage::External:
2934 case Linkage::Internal:
2935 case Linkage::Private:
2937 case Linkage::WeakODR:
2938 case Linkage::Linkonce:
2939 case Linkage::LinkonceODR:
2942 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
2943 <<
"' linkage not supported in ifuncs, available "
2944 "options: private, internal, linkonce, weak, "
2945 "linkonce_odr, weak_odr, or external linkage";
2957 auto containerType = v1.
getType();
2961 build(builder, state, vType, v1, v2, mask);
2975 "expected an LLVM compatible vector type");
2986LogicalResult ShuffleVectorOp::verify() {
2988 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2989 return emitOpError(
"expected a splat operation for scalable vectors");
2995OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
2997 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
2998 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
3002 if (getMask().size() != 1 || getMask()[0] != 0)
3013 assert(empty() &&
"function already has an entry block");
3018 LLVMFunctionType type = getFunctionType();
3019 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
3020 entry->
addArgument(type.getParamType(i), getLoc());
3025 StringRef name,
Type type, LLVM::Linkage linkage,
3026 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
3029 std::optional<uint64_t> functionEntryCount) {
3033 result.addAttribute(getFunctionTypeAttrName(
result.name),
3034 TypeAttr::get(type));
3036 LinkageAttr::get(builder.
getContext(), linkage));
3038 CConvAttr::get(builder.
getContext(), cconv));
3039 result.attributes.append(attrs.begin(), attrs.end());
3044 result.addAttribute(getComdatAttrName(
result.name), comdat);
3045 if (functionEntryCount)
3046 result.addAttribute(getFunctionEntryCountAttrName(
result.name),
3049 std::optional<NamedAttribute> duplicate =
result.attributes.findDuplicate();
3050 if (duplicate.has_value()) {
3051 llvm::report_fatal_error(
3052 Twine(
"LLVMFuncOp propagated an attribute that is meant "
3053 "to be constructed by the builder: ") +
3054 duplicate->getName().str());
3057 if (argAttrs.empty())
3060 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
3061 "expected as many argument attribute lists as arguments");
3063 builder,
result, argAttrs, {},
3064 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3075 if (outputs.size() > 1) {
3076 parser.
emitError(loc,
"failed to construct function type: expected zero or "
3077 "one function result");
3083 for (
auto t : inputs) {
3085 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3086 "type for function arguments");
3089 llvmInputs.push_back(t);
3094 outputs.empty() ? LLVMVoidType::get(
b.getContext()) : outputs.front();
3096 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3097 "type for function results")
3101 return LLVMFunctionType::get(llvmOutput, llvmInputs,
3117 parser, LLVM::Linkage::External)));
3120 result.addAttribute(getVisibility_AttrName(
result.name),
3123 parser, LLVM::Visibility::Default)));
3126 result.addAttribute(getUnnamedAddrAttrName(
result.name),
3129 parser, LLVM::UnnamedAddr::None)));
3133 getCConvAttrName(
result.name),
3137 StringAttr nameAttr;
3147 parser,
true, entryArgs, isVariadic, resultTypes,
3152 for (
auto &arg : entryArgs)
3153 argTypes.push_back(arg.type);
3159 result.addAttribute(getFunctionTypeAttrName(
result.name),
3160 TypeAttr::get(type));
3168 auto intTy = IntegerType::get(parser.
getContext(), 32);
3170 getVscaleRangeAttrName(
result.name),
3171 LLVM::VScaleRangeAttr::get(parser.
getContext(),
3172 IntegerAttr::get(intTy, minRange),
3173 IntegerAttr::get(intTy, maxRange)));
3177 SymbolRefAttr comdat;
3182 result.addAttribute(getComdatAttrName(
result.name), comdat);
3189 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3191 auto *body =
result.addRegion();
3202 if (getLinkage() != LLVM::Linkage::External)
3203 p << stringifyLinkage(getLinkage()) <<
' ';
3204 StringRef visibility = stringifyVisibility(getVisibility_());
3205 if (!visibility.empty())
3206 p << visibility <<
' ';
3207 if (
auto unnamedAddr = getUnnamedAddr()) {
3208 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3212 if (getCConv() != LLVM::CConv::C)
3213 p << stringifyCConv(getCConv()) <<
' ';
3217 LLVMFunctionType fnType = getFunctionType();
3220 argTypes.reserve(fnType.getNumParams());
3221 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3222 argTypes.push_back(fnType.getParamType(i));
3224 Type returnType = fnType.getReturnType();
3225 if (!llvm::isa<LLVMVoidType>(returnType))
3226 resTypes.push_back(returnType);
3229 isVarArg(), resTypes);
3232 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3233 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3234 << vscale->getMaxRange().getInt() <<
')';
3237 if (
auto comdat = getComdat())
3238 p <<
" comdat(" << *comdat <<
')';
3242 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3243 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3244 getComdatAttrName(), getUnnamedAddrAttrName(),
3245 getVscaleRangeAttrName()});
3248 Region &body = getBody();
3249 if (!body.empty()) {
3260LogicalResult LLVMFuncOp::verify() {
3261 if (getLinkage() == LLVM::Linkage::Common)
3263 << stringifyLinkage(LLVM::Linkage::Common)
3270 if (getLinkage() != LLVM::Linkage::External &&
3271 getLinkage() != LLVM::Linkage::ExternWeak)
3272 return emitOpError() <<
"external functions must have '"
3273 << stringifyLinkage(LLVM::Linkage::External)
3275 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3281 if (isNoInline() && isAlwaysInline())
3282 return emitError(
"no_inline and always_inline attributes are incompatible");
3284 if (isOptimizeNone() && !isNoInline())
3285 return emitOpError(
"with optimize_none must also be no_inline");
3287 Type landingpadResultTy;
3288 StringRef diagnosticMessage;
3289 bool isLandingpadTypeConsistent =
3291 const auto checkType = [&](
Type type, StringRef errorMessage) {
3292 if (!landingpadResultTy) {
3293 landingpadResultTy = type;
3296 if (landingpadResultTy != type) {
3297 diagnosticMessage = errorMessage;
3303 .Case([&](LandingpadOp landingpad) {
3304 constexpr StringLiteral errorMessage =
3305 "'llvm.landingpad' should have a consistent result type "
3306 "inside a function";
3307 return checkType(landingpad.getType(), errorMessage);
3309 .Case([&](ResumeOp resume) {
3310 constexpr StringLiteral errorMessage =
3311 "'llvm.resume' should have a consistent input type inside a "
3313 return checkType(resume.getValue().getType(), errorMessage);
3316 }).wasInterrupted();
3317 if (!isLandingpadTypeConsistent) {
3318 assert(!diagnosticMessage.empty() &&
3319 "Expecting a non-empty diagnostic message");
3331LogicalResult LLVMFuncOp::verifyRegions() {
3335 unsigned numArguments = getFunctionType().getNumParams();
3336 Block &entryBlock = front();
3337 for (
unsigned i = 0; i < numArguments; ++i) {
3341 << i <<
" is not of LLVM type";
3347Region *LLVMFuncOp::getCallableRegion() {
3376OpFoldResult LLVM::MetadataAsValueOp::fold(FoldAdaptor) {
3377 return getMetadataAttr();
3384LogicalResult LLVM::ZeroOp::verify() {
3385 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3386 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3388 <<
"target extension type does not support zero-initializer";
3410 if (
auto vecType = dyn_cast<VectorType>(t)) {
3411 assert(!vecType.isScalable() &&
3412 "number of elements of a scalable vector type is unknown");
3413 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3415 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3416 return arrayType.getNumElements() *
3424 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3425 type = arrayType.getElementType();
3426 if (
auto vecType = dyn_cast<VectorType>(type))
3427 return vecType.getElementType();
3428 if (
auto tenType = dyn_cast<TensorType>(type))
3429 return tenType.getElementType();
3436 if (
auto vecType = dyn_cast<VectorType>(t)) {
3437 if (vecType.isScalable())
3441 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3449 LLVM::LLVMArrayType arrayType,
3451 if (arrayType.getNumElements() != arrayAttr.size())
3452 return op.emitOpError()
3453 <<
"array attribute size does not match array type size in "
3455 << dim <<
": " << arrayAttr.size() <<
" vs. "
3456 << arrayType.getNumElements();
3461 if (
auto subArrayType =
3462 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3463 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3464 if (elementsVerified.insert(elementAttr).second) {
3465 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3467 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3469 return op.emitOpError()
3470 <<
"nested attribute for sub-array in dimension " << dim
3471 <<
" at index " << idx
3472 <<
" must be a zero, or undef, or array attribute";
3486 Type elementType = arrayType.getElementType();
3487 if (isa<LLVM::LLVMPointerType>(elementType)) {
3488 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3490 LLVM::PoisonAttr>(elementAttr))
3492 return op.emitOpError()
3493 <<
"pointer array element at index " << idx
3494 <<
" must be a flat symbol reference, zero, undef, or poison";
3498 auto structType = dyn_cast<LLVM::LLVMStructType>(elementType);
3500 return op.emitOpError() <<
"for array with an array attribute must have a "
3501 "struct element type";
3505 size_t numStructElements = structType.getBody().size();
3506 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3507 if (elementsVerified.insert(elementAttr).second) {
3508 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3510 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3512 return op.emitOpError()
3513 <<
"nested attribute for struct element at index " << idx
3514 <<
" must be a zero, or undef, or array attribute";
3515 if (subArrayAttr.size() != numStructElements)
3516 return op.emitOpError()
3517 <<
"nested array attribute size for struct element at index "
3518 << idx <<
" must match struct size: " << subArrayAttr.size()
3519 <<
" vs. " << numStructElements;
3526LogicalResult LLVM::ConstantOp::verify() {
3527 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3528 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3529 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3530 !arrayType.getElementType().isInteger(8)) {
3532 << sAttr.getValue().size()
3533 <<
" i8 elements for the string constant";
3537 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3538 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3540 return emitOpError() <<
"expected array attribute for struct type";
3543 if (arrayAttr.size() != elementTypes.size()) {
3544 return emitOpError() <<
"expected array attribute of size "
3545 << elementTypes.size();
3547 for (
auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3549 return emitOpError() <<
"expected struct element types to be floating "
3550 "point type or integer type";
3552 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3553 return emitOpError() <<
"expected element of array attribute to be "
3554 "floating point or integer";
3556 if (cast<TypedAttr>(attr).
getType() != type)
3558 <<
"struct element at index " << i <<
" is of wrong type";
3563 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3564 return emitOpError() <<
"does not support target extension type.";
3575 auto verifyFloatSemantics =
3576 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3577 Type constantElementType) -> LogicalResult {
3578 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3579 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3581 <<
"attribute and type have different float semantics";
3585 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3586 if (isa<IntegerType>(constantElementType)) {
3587 if (!constantElementType.isInteger(floatWidth))
3588 return emitOpError() <<
"expected integer type of width " << floatWidth;
3596 if (isa<IntegerAttr>(getValue())) {
3597 if (!llvm::isa<IntegerType>(
getType()))
3599 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3600 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3601 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3605 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3606 if (!splatElementsAttr)
3608 <<
"scalable vector type requires a splat attribute";
3611 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3612 return emitOpError() <<
"expected vector or array type";
3615 int64_t attrNumElements = elementsAttr.getNumElements();
3618 <<
"type and attribute have a different number of elements: "
3624 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3625 return verifyFloatSemantics(floatType.getFloatSemantics(), resultElmType);
3627 if (isa<IntegerType>(attrElmType) && !isa<IntegerType>(resultElmType)) {
3629 "expected integer element type for integer elements attribute");
3631 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3634 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3637 <<
"expected array or struct type for array attribute";
3644 <<
"only supports integer, float, string or elements attributes";
3650bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3652 auto typedAttr = dyn_cast<TypedAttr>(value);
3659 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3664 if (isBuildableWith(value, type))
3665 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3670OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3678 AtomicOrdering ordering, StringRef syncscope,
3679 unsigned alignment,
bool isVolatile) {
3680 build(builder, state, val.
getType(), binOp,
ptr, val, ordering,
3681 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3684 nullptr,
nullptr,
nullptr);
3687LogicalResult AtomicRMWOp::verify() {
3688 auto valType = getVal().getType();
3689 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3690 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3691 getBinOp() == AtomicBinOp::fminimum ||
3692 getBinOp() == AtomicBinOp::fmaximum ||
3693 getBinOp() == AtomicBinOp::fminimumnum ||
3694 getBinOp() == AtomicBinOp::fmaximumnum) {
3697 return emitOpError(
"expected LLVM IR fixed vector type");
3698 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3701 "expected LLVM IR floating point type for vector element");
3703 return emitOpError(
"expected LLVM IR floating point type");
3705 }
else if (getBinOp() == AtomicBinOp::xchg) {
3708 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3710 auto intType = llvm::dyn_cast<IntegerType>(valType);
3711 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3712 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3714 return emitOpError(
"expected LLVM IR integer type");
3717 if (
static_cast<unsigned>(getOrdering()) <
3718 static_cast<unsigned>(AtomicOrdering::monotonic))
3720 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3732 auto boolType = IntegerType::get(valType.
getContext(), 1);
3733 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3738 AtomicOrdering successOrdering,
3739 AtomicOrdering failureOrdering, StringRef syncscope,
3740 unsigned alignment,
bool isWeak,
bool isVolatile) {
3742 successOrdering, failureOrdering,
3743 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3745 isVolatile,
nullptr,
3746 nullptr,
nullptr,
nullptr);
3749LogicalResult AtomicCmpXchgOp::verify() {
3750 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3752 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3753 auto valType = getVal().getType();
3757 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3758 getFailureOrdering() < AtomicOrdering::monotonic)
3759 return emitOpError(
"ordering must be at least 'monotonic'");
3760 if (getFailureOrdering() == AtomicOrdering::release ||
3761 getFailureOrdering() == AtomicOrdering::acq_rel)
3762 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3771 AtomicOrdering ordering, StringRef syncscope) {
3772 build(builder, state, ordering,
3773 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3776LogicalResult FenceOp::verify() {
3777 if (getOrdering() == AtomicOrdering::not_atomic ||
3778 getOrdering() == AtomicOrdering::unordered ||
3779 getOrdering() == AtomicOrdering::monotonic)
3780 return emitOpError(
"can be given only acquire, release, acq_rel, "
3781 "and seq_cst orderings");
3791template <
class ExtOp>
3793 IntegerType inputType, outputType;
3796 return op.emitError(
3797 "input type is a vector but output type is an integer");
3800 return op.emitError(
"input and output vectors are of incompatible shape");
3803 inputType = cast<IntegerType>(
3804 cast<VectorType>(op.getArg().getType()).getElementType());
3805 outputType = cast<IntegerType>(
3806 cast<VectorType>(op.getResult().getType()).getElementType());
3810 inputType = cast<IntegerType>(op.getArg().getType());
3811 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3813 return op.emitError(
3814 "input type is an integer but output type is a vector");
3817 if (outputType.getWidth() <= inputType.getWidth())
3818 return op.emitError(
"integer width of the output type is smaller or "
3819 "equal to the integer width of the input type");
3830 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3834 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3835 return IntegerAttr::get(
getType(), arg.getValue().zext(targetSize));
3849template <
typename T>
3851 typename T::FoldAdaptor adaptor) {
3853 if (castOp.getArg().getType() == castOp.getType())
3854 return castOp.getArg();
3855 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3857 if (prev.getArg().getType() == castOp.getType())
3858 return prev.getArg();
3860 castOp.getArgMutable().set(prev.getArg());
3861 return Value{castOp};
3866OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3870LogicalResult LLVM::BitcastOp::verify() {
3876 if (isa<LLVMByteType>(srcElemType) || isa<LLVMByteType>(dstElemType))
3879 auto resultType = llvm::dyn_cast<LLVMPointerType>(dstElemType);
3880 auto sourceType = llvm::dyn_cast<LLVMPointerType>(srcElemType);
3884 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3885 return emitOpError(
"can only cast pointers from and to pointers");
3890 auto isVector = llvm::IsaPred<VectorType>;
3894 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3895 return emitOpError(
"cannot cast pointer to vector of pointers");
3897 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3898 return emitOpError(
"cannot cast vector of pointers to pointer");
3902 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3903 return emitOpError(
"cannot cast pointers of different address spaces, "
3904 "use 'llvm.addrspacecast' instead");
3909LogicalResult LLVM::PtrToAddrOp::verify() {
3916 assert(width &&
"pointers always return an index bitwidth");
3917 if (width != integerType.getWidth())
3918 return emitOpError(
"bit-width of integer result type ")
3919 << integerType <<
" must match the pointer bitwidth (" << *width
3920 <<
") specified in the datalayout";
3929OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3933Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3941 adaptor.getDynamicIndices());
3945 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(
indices[0]))
3946 if (integer.getValue().isZero())
3950 bool changed =
false;
3952 for (
auto iter : llvm::enumerate(
indices)) {
3953 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3956 if (!
indices.isDynamicIndex(iter.index()) || !integer ||
3960 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3961 gepArgs.emplace_back(val);
3963 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3969 gepArgs.emplace_back(integer.getInt());
3977 getDynamicIndicesMutable().assign(dynamicIndices);
3978 setRawConstantIndices(rawConstantIndices);
3979 return Value{*
this};
3985Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3992 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3996 if (
rhs.getValue().getZExtValue() >=
3997 getLhs().
getType().getIntOrFloatBitWidth())
4000 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4004 return IntegerAttr::get(
getType(),
lhs.getValue().shl(
rhs.getValue()));
4012 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4016 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4020 return IntegerAttr::get(
getType(),
lhs.getValue() |
rhs.getValue());
4027LogicalResult CallIntrinsicOp::verify() {
4028 if (!getIntrin().starts_with(
"llvm."))
4029 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
4037 build(builder, state,
TypeRange{}, intrin, args,
4038 FastmathFlagsAttr{},
4045 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4046 build(builder, state,
TypeRange{}, intrin, args,
4053 mlir::Type resultType, mlir::StringAttr intrin,
4055 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
4063 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4064 build(builder, state, resultTypes, intrin, args, fastMathFlags,
4069ParseResult CallIntrinsicOp::parse(
OpAsmParser &parser,
4071 StringAttr intrinAttr;
4081 result.addAttribute(CallIntrinsicOp::getIntrinAttrName(
result.name),
4089 return mlir::failure();
4092 return mlir::failure();
4097 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
4100 if (opBundleTags && !opBundleTags.empty())
4102 CallIntrinsicOp::getOpBundleTagsAttrName(
result.name).getValue(),
4106 return mlir::failure();
4111 operands, argAttrs, resultAttrs))
4115 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
4118 opBundleOperandTypes,
4119 getOpBundleSizesAttrName(
result.name)))
4122 int32_t numOpBundleOperands = 0;
4123 for (
const auto &operands : opBundleOperands)
4124 numOpBundleOperands += operands.size();
4127 CallIntrinsicOp::getOperandSegmentSizeAttr(),
4129 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
4131 return mlir::success();
4139 p <<
"(" << args <<
")";
4142 if (!getOpBundleOperands().empty()) {
4145 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
4149 {getOperandSegmentSizesAttrName(),
4150 getOpBundleSizesAttrName(), getIntrinAttrName(),
4151 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
4152 getResAttrsAttrName()});
4158 p, args.
getTypes(), getArgAttrsAttr(),
4159 false, getResultTypes(), getResAttrsAttr());
4166LogicalResult LinkerOptionsOp::verify() {
4169 return emitOpError(
"must appear at the module level");
4177LogicalResult ModuleFlagsOp::verify() {
4180 return emitOpError(
"must appear at the module level");
4184 auto moduleFlag = dyn_cast<ModuleFlagAttrInterface>(flag);
4186 return emitOpError(
"expected a module flag attribute");
4188 moduleFlag.getModuleFlagKey(), moduleFlag.getModuleFlagValue(),
4189 [&] { return emitOpError(); })))
4191 if (moduleFlag.getModuleFlagBehavior() == ModFlagBehavior::Require)
4193 StringAttr key = moduleFlag.getModuleFlagKey();
4194 if (!seenNonRequireKeys.insert(key).second)
4196 << key.getValue() <<
"' to be unique for non-require flags";
4205void InlineAsmOp::getEffects(
4208 if (getHasSideEffects()) {
4221 getBlockAddr().getFunction());
4222 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
4225 return emitOpError(
"must reference a function defined by 'llvm.func'");
4235BlockTagOp BlockAddressOp::getBlockTagOp() {
4240 auto funcOp = dyn_cast<LLVMFuncOp>(sym);
4243 BlockTagOp blockTagOp =
nullptr;
4244 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4245 if (labelOp.getTag() == getBlockAddr().getTag()) {
4246 blockTagOp = labelOp;
4254LogicalResult BlockAddressOp::verify() {
4255 if (!getBlockTagOp())
4257 "expects an existing block label target in the referenced function");
4264OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4271 assert(
index < getNumSuccessors() &&
"invalid successor index");
4283 rangeSegments.push_back(range.size());
4297 Block *destination = nullptr;
4298 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4299 SmallVector<Type> operandTypes;
4301 if (parser.parseSuccessor(destination).failed())
4304 if (succeeded(parser.parseOptionalLParen())) {
4305 if (failed(parser.parseOperandList(
4306 operands, OpAsmParser::Delimiter::None)) ||
4307 failed(parser.parseColonTypeList(operandTypes)) ||
4308 failed(parser.parseRParen()))
4311 succOperandBlocks.push_back(destination);
4312 succOperands.emplace_back(operands);
4313 succOperandsTypes.emplace_back(operandTypes);
4316 "successor blocks")))
4327 llvm::zip(succs, succOperands),
4333 if (!succOperands.empty())
4342LogicalResult LLVM::SincosOp::verify() {
4343 auto operandType = getOperand().getType();
4344 auto resultType = getResult().getType();
4345 auto resultStructType =
4346 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4347 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4348 resultStructType.getBody()[0] != operandType ||
4349 resultStructType.getBody()[1] != operandType) {
4350 return emitOpError(
"expected result type to be an homogeneous struct with "
4351 "two elements matching the operand type, but got ")
4363 return build(builder, state, cond, {},
4375 return build(builder, state, cond,
"align",
ValueRange{
ptr, align});
4381 return build(builder, state, cond,
"separate_storage",
4391LogicalResult LLVM::masked_gather::verify() {
4392 auto ptrsVectorType = getPtrs().getType();
4393 Type expectedPtrsVectorType =
4398 if (ptrsVectorType != expectedPtrsVectorType)
4399 return emitOpError(
"expected operand #1 type to be ")
4400 << expectedPtrsVectorType;
4408LogicalResult LLVM::masked_scatter::verify() {
4409 auto ptrsVectorType = getPtrs().getType();
4410 Type expectedPtrsVectorType =
4415 if (ptrsVectorType != expectedPtrsVectorType)
4416 return emitOpError(
"expected operand #2 type to be ")
4417 << expectedPtrsVectorType;
4430 build(builder, state, resTys,
ptr, mask, passthru, argAttrs,
4438void LLVM::masked_compressstore::build(
OpBuilder &builder,
4443 build(builder, state, value,
ptr, mask, argAttrs,
4451LogicalResult InlineAsmOp::verify() {
4452 if (!getTailCallKindAttr())
4455 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4457 "tail call kind 'musttail' is not supported by this operation");
4467 Value divisor = getRhs();
4482 Value divisor = getRhs();
4494void LLVMDialect::initialize() {
4495 registerAttributes();
4498 addTypes<LLVMVoidType,
4500 LLVMMetadataType>();
4506#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4510#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4515 allowUnknownOperations();
4516 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4520#define GET_OP_CLASSES
4521#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4523#define GET_OP_CLASSES
4524#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4526LogicalResult LLVMDialect::verifyDataLayoutString(
4529 llvm::DataLayout::parse(descr);
4530 if (maybeDataLayout)
4533 std::string message;
4534 llvm::raw_string_ostream messageStream(message);
4535 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4536 reportError(
"invalid data layout descriptor: " + message);
4541LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4547 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4549 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4550 return verifyDataLayoutString(
4551 stringAttr.getValue(),
4552 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4555 << LLVM::LLVMDialect::getDataLayoutAttrName()
4556 <<
"' to be a string attributes";
4559LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4567 StringAttr name = paramAttr.
getName();
4569 auto checkUnitAttrType = [&]() -> LogicalResult {
4570 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4571 return op->
emitError() << name <<
" should be a unit attribute";
4574 auto checkTypeAttrType = [&]() -> LogicalResult {
4575 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4576 return op->
emitError() << name <<
" should be a type attribute";
4579 auto checkIntegerAttrType = [&]() -> LogicalResult {
4580 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4581 return op->
emitError() << name <<
" should be an integer attribute";
4584 auto checkPointerType = [&]() -> LogicalResult {
4585 if (!llvm::isa<LLVMPointerType>(paramType))
4587 << name <<
" attribute attached to non-pointer LLVM type";
4590 auto checkIntegerType = [&]() -> LogicalResult {
4591 if (!llvm::isa<IntegerType>(paramType))
4593 << name <<
" attribute attached to non-integer LLVM type";
4596 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4597 if (
failed(checkPointerType()))
4604 if (name == LLVMDialect::getNoAliasAttrName() ||
4605 name == LLVMDialect::getReadonlyAttrName() ||
4606 name == LLVMDialect::getReadnoneAttrName() ||
4607 name == LLVMDialect::getWriteOnlyAttrName() ||
4608 name == LLVMDialect::getNestAttrName() ||
4609 name == LLVMDialect::getNoCaptureAttrName() ||
4610 name == LLVMDialect::getNoFreeAttrName() ||
4611 name == LLVMDialect::getNonNullAttrName()) {
4612 if (
failed(checkUnitAttrType()))
4614 if (verifyValueType &&
failed(checkPointerType()))
4620 if (name == LLVMDialect::getStructRetAttrName() ||
4621 name == LLVMDialect::getByValAttrName() ||
4622 name == LLVMDialect::getByRefAttrName() ||
4623 name == LLVMDialect::getElementTypeAttrName() ||
4624 name == LLVMDialect::getInAllocaAttrName() ||
4625 name == LLVMDialect::getPreallocatedAttrName()) {
4626 if (
failed(checkTypeAttrType()))
4628 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4634 if (name == LLVMDialect::getSExtAttrName() ||
4635 name == LLVMDialect::getZExtAttrName()) {
4636 if (
failed(checkUnitAttrType()))
4638 if (verifyValueType &&
failed(checkIntegerType()))
4644 if (name == LLVMDialect::getAlignAttrName() ||
4645 name == LLVMDialect::getDereferenceableAttrName() ||
4646 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4647 if (
failed(checkIntegerAttrType()))
4649 if (verifyValueType &&
failed(checkPointerType()))
4655 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4656 if (
failed(checkIntegerAttrType()))
4662 if (name == LLVMDialect::getNoUndefAttrName() ||
4663 name == LLVMDialect::getInRegAttrName() ||
4664 name == LLVMDialect::getReturnedAttrName())
4665 return checkUnitAttrType();
4671LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4675 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4678 Type argType = funcOp.getArgumentTypes()[argIdx];
4680 return verifyParameterAttribute(op, argType, argAttr);
4683LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4687 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4690 Type resType = funcOp.getResultTypes()[resIdx];
4694 if (llvm::isa<LLVMVoidType>(resType))
4695 return op->
emitError() <<
"cannot attach result attributes to functions "
4696 "with a void return";
4700 auto name = resAttr.
getName();
4701 if (name == LLVMDialect::getAllocAlignAttrName() ||
4702 name == LLVMDialect::getAllocatedPointerAttrName() ||
4703 name == LLVMDialect::getByValAttrName() ||
4704 name == LLVMDialect::getByRefAttrName() ||
4705 name == LLVMDialect::getInAllocaAttrName() ||
4706 name == LLVMDialect::getNestAttrName() ||
4707 name == LLVMDialect::getNoCaptureAttrName() ||
4708 name == LLVMDialect::getNoFreeAttrName() ||
4709 name == LLVMDialect::getPreallocatedAttrName() ||
4710 name == LLVMDialect::getReadnoneAttrName() ||
4711 name == LLVMDialect::getReadonlyAttrName() ||
4712 name == LLVMDialect::getReturnedAttrName() ||
4713 name == LLVMDialect::getStackAlignmentAttrName() ||
4714 name == LLVMDialect::getStructRetAttrName() ||
4715 name == LLVMDialect::getWriteOnlyAttrName())
4716 return op->
emitError() << name <<
" is not a valid result attribute";
4717 return verifyParameterAttribute(op, resType, resAttr);
4725 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4726 if (isa<LLVM::LLVMPointerType>(type))
4727 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4728 if (isa<LLVM::UndefAttr>(value))
4729 return LLVM::UndefOp::create(builder, loc, type);
4730 if (isa<LLVM::PoisonAttr>(value))
4731 return LLVM::PoisonOp::create(builder, loc, type);
4732 if (isa<LLVM::ZeroAttr>(value))
4733 return LLVM::ZeroOp::create(builder, loc, type);
4734 if (isa<LLVM::MDStringAttr, LLVM::MDConstantAttr, LLVM::MDFuncAttr,
4735 LLVM::MDNodeAttr>(value))
4736 if (isa<LLVM::LLVMMetadataType>(type))
4737 return LLVM::MetadataAsValueOp::create(builder, loc, type, value);
4739 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4747 StringRef name, StringRef value,
4748 LLVM::Linkage linkage) {
4751 "expected builder to point to a block constrained in an op");
4753 builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4754 assert(module &&
"builder points to an op outside of a module");
4759 auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4760 auto global = LLVM::GlobalOp::create(
4761 moduleBuilder, loc, type,
true, linkage, name,
4764 LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4767 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4768 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4780 module = module->getParentOp();
4781 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.