29 #include "llvm/ADT/SCCIterator.h"
30 #include "llvm/ADT/TypeSwitch.h"
31 #include "llvm/AsmParser/Parser.h"
32 #include "llvm/Bitcode/BitcodeReader.h"
33 #include "llvm/Bitcode/BitcodeWriter.h"
34 #include "llvm/IR/Attributes.h"
35 #include "llvm/IR/Function.h"
36 #include "llvm/IR/Type.h"
37 #include "llvm/Support/Error.h"
38 #include "llvm/Support/Mutex.h"
39 #include "llvm/Support/SourceMgr.h"
46 using mlir::LLVM::cconv::getMaxEnumValForCConv;
47 using mlir::LLVM::linkage::getMaxEnumValForLinkage;
48 using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
50 #include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
61 if (attr.
getName() ==
"fastmathFlags") {
63 FastmathFlagsAttr::get(attr.getValue().getContext(), {});
81 << name <<
"' does not reference a valid LLVM function";
82 if (func.isExternal())
83 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
109 template <
typename Ty>
110 struct EnumTraits {};
112 #define REGISTER_ENUM_TYPE(Ty) \
114 struct EnumTraits<Ty> { \
115 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
116 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
129 template <
typename EnumTy,
typename RetTy = EnumTy>
132 EnumTy defaultValue) {
134 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
139 return static_cast<RetTy
>(defaultValue);
140 return static_cast<RetTy
>(index);
152 if (!operands.empty()) {
155 llvm::interleaveComma(operandTypes, p);
164 std::optional<ArrayAttr> opBundleTags) {
165 if (opBundleOperands.empty())
167 assert(opBundleTags &&
"expect operand bundle tags");
170 llvm::interleaveComma(
171 llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
173 auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
191 return p.
emitError(currentParserLoc,
"expect operand bundle tag");
202 opBundleOperands.push_back(std::move(operands));
203 opBundleOperandTypes.push_back(std::move(types));
213 ArrayAttr &opBundleTags) {
221 auto bundleParser = [&] {
241 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
242 <<
", " << getOperand(1);
244 p <<
" : " << getLhs().getType();
248 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
249 <<
", " << getOperand(1);
251 p <<
" : " << getLhs().getType();
258 template <
typename CmpPredicateType>
260 StringAttr predicateAttr;
263 SMLoc predicateLoc, trailingTypeLoc;
275 int64_t predicateValue = 0;
276 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
277 std::optional<ICmpPredicate> predicate =
278 symbolizeICmpPredicate(predicateAttr.getValue());
281 <<
"'" << predicateAttr.getValue()
282 <<
"' is an incorrect value of the 'predicate' attribute";
283 predicateValue =
static_cast<int64_t
>(*predicate);
285 std::optional<FCmpPredicate> predicate =
286 symbolizeFCmpPredicate(predicateAttr.getValue());
289 <<
"'" << predicateAttr.getValue()
290 <<
"' is an incorrect value of the 'predicate' attribute";
291 predicateValue =
static_cast<int64_t
>(*predicate);
301 "expected LLVM dialect-compatible type");
307 return parseCmpOp<ICmpPredicate>(parser, result);
311 return parseCmpOp<FCmpPredicate>(parser, result);
317 ShapedType shapedType = dyn_cast<ShapedType>(type);
324 if (getPredicate() != ICmpPredicate::eq &&
325 getPredicate() != ICmpPredicate::ne)
329 if (getLhs() == getRhs())
331 getPredicate() == ICmpPredicate::eq);
334 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
336 getPredicate() == ICmpPredicate::ne);
339 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
340 Value lhs = getLhs();
341 Value rhs = getRhs();
342 getLhsMutable().assign(rhs);
343 getRhsMutable().assign(lhs);
361 p <<
' ' << getArraySize() <<
" x " << getElemType();
362 if (getAlignment() && *getAlignment() != 0)
364 {kElemTypeAttrName, getInallocaAttrName()});
368 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
369 p <<
" : " << funcTy;
377 SMLoc trailingTypeLoc;
389 std::optional<NamedAttribute> alignmentAttr =
391 if (alignmentAttr.has_value()) {
392 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
395 "expected integer alignment");
396 if (alignmentInt.getValue().isZero())
401 auto funcType = llvm::dyn_cast<FunctionType>(type);
402 if (!funcType || funcType.getNumInputs() != 1 ||
403 funcType.getNumResults() != 1)
406 "expected trailing function type with one argument and one result");
411 Type resultType = funcType.getResult(0);
412 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
415 result.
addTypes({funcType.getResult(0)});
421 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
422 targetExtType && !targetExtType.supportsMemOps())
424 <<
"this target extension type cannot be used in alloca";
434 assert(index == 0 &&
"invalid successor index");
443 assert(index < getNumSuccessors() &&
"invalid successor index");
445 : getFalseDestOperandsMutable());
451 std::optional<std::pair<uint32_t, uint32_t>> weights) {
456 static_cast<int32_t
>(weights->second)});
458 build(builder, result, condition, trueOperands, falseOperands, weightsAttr,
459 {}, trueDest, falseDest);
473 if (!branchWeights.empty())
476 build(builder, result, value, defaultOperands, caseOperands, caseValues,
477 weightsAttr, defaultDestination, caseDestinations);
486 if (!caseValues.empty()) {
488 static_cast<int64_t
>(caseValues.size()), value.
getType());
492 build(builder, result, value, defaultDestination, defaultOperands,
493 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
502 if (!caseValues.empty()) {
504 static_cast<int64_t
>(caseValues.size()), value.
getType());
508 build(builder, result, value, defaultDestination, defaultOperands,
509 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
525 auto parseCase = [&]() {
529 values.push_back(APInt(bitWidth, value,
true));
542 caseDestinations.push_back(destination);
543 caseOperands.emplace_back(operands);
544 caseOperandTypes.emplace_back(operandTypes);
550 ShapedType caseValueType =
570 llvm::zip(caseValues, caseDestinations),
586 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
588 getCaseValues()->size() !=
589 static_cast<int64_t
>(getCaseDestinations().size())))
590 return emitOpError(
"expects number of case values to match number of "
591 "case destinations");
592 if (getBranchWeights() && getBranchWeights()->size() != getNumSuccessors())
593 return emitError(
"expects number of branch weights to match number of "
595 << getBranchWeights()->size() <<
" vs " << getNumSuccessors();
596 if (getCaseValues() &&
598 return emitError(
"expects case value type to match condition value type");
603 assert(index < getNumSuccessors() &&
"invalid successor index");
605 : getCaseOperandsMutable(index - 1));
612 constexpr int32_t GEPOp::kDynamicIndex;
616 getDynamicIndices());
621 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
622 return vectorType.getElementType();
634 for (
const GEPArg &iter : indices) {
639 bool requiresConst = !rawConstantIndices.empty() &&
640 isa_and_nonnull<LLVMStructType>(currType);
641 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
645 rawConstantIndices.push_back(intC.getSExtValue());
647 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
648 dynamicIndices.push_back(val);
651 rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
656 if (rawConstantIndices.size() == 1 || !currType)
660 .Case<VectorType, LLVMArrayType>([](
auto containerType) {
661 return containerType.getElementType();
663 .Case([&](LLVMStructType structType) ->
Type {
664 int64_t memberIndex = rawConstantIndices.back();
665 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
666 structType.getBody().size())
667 return structType.getBody()[memberIndex];
670 .Default(
Type(
nullptr));
676 GEPNoWrapFlags noWrapFlags,
695 GEPNoWrapFlags noWrapFlags,
697 build(builder, result, resultType, elementType, basePtr,
707 auto idxParser = [&]() -> ParseResult {
712 if (failed(parsedInteger.
value()))
718 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
732 llvm::interleaveComma(
735 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
738 printer << cast<IntegerAttr>(cst).getInt();
748 if (indexPos >= indices.
size())
753 .Case<LLVMStructType>([&](LLVMStructType structType) -> LogicalResult {
754 auto attr = dyn_cast<IntegerAttr>(indices[indexPos]);
756 return emitOpError() <<
"expected index " << indexPos
757 <<
" indexing a struct to be constant";
759 int32_t gepIndex = attr.getInt();
762 static_cast<size_t>(gepIndex) >= elementTypes.size())
763 return emitOpError() <<
"index " << indexPos
764 <<
" indexing a struct is out of bounds";
769 indices, emitOpError);
771 .Case<VectorType, LLVMArrayType>(
772 [&](
auto containerType) -> LogicalResult {
774 indexPos + 1, indices, emitOpError);
776 .Default([&](
auto otherType) -> LogicalResult {
778 <<
"type " << otherType <<
" cannot be indexed (index #"
791 if (
static_cast<size_t>(
792 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
793 getDynamicIndices().size())
794 return emitOpError(
"expected as many dynamic indices as specified in '")
795 << getRawConstantIndicesAttrName().getValue() <<
"'";
797 if (getNoWrapFlags() == GEPNoWrapFlags::inboundsFlag)
798 return emitOpError(
"'inbounds_flag' cannot be used directly.");
801 [&] {
return emitOpError(); });
808 void LoadOp::getEffects(
817 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
818 getOrdering() != AtomicOrdering::unordered)) {
829 if (!isa<IntegerType, LLVMPointerType>(type))
834 if (bitWidth.isScalable())
837 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
841 template <
typename OpTy>
844 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
847 return memOp.emitOpError(
"unsupported type ")
848 << valueType <<
" for atomic access";
849 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
850 return memOp.emitOpError(
"unsupported ordering '")
851 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
852 if (!memOp.getAlignment())
853 return memOp.emitOpError(
"expected alignment for atomic access");
856 if (memOp.getSyncscope())
857 return memOp.emitOpError(
858 "expected syncscope to be null for non-atomic access");
863 Type valueType = getResult().getType();
865 {AtomicOrdering::release, AtomicOrdering::acq_rel});
869 Value addr,
unsigned alignment,
bool isVolatile,
870 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
871 AtomicOrdering ordering, StringRef syncscope) {
872 build(builder, state, type, addr,
874 isNonTemporal, isInvariant, isInvariantGroup, ordering,
875 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
886 void StoreOp::getEffects(
895 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
896 getOrdering() != AtomicOrdering::unordered)) {
903 Type valueType = getValue().getType();
905 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
909 Value addr,
unsigned alignment,
bool isVolatile,
910 bool isNonTemporal,
bool isInvariantGroup,
911 AtomicOrdering ordering, StringRef syncscope) {
912 build(builder, state, value, addr,
914 isNonTemporal, isInvariantGroup, ordering,
915 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
917 nullptr,
nullptr,
nullptr);
927 Type resultType = calleeType.getReturnType();
928 if (!isa<LLVM::LLVMVoidType>(resultType))
929 results.push_back(resultType);
935 return calleeType.isVarArg() ?
TypeAttr::get(calleeType) :
nullptr;
945 resultType = results.front();
952 build(builder, state, results, builder.
getStringAttr(callee), args);
962 assert(callee &&
"expected non-null callee in direct call builder");
963 build(builder, state, results,
964 nullptr, callee, args,
nullptr,
968 nullptr,
nullptr,
nullptr,
978 LLVMFunctionType calleeType, StringRef callee,
980 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
984 LLVMFunctionType calleeType, StringAttr callee,
1002 nullptr,
nullptr,
nullptr,
1008 LLVMFunctionType calleeType,
ValueRange args) {
1013 nullptr,
nullptr,
nullptr,
1014 nullptr,
nullptr,
nullptr,
1025 auto calleeType = func.getFunctionType();
1029 nullptr,
nullptr,
nullptr,
1030 nullptr,
nullptr,
nullptr,
1044 return getOperand(0);
1050 auto symRef = cast<SymbolRefAttr>(callee);
1051 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1054 return setOperand(0, cast<Value>(callee));
1058 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1063 getCalleeOperands().size());
1070 if (callee.isExternal())
1072 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1076 auto hasSubprogram = [](
Operation *op) {
1081 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1083 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1085 return callOp.emitError()
1086 <<
"inlinable function call in a function with a DISubprogram "
1087 "location must have a debug location";
1093 template <
typename OpTy>
1095 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1100 if (!varCalleeType->isVarArg())
1101 return callOp.emitOpError(
1102 "expected var_callee_type to be a variadic function type");
1106 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1107 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1108 << callOp.getArgOperands().size() <<
" parameters";
1111 for (
auto [paramType, operand] :
1112 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1113 if (paramType != operand.getType())
1114 return callOp.emitOpError()
1115 <<
"var_callee_type parameter type mismatch: " << paramType
1116 <<
" != " << operand.getType();
1119 if (!callOp.getNumResults()) {
1120 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1121 return callOp.emitOpError(
"expected var_callee_type to return void");
1123 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1124 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1125 << varCalleeType->getReturnType()
1126 <<
" != " << callOp.getResult().getType();
1131 template <
typename OpType>
1134 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1136 auto isStringAttr = [](
Attribute tagAttr) {
1137 return isa<StringAttr>(tagAttr);
1139 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1140 return op.emitError(
"operand bundle tag must be a StringAttr");
1142 size_t numOpBundles = opBundleOperands.size();
1143 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1144 if (numOpBundles != numOpBundleTags)
1145 return op.emitError(
"expected ")
1146 << numOpBundles <<
" operand bundle tags, but actually got "
1162 bool isIndirect =
false;
1168 if (!getNumOperands())
1170 "must have either a `callee` attribute or at least an operand");
1171 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1173 return emitOpError(
"indirect call expects a pointer as callee: ")
1174 << getOperand(0).getType();
1181 return emitOpError()
1183 <<
"' does not reference a symbol in the current scope";
1184 auto fn = dyn_cast<LLVMFuncOp>(callee);
1186 return emitOpError() <<
"'" << calleeName.
getValue()
1187 <<
"' does not reference a valid LLVM function";
1191 fnType = fn.getFunctionType();
1194 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1196 return emitOpError(
"callee does not have a functional type: ") << fnType;
1198 if (funcType.isVarArg() && !getVarCalleeType())
1199 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1203 if (!funcType.isVarArg() &&
1204 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1205 return emitOpError() <<
"incorrect number of operands ("
1206 << (getCalleeOperands().size() - isIndirect)
1207 <<
") for callee (expecting: "
1208 << funcType.getNumParams() <<
")";
1210 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1211 return emitOpError() <<
"incorrect number of operands ("
1212 << (getCalleeOperands().size() - isIndirect)
1213 <<
") for varargs callee (expecting at least: "
1214 << funcType.getNumParams() <<
")";
1216 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1217 if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1218 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1219 << getOperand(i + isIndirect).getType()
1220 <<
" != " << funcType.getParamType(i);
1222 if (getNumResults() == 0 &&
1223 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1224 return emitOpError() <<
"expected function call to produce a value";
1226 if (getNumResults() != 0 &&
1227 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1228 return emitOpError()
1229 <<
"calling function with void result must not produce values";
1231 if (getNumResults() > 1)
1232 return emitOpError()
1233 <<
"expected LLVM function call to produce 0 or 1 result";
1235 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1236 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1237 <<
" != " << funcType.getReturnType();
1243 auto callee = getCallee();
1244 bool isDirect = callee.has_value();
1249 if (getCConv() != LLVM::CConv::C)
1250 p << stringifyCConv(getCConv()) <<
' ';
1253 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1262 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1263 p <<
'(' << args <<
')';
1266 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1267 p <<
" vararg(" << *varCalleeType <<
")";
1269 if (!getOpBundleOperands().empty()) {
1272 getOpBundleOperands().getTypes(), getOpBundleTags());
1276 {getCalleeAttrName(), getTailCallKindAttrName(),
1277 getVarCalleeTypeAttrName(), getCConvAttrName(),
1278 getOperandSegmentSizesAttrName(),
1279 getOpBundleSizesAttrName(),
1280 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1281 getResAttrsAttrName()});
1285 p << getOperand(0).getType() <<
", ";
1289 p, args.getTypes(), getArgAttrsAttr(),
1290 false, getResultTypes(), getResAttrsAttr());
1305 types.emplace_back();
1310 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1315 resTypes, resultAttrs)) {
1317 return parser.
emitError(trailingTypesLoc,
1318 "expected direct call to have 1 trailing types");
1319 return parser.
emitError(trailingTypesLoc,
1320 "expected trailing function type");
1323 if (resTypes.size() > 1)
1324 return parser.
emitError(trailingTypesLoc,
1325 "expected function with 0 or 1 result");
1326 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1327 return parser.
emitError(trailingTypesLoc,
1328 "expected a non-void result type");
1334 llvm::append_range(types, argTypes);
1338 if (resTypes.size() != 0)
1352 if (failed(*parseResult))
1353 return *parseResult;
1354 operands.push_back(funcPtrOperand);
1363 StringAttr opBundleSizesAttrName) {
1364 unsigned opBundleIndex = 0;
1365 for (
const auto &[operands, types] :
1366 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1367 if (operands.size() != types.size())
1368 return parser.
emitError(loc,
"expected ")
1370 <<
" types for operand bundle operands for operand bundle #"
1371 << opBundleIndex <<
", but actually got " << types.size();
1377 opBundleSizes.reserve(opBundleOperands.size());
1378 for (
const auto &operands : opBundleOperands)
1379 opBundleSizes.push_back(operands.size());
1382 opBundleSizesAttrName,
1394 SymbolRefAttr funcAttr;
1395 TypeAttr varCalleeType;
1399 ArrayAttr opBundleTags;
1403 getCConvAttrName(result.
name),
1405 parser, result, LLVM::CConv::C)));
1408 getTailCallKindAttrName(result.
name),
1410 parseOptionalLLVMKeyword<TailCallKind>(
1416 bool isDirect = operands.empty();
1429 StringAttr varCalleeTypeAttrName =
1430 CallOp::getVarCalleeTypeAttrName(result.
name);
1442 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1443 result && failed(*result))
1445 if (opBundleTags && !opBundleTags.empty())
1446 result.
addAttribute(CallOp::getOpBundleTagsAttrName(result.
name).getValue(),
1456 argAttrs, resultAttrs))
1459 parser.
getBuilder(), result, argAttrs, resultAttrs,
1460 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
1462 opBundleOperandTypes,
1463 getOpBundleSizesAttrName(result.
name)))
1466 int32_t numOpBundleOperands = 0;
1467 for (
const auto &operands : opBundleOperands)
1468 numOpBundleOperands += operands.size();
1471 CallOp::getOperandSegmentSizeAttr(),
1473 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1477 LLVMFunctionType CallOp::getCalleeFunctionType() {
1478 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1479 return *varCalleeType;
1490 auto calleeType = func.getFunctionType();
1493 nullptr,
nullptr, normalOps, unwindOps,
1494 nullptr,
nullptr, {}, {}, normal, unwind);
1501 build(builder, state, tys,
1502 nullptr, callee, ops,
nullptr,
1503 nullptr, normalOps, unwindOps,
nullptr,
nullptr, {}, {},
1513 nullptr,
nullptr, normalOps, unwindOps,
1514 nullptr,
nullptr, {}, {}, normal, unwind);
1518 assert(index < getNumSuccessors() &&
"invalid successor index");
1520 : getUnwindDestOperandsMutable());
1528 return getOperand(0);
1534 auto symRef = cast<SymbolRefAttr>(callee);
1535 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1538 return setOperand(0, cast<Value>(callee));
1542 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1547 getCalleeOperands().size());
1554 Block *unwindDest = getUnwindDest();
1555 if (unwindDest->
empty())
1556 return emitError(
"must have at least one operation in unwind destination");
1559 if (!isa<LandingpadOp>(unwindDest->
front()))
1560 return emitError(
"first operation in unwind destination should be a "
1561 "llvm.landingpad operation");
1570 auto callee = getCallee();
1571 bool isDirect = callee.has_value();
1576 if (getCConv() != LLVM::CConv::C)
1577 p << stringifyCConv(getCConv()) <<
' ';
1585 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1592 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1593 p <<
" vararg(" << *varCalleeType <<
")";
1595 if (!getOpBundleOperands().empty()) {
1598 getOpBundleOperands().getTypes(), getOpBundleTags());
1602 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1603 getCConvAttrName(), getVarCalleeTypeAttrName(),
1604 getOpBundleSizesAttrName(),
1605 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1606 getResAttrsAttrName()});
1610 p << getOperand(0).getType() <<
", ";
1612 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1614 false, getResultTypes(), getResAttrsAttr());
1627 SymbolRefAttr funcAttr;
1628 TypeAttr varCalleeType;
1631 ArrayAttr opBundleTags;
1632 Block *normalDest, *unwindDest;
1638 getCConvAttrName(result.
name),
1640 parser, result, LLVM::CConv::C)));
1645 bool isDirect = operands.empty();
1661 StringAttr varCalleeTypeAttrName =
1662 InvokeOp::getVarCalleeTypeAttrName(result.
name);
1674 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1675 result && failed(*result))
1677 if (opBundleTags && !opBundleTags.empty())
1679 InvokeOp::getOpBundleTagsAttrName(result.
name).getValue(),
1689 argAttrs, resultAttrs))
1692 parser.
getBuilder(), result, argAttrs, resultAttrs,
1693 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
1696 opBundleOperandTypes,
1697 getOpBundleSizesAttrName(result.
name)))
1704 int32_t numOpBundleOperands = 0;
1705 for (
const auto &operands : opBundleOperands)
1706 numOpBundleOperands += operands.size();
1709 InvokeOp::getOperandSegmentSizeAttr(),
1711 static_cast<int32_t>(normalOperands.size()),
1712 static_cast<int32_t>(unwindOperands.size()),
1713 numOpBundleOperands}));
1717 LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1718 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1719 return *varCalleeType;
1729 if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1730 if (!func.getPersonality())
1732 "llvm.landingpad needs to be in a function with a personality");
1738 if (!getCleanup() && getOperands().empty())
1739 return emitError(
"landingpad instruction expects at least one clause or "
1740 "cleanup attribute");
1742 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1743 value = getOperand(idx);
1744 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1751 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1754 <<
"global addresses expected as operand to "
1755 "bitcast used in clauses for landingpad";
1763 << idx <<
" is not a known constant - null, addressof, bitcast";
1770 p << (getCleanup() ?
" cleanup " :
" ");
1773 for (
auto value : getOperands()) {
1776 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1777 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1824 Type llvmType = containerType;
1826 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1834 for (int64_t idx : position) {
1835 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1836 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1837 emitError(
"position out of bounds: ") << idx;
1840 llvmType = arrayType.getElementType();
1841 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1843 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1844 emitError(
"position out of bounds: ") << idx;
1847 llvmType = structType.getBody()[idx];
1849 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1860 for (int64_t idx : position) {
1861 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1862 llvmType = structType.getBody()[idx];
1864 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1869 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1870 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
1872 newPos.append(getPosition().begin(), getPosition().end());
1873 setPosition(newPos);
1874 getContainerMutable().set(extractValueOp.getContainer());
1882 if (isa<SplatElementsAttr>(constval))
1884 if (getPosition().size() == 1)
1889 auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1892 bool switchedToInsertedValue =
false;
1893 while (insertValueOp) {
1895 auto extractPosSize = extractPos.size();
1896 auto insertPosSize = insertPos.size();
1899 if (extractPos == insertPos)
1900 return insertValueOp.getValue();
1914 if (extractPosSize > insertPosSize &&
1915 extractPos.take_front(insertPosSize) == insertPos) {
1916 insertValueOp = insertValueOp.getValue().getDefiningOp<InsertValueOp>();
1917 extractPos = extractPos.drop_front(insertPosSize);
1918 switchedToInsertedValue =
true;
1923 unsigned min =
std::min(extractPosSize, insertPosSize);
1935 if (extractPos.take_front(
min) == insertPos.take_front(
min))
1940 if (!switchedToInsertedValue) {
1943 getContainerMutable().assign(insertValueOp.getContainer());
1944 result = getResult();
1946 insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1952 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1958 if (getRes().
getType() != valueType)
1959 return emitOpError() <<
"Type mismatch: extracting from "
1960 << getContainer().getType() <<
" should produce "
1961 << valueType <<
" but this op returns "
1962 << getRes().getType();
1968 build(builder, state,
1983 [&](StringRef msg) {
1987 return success(!!valueType);
1997 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
2003 if (getValue().
getType() != valueType)
2004 return emitOpError() <<
"Type mismatch: cannot insert "
2005 << getValue().getType() <<
" into "
2006 << getContainer().getType();
2016 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2020 Type expectedType = parent.getFunctionType().getReturnType();
2021 if (llvm::isa<LLVMVoidType>(expectedType)) {
2025 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2029 if (llvm::isa<LLVMVoidType>(expectedType))
2032 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2035 if (expectedType != getArg().
getType()) {
2037 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2051 assert(module &&
"unexpected operation outside of a module");
2056 return dyn_cast_or_null<GlobalOp>(
2061 return dyn_cast_or_null<LLVMFuncOp>(
2066 return dyn_cast_or_null<AliasOp>(
2075 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2076 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2077 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2079 if (!global && !
function && !alias)
2080 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2081 "'llvm.mlir.alias' or 'llvm.func'");
2083 LLVMPointerType type =
getType();
2084 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2085 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2086 return emitOpError(
"pointer address space must match address space of the "
2087 "referenced global or alias");
2094 return getGlobalNameAttr();
2115 getFunctionNameAttr());
2116 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2117 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2119 if (!
function && !alias)
2121 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2124 if (alias.getInitializer()
2125 .walk([&](AddressOfOp addrOp) {
2126 if (addrOp.getGlobal(symbolTable))
2127 return WalkResult::interrupt();
2128 return WalkResult::advance();
2131 return emitOpError(
"must reference an alias to a function");
2134 if ((
function &&
function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2135 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2137 "target function with 'extern_weak' linkage not allowed");
2153 StringRef symName) {
2160 LogicalResult ComdatOp::verifyRegions() {
2161 Region &body = getBody();
2163 if (!isa<ComdatSelectorOp>(op))
2164 return op.emitError(
2165 "only comdat selector symbols can appear in a comdat region");
2175 bool isConstant, Linkage linkage, StringRef name,
2176 Attribute value, uint64_t alignment,
unsigned addrSpace,
2177 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2211 if (!dbgExprs.empty())
2218 template <
typename OpType>
2220 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2221 StringRef visibility = stringifyVisibility(op.getVisibility_());
2222 if (!visibility.empty())
2223 p << visibility <<
' ';
2224 if (op.getThreadLocal_())
2225 p <<
"thread_local ";
2226 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2227 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2234 printCommonGlobalAndAlias<GlobalOp>(p, *
this);
2239 if (
auto value = getValueOrNull())
2242 if (
auto comdat = getComdat())
2243 p <<
" comdat(" << *comdat <<
')';
2249 {SymbolTable::getSymbolAttrName(),
2250 getGlobalTypeAttrName(), getConstantAttrName(),
2251 getValueAttrName(), getLinkageAttrName(),
2252 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2253 getVisibility_AttrName(), getComdatAttrName(),
2254 getUnnamedAddrAttrName()});
2257 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2261 Region &initializer = getInitializerRegion();
2262 if (!initializer.
empty()) {
2269 std::optional<SymbolRefAttr> attr) {
2274 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2275 return op->
emitError() <<
"expected comdat symbol";
2285 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2286 if (blockTags.contains(blockTagOp.getTag())) {
2287 blockTagOp.emitError()
2288 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2289 <<
"' in the same function: ";
2290 return WalkResult::interrupt();
2292 blockTags.insert(blockTagOp.getTag());
2301 template <
typename OpType>
2308 ctx, parseOptionalLLVMKeyword<Linkage>(
2309 parser, result, LLVM::Linkage::External)));
2314 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2315 parser, result, LLVM::Visibility::Default)));
2324 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2340 if (parseCommonGlobalAndAlias<GlobalOp>(parser, result).failed())
2362 SymbolRefAttr comdat;
2375 if (types.size() > 1)
2379 if (types.empty()) {
2380 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2383 strAttr.getValue().size());
2384 types.push_back(arrayType);
2387 "type can only be omitted for string globals");
2393 if (parseResult.
has_value() && failed(*parseResult))
2403 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2404 return intValue.getValue().isZero();
2405 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2406 return fpValue.getValue().isZero();
2407 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2409 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2411 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2418 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2419 LLVMMetadataType, LLVMLabelType>(
getType())
2420 : llvm::isa<PointerElementTypeInterface>(
getType());
2423 "expects type to be a valid element type for an LLVM global");
2425 return emitOpError(
"must appear at the module level");
2427 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2428 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2429 IntegerType elementType =
2430 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2431 if (!elementType || elementType.getWidth() != 8 ||
2432 type.getNumElements() != strAttr.getValue().size())
2434 "requires an i8 array type of the length equal to that of the string "
2438 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2439 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2440 return emitOpError()
2441 <<
"this target extension type cannot be used in a global";
2444 return emitOpError() <<
"global with target extension type can only be "
2445 "initialized with zero-initializer";
2448 if (getLinkage() == Linkage::Common) {
2449 if (
Attribute value = getValueOrNull()) {
2451 return emitOpError()
2452 <<
"expected zero value for '"
2453 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2458 if (getLinkage() == Linkage::Appending) {
2459 if (!llvm::isa<LLVMArrayType>(
getType())) {
2460 return emitOpError() <<
"expected array type for '"
2461 << stringifyLinkage(Linkage::Appending)
2469 std::optional<uint64_t> alignAttr = getAlignment();
2470 if (alignAttr.has_value()) {
2471 uint64_t value = alignAttr.value();
2472 if (!llvm::isPowerOf2_64(value))
2473 return emitError() <<
"alignment attribute is not a power of 2";
2479 LogicalResult GlobalOp::verifyRegions() {
2480 if (
Block *b = getInitializerBlock()) {
2481 ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2482 if (ret.operand_type_begin() == ret.operand_type_end())
2483 return emitOpError(
"initializer region cannot return void");
2484 if (*ret.operand_type_begin() !=
getType())
2485 return emitOpError(
"initializer region type ")
2486 << *ret.operand_type_begin() <<
" does not match global type "
2490 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2491 if (!iface || !iface.hasNoEffect())
2492 return op.emitError()
2493 <<
"ops with side effects not allowed in global initializers";
2496 if (getValueOrNull())
2497 return emitOpError(
"cannot have both initializer value and region");
2512 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2515 return op->
emitError(
"data element must be symbol or #llvm.zero");
2532 if (getCtors().size() == getPriorities().size() &&
2533 getCtors().size() == getData().size())
2536 "ctors, priorities, and data must have the same number of elements");
2557 if (getDtors().size() == getPriorities().size() &&
2558 getDtors().size() == getData().size())
2561 "dtors, priorities, and data must have the same number of elements");
2569 Linkage linkage, StringRef name,
bool dsoLocal,
2589 printCommonGlobalAndAlias<AliasOp>(p, *
this);
2593 {SymbolTable::getSymbolAttrName(),
2594 getAliasTypeAttrName(), getLinkageAttrName(),
2595 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2596 getVisibility_AttrName(), getUnnamedAddrAttrName()});
2599 p <<
" : " <<
getType() <<
' ';
2612 if (parseCommonGlobalAndAlias<AliasOp>(parser, result).failed())
2625 if (types.size() > 1)
2639 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2640 LLVMMetadataType, LLVMLabelType>(
getType())
2641 : llvm::isa<PointerElementTypeInterface>(
getType());
2644 "expects type to be a valid element type for an LLVM global alias");
2647 switch (getLinkage()) {
2648 case Linkage::External:
2649 case Linkage::Internal:
2650 case Linkage::Private:
2652 case Linkage::WeakODR:
2653 case Linkage::Linkonce:
2654 case Linkage::LinkonceODR:
2655 case Linkage::AvailableExternally:
2658 return emitOpError()
2659 <<
"'" << stringifyLinkage(getLinkage())
2660 <<
"' linkage not supported in aliases, available options: private, "
2661 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2662 "available_externally";
2668 LogicalResult AliasOp::verifyRegions() {
2669 Block &b = getInitializerBlock();
2671 if (ret.getNumOperands() == 0 ||
2672 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2673 return emitOpError(
"initializer region must always return a pointer");
2676 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2677 if (!iface || !iface.hasNoEffect())
2678 return op.emitError()
2679 <<
"ops with side effects are not allowed in alias initializers";
2685 unsigned AliasOp::getAddrSpace() {
2686 Block &initializer = getInitializerBlock();
2688 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2689 return ptrTy.getAddressSpace();
2699 auto containerType = v1.
getType();
2703 build(builder, state, vType, v1, v2, mask);
2704 state.addAttributes(attrs);
2717 "expected an LLVM compatible vector type");
2730 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2731 return emitOpError(
"expected a splat operation for scalable vectors");
2741 assert(empty() &&
"function already has an entry block");
2746 LLVMFunctionType type = getFunctionType();
2747 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2748 entry->
addArgument(type.getParamType(i), getLoc());
2753 StringRef name,
Type type, LLVM::Linkage linkage,
2754 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2757 std::optional<uint64_t> functionEntryCount) {
2773 if (functionEntryCount)
2776 if (argAttrs.empty())
2779 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2780 "expected as many argument attribute lists as arguments");
2782 builder, result, argAttrs, std::nullopt,
2783 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2794 if (outputs.size() > 1) {
2795 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2796 "one function result");
2802 for (
auto t : inputs) {
2804 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2805 "type for function arguments");
2808 llvmInputs.push_back(t);
2815 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2816 "type for function results")
2834 getLinkageAttrName(result.
name),
2836 parseOptionalLLVMKeyword<Linkage>(
2837 parser, result, LLVM::Linkage::External)));
2842 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2843 parser, result, LLVM::Visibility::Default)));
2848 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2853 getCConvAttrName(result.
name),
2855 parser, result, LLVM::CConv::C)));
2857 StringAttr nameAttr;
2867 parser,
true, entryArgs, isVariadic, resultTypes,
2872 for (
auto &arg : entryArgs)
2873 argTypes.push_back(arg.type);
2883 int64_t minRange, maxRange;
2890 getVscaleRangeAttrName(result.
name),
2897 SymbolRefAttr comdat;
2908 parser.
getBuilder(), result, entryArgs, resultAttrs,
2909 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2914 return failure(parseResult.
has_value() && failed(*parseResult));
2922 if (getLinkage() != LLVM::Linkage::External)
2923 p << stringifyLinkage(getLinkage()) <<
' ';
2924 StringRef visibility = stringifyVisibility(getVisibility_());
2925 if (!visibility.empty())
2926 p << visibility <<
' ';
2927 if (
auto unnamedAddr = getUnnamedAddr()) {
2928 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2932 if (getCConv() != LLVM::CConv::C)
2933 p << stringifyCConv(getCConv()) <<
' ';
2937 LLVMFunctionType fnType = getFunctionType();
2940 argTypes.reserve(fnType.getNumParams());
2941 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
2942 argTypes.push_back(fnType.getParamType(i));
2944 Type returnType = fnType.getReturnType();
2945 if (!llvm::isa<LLVMVoidType>(returnType))
2946 resTypes.push_back(returnType);
2949 isVarArg(), resTypes);
2952 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
2953 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
2954 << vscale->getMaxRange().getInt() <<
')';
2957 if (
auto comdat = getComdat())
2958 p <<
" comdat(" << *comdat <<
')';
2962 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
2963 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
2964 getComdatAttrName(), getUnnamedAddrAttrName(),
2965 getVscaleRangeAttrName()});
2968 Region &body = getBody();
2969 if (!body.empty()) {
2981 if (getLinkage() == LLVM::Linkage::Common)
2982 return emitOpError() <<
"functions cannot have '"
2983 << stringifyLinkage(LLVM::Linkage::Common)
2990 if (getLinkage() != LLVM::Linkage::External &&
2991 getLinkage() != LLVM::Linkage::ExternWeak)
2992 return emitOpError() <<
"external functions must have '"
2993 << stringifyLinkage(LLVM::Linkage::External)
2995 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3001 if (isNoInline() && isAlwaysInline())
3002 return emitError(
"no_inline and always_inline attributes are incompatible");
3004 if (isOptimizeNone() && !isNoInline())
3005 return emitOpError(
"with optimize_none must also be no_inline");
3007 Type landingpadResultTy;
3008 StringRef diagnosticMessage;
3009 bool isLandingpadTypeConsistent =
3011 const auto checkType = [&](
Type type, StringRef errorMessage) {
3012 if (!landingpadResultTy) {
3013 landingpadResultTy = type;
3016 if (landingpadResultTy != type) {
3017 diagnosticMessage = errorMessage;
3023 .Case<LandingpadOp>([&](
auto landingpad) {
3024 constexpr StringLiteral errorMessage =
3025 "'llvm.landingpad' should have a consistent result type "
3026 "inside a function";
3027 return checkType(landingpad.getType(), errorMessage);
3029 .Case<ResumeOp>([&](
auto resume) {
3030 constexpr StringLiteral errorMessage =
3031 "'llvm.resume' should have a consistent input type inside a "
3033 return checkType(resume.getValue().getType(), errorMessage);
3036 }).wasInterrupted();
3037 if (!isLandingpadTypeConsistent) {
3038 assert(!diagnosticMessage.empty() &&
3039 "Expecting a non-empty diagnostic message");
3051 LogicalResult LLVMFuncOp::verifyRegions() {
3055 unsigned numArguments = getFunctionType().getNumParams();
3056 Block &entryBlock = front();
3057 for (
unsigned i = 0; i < numArguments; ++i) {
3060 return emitOpError(
"entry block argument #")
3061 << i <<
" is not of LLVM type";
3067 Region *LLVMFuncOp::getCallableRegion() {
3096 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3097 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3098 return emitOpError()
3099 <<
"target extension type does not support zero-initializer";
3121 if (
auto vecType = dyn_cast<VectorType>(t)) {
3122 assert(!vecType.isScalable() &&
3123 "number of elements of a scalable vector type is unknown");
3124 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3126 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3127 return arrayType.getNumElements() *
3135 if (
auto vecType = dyn_cast<VectorType>(t)) {
3136 if (vecType.isScalable())
3140 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3148 LLVM::LLVMArrayType arrayType,
3149 ArrayAttr arrayAttr,
int dim) {
3150 if (arrayType.getNumElements() != arrayAttr.size())
3151 return op.emitOpError()
3152 <<
"array attribute size does not match array type size in "
3154 << dim <<
": " << arrayAttr.size() <<
" vs. "
3155 << arrayType.getNumElements();
3160 if (
auto subArrayType =
3161 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3163 if (elementsVerified.insert(elementAttr).second) {
3164 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3166 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3168 return op.emitOpError()
3169 <<
"nested attribute for sub-array in dimension " << dim
3170 <<
" at index " << idx
3171 <<
" must be a zero, or undef, or array attribute";
3185 auto structType = dyn_cast<LLVM::LLVMStructType>(arrayType.getElementType());
3187 return op.emitOpError() <<
"for array with an array attribute must have a "
3188 "struct element type";
3192 size_t numStructElements = structType.getBody().size();
3194 if (elementsVerified.insert(elementAttr).second) {
3195 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3197 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3199 return op.emitOpError()
3200 <<
"nested attribute for struct element at index " << idx
3201 <<
" must be a zero, or undef, or array attribute";
3202 if (subArrayAttr.size() != numStructElements)
3203 return op.emitOpError()
3204 <<
"nested array attribute size for struct element at index "
3205 << idx <<
" must match struct size: " << subArrayAttr.size()
3206 <<
" vs. " << numStructElements;
3214 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3215 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3216 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3217 !arrayType.getElementType().isInteger(8)) {
3218 return emitOpError() <<
"expected array type of "
3219 << sAttr.getValue().size()
3220 <<
" i8 elements for the string constant";
3224 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3225 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3227 return emitOpError() <<
"expected array attribute for a struct constant";
3231 if (arrayAttr.size() != elementTypes.size()) {
3232 return emitOpError() <<
"expected array attribute of size "
3233 << elementTypes.size();
3235 for (
auto elementTy : elementTypes) {
3236 if (!isa<IntegerType, FloatType, LLVMPPCFP128Type>(elementTy)) {
3237 return emitOpError() <<
"expected struct element types to be floating "
3238 "point type or integer type";
3242 for (
size_t i = 0; i < elementTypes.size(); ++i) {
3244 if (!isa<IntegerAttr, FloatAttr>(element)) {
3245 return emitOpError()
3246 <<
"expected struct element attribute types to be floating "
3247 "point type or integer type";
3249 auto elementType = cast<TypedAttr>(element).getType();
3250 if (elementType != elementTypes[i]) {
3251 return emitOpError()
3252 <<
"struct element at index " << i <<
" is of wrong type";
3258 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
3259 return emitOpError() <<
"does not support target extension type.";
3263 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
3264 if (!llvm::isa<IntegerType>(
getType()))
3265 return emitOpError() <<
"expected integer type";
3266 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3267 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
3268 unsigned floatWidth = APFloat::getSizeInBits(sem);
3269 if (
auto floatTy = dyn_cast<FloatType>(
getType())) {
3270 if (floatTy.getWidth() != floatWidth) {
3271 return emitOpError() <<
"expected float type of width " << floatWidth;
3276 if (isa<IntegerType>(
getType()) && !
getType().isInteger(floatWidth)) {
3277 return emitOpError() <<
"expected integer type of width " << floatWidth;
3279 }
else if (isa<ElementsAttr>(getValue())) {
3283 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3284 if (!splatElementsAttr)
3285 return emitOpError()
3286 <<
"scalable vector type requires a splat attribute";
3289 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3290 return emitOpError() <<
"expected vector or array type";
3292 if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3293 int64_t attrNumElements = elementsAttr.getNumElements();
3295 return emitOpError()
3296 <<
"type and attribute have a different number of elements: "
3299 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3300 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3302 return emitOpError() <<
"expected array type";
3307 return emitOpError()
3308 <<
"only supports integer, float, string or elements attributes";
3314 bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3316 auto typedAttr = dyn_cast<TypedAttr>(value);
3323 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3328 if (isBuildableWith(value, type))
3329 return builder.
create<LLVM::ConstantOp>(loc, cast<TypedAttr>(value));
3334 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3342 AtomicOrdering ordering, StringRef syncscope,
3343 unsigned alignment,
bool isVolatile) {
3344 build(builder, state, val.
getType(), binOp, ptr, val, ordering,
3345 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3348 nullptr,
nullptr,
nullptr);
3352 auto valType = getVal().getType();
3353 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3354 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3355 getBinOp() == AtomicBinOp::fminimum ||
3356 getBinOp() == AtomicBinOp::fmaximum) {
3359 return emitOpError(
"expected LLVM IR fixed vector type");
3360 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3363 "expected LLVM IR floating point type for vector element");
3365 return emitOpError(
"expected LLVM IR floating point type");
3367 }
else if (getBinOp() == AtomicBinOp::xchg) {
3370 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3372 auto intType = llvm::dyn_cast<IntegerType>(valType);
3373 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3374 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3376 return emitOpError(
"expected LLVM IR integer type");
3379 if (
static_cast<unsigned>(getOrdering()) <
3380 static_cast<unsigned>(AtomicOrdering::monotonic))
3381 return emitOpError() <<
"expected at least '"
3382 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3395 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3400 AtomicOrdering successOrdering,
3401 AtomicOrdering failureOrdering, StringRef syncscope,
3402 unsigned alignment,
bool isWeak,
bool isVolatile) {
3404 successOrdering, failureOrdering,
3405 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3407 isVolatile,
nullptr,
3408 nullptr,
nullptr,
nullptr);
3412 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3414 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3415 auto valType = getVal().getType();
3418 return emitOpError(
"unexpected LLVM IR type");
3419 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3420 getFailureOrdering() < AtomicOrdering::monotonic)
3421 return emitOpError(
"ordering must be at least 'monotonic'");
3422 if (getFailureOrdering() == AtomicOrdering::release ||
3423 getFailureOrdering() == AtomicOrdering::acq_rel)
3424 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3433 AtomicOrdering ordering, StringRef syncscope) {
3434 build(builder, state, ordering,
3435 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3439 if (getOrdering() == AtomicOrdering::not_atomic ||
3440 getOrdering() == AtomicOrdering::unordered ||
3441 getOrdering() == AtomicOrdering::monotonic)
3442 return emitOpError(
"can be given only acquire, release, acq_rel, "
3443 "and seq_cst orderings");
3453 template <
class ExtOp>
3455 IntegerType inputType, outputType;
3458 return op.emitError(
3459 "input type is a vector but output type is an integer");
3462 return op.emitError(
"input and output vectors are of incompatible shape");
3465 inputType = cast<IntegerType>(
3466 cast<VectorType>(op.getArg().getType()).getElementType());
3467 outputType = cast<IntegerType>(
3468 cast<VectorType>(op.getResult().getType()).getElementType());
3472 inputType = cast<IntegerType>(op.getArg().getType());
3473 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3475 return op.emitError(
3476 "input type is an integer but output type is a vector");
3479 if (outputType.getWidth() <= inputType.getWidth())
3480 return op.emitError(
"integer width of the output type is smaller or "
3481 "equal to the integer width of the input type");
3489 LogicalResult
ZExtOp::verify() {
return verifyExtOp<ZExtOp>(*
this); }
3492 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3496 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3504 LogicalResult
SExtOp::verify() {
return verifyExtOp<SExtOp>(*
this); }
3511 template <
typename T>
3513 typename T::FoldAdaptor adaptor) {
3515 if (castOp.getArg().getType() == castOp.getType())
3516 return castOp.getArg();
3517 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3519 if (prev.getArg().getType() == castOp.getType())
3520 return prev.getArg();
3522 castOp.getArgMutable().set(prev.getArg());
3523 return Value{castOp};
3528 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3533 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3535 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3540 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3541 return emitOpError(
"can only cast pointers from and to pointers");
3546 auto isVector = llvm::IsaPred<VectorType>;
3550 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3551 return emitOpError(
"cannot cast pointer to vector of pointers");
3553 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3554 return emitOpError(
"cannot cast vector of pointers to pointer");
3558 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3559 return emitOpError(
"cannot cast pointers of different address spaces, "
3560 "use 'llvm.addrspacecast' instead");
3569 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3573 Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3581 adaptor.getDynamicIndices());
3585 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
3586 if (integer.getValue().isZero())
3593 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3600 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3601 gepArgs.emplace_back(val);
3603 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3609 gepArgs.emplace_back(integer.getInt());
3617 getDynamicIndicesMutable().assign(dynamicIndices);
3618 setRawConstantIndices(rawConstantIndices);
3619 return Value{*
this};
3625 Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3632 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3636 if (rhs.getValue().getZExtValue() >=
3637 getLhs().
getType().getIntOrFloatBitWidth())
3640 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3652 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3656 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3668 if (!getIntrin().starts_with(
"llvm."))
3669 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3677 build(builder, state,
TypeRange{}, intrin, args,
3678 FastmathFlagsAttr{},
3685 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3686 build(builder, state,
TypeRange{}, intrin, args,
3693 mlir::Type resultType, mlir::StringAttr intrin,
3695 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
3703 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3704 build(builder, state, resultTypes, intrin, args, fastMathFlags,
3711 StringAttr intrinAttr;
3715 ArrayAttr opBundleTags;
3729 return mlir::failure();
3732 return mlir::failure();
3737 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
3738 result && failed(*result))
3740 if (opBundleTags && !opBundleTags.empty())
3742 CallIntrinsicOp::getOpBundleTagsAttrName(result.
name).getValue(),
3746 return mlir::failure();
3751 operands, argAttrs, resultAttrs))
3754 parser.
getBuilder(), result, argAttrs, resultAttrs,
3755 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
3758 opBundleOperandTypes,
3759 getOpBundleSizesAttrName(result.
name)))
3762 int32_t numOpBundleOperands = 0;
3763 for (
const auto &operands : opBundleOperands)
3764 numOpBundleOperands += operands.size();
3767 CallIntrinsicOp::getOperandSegmentSizeAttr(),
3769 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
3771 return mlir::success();
3779 p <<
"(" << args <<
")";
3782 if (!getOpBundleOperands().empty()) {
3785 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
3789 {getOperandSegmentSizesAttrName(),
3790 getOpBundleSizesAttrName(), getIntrinAttrName(),
3791 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
3792 getResAttrsAttrName()});
3798 p, args.
getTypes(), getArgAttrsAttr(),
3799 false, getResultTypes(), getResAttrsAttr());
3809 return emitOpError(
"must appear at the module level");
3820 return emitOpError(
"must appear at the module level");
3822 if (!isa<ModuleFlagAttr>(flag))
3823 return emitOpError(
"expected a module flag attribute");
3831 void InlineAsmOp::getEffects(
3834 if (getHasSideEffects()) {
3847 getBlockAddr().getFunction());
3848 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
3851 return emitOpError(
"must reference a function defined by 'llvm.func'");
3861 BlockTagOp BlockAddressOp::getBlockTagOp() {
3867 BlockTagOp blockTagOp =
nullptr;
3868 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
3869 if (labelOp.getTag() == getBlockAddr().getTag()) {
3870 blockTagOp = labelOp;
3879 if (!getBlockTagOp())
3881 "expects an existing block label target in the referenced function");
3888 OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
3895 assert(index < getNumSuccessors() &&
"invalid successor index");
3907 rangeSegments.push_back(range.size());
3921 Block *destination = nullptr;
3922 SmallVector<OpAsmParser::UnresolvedOperand> operands;
3923 SmallVector<Type> operandTypes;
3925 if (parser.parseSuccessor(destination).failed())
3928 if (succeeded(parser.parseOptionalLParen())) {
3929 if (failed(parser.parseOperandList(
3930 operands, OpAsmParser::Delimiter::None)) ||
3931 failed(parser.parseColonTypeList(operandTypes)) ||
3932 failed(parser.parseRParen()))
3935 succOperandBlocks.push_back(destination);
3936 succOperands.emplace_back(operands);
3937 succOperandsTypes.emplace_back(operandTypes);
3940 "successor blocks")))
3951 llvm::zip(succs, succOperands),
3957 if (!succOperands.empty())
3968 return build(builder, state, cond, {},
3974 ArrayRef<llvm::OperandBundleDefT<Value>> opBundles) {
3977 opBundleOperands.reserve(opBundles.size());
3978 opBundleTags.reserve(opBundles.size());
3980 for (
const llvm::OperandBundleDefT<Value> &bundle : opBundles) {
3981 opBundleOperands.emplace_back(bundle.inputs());
3982 opBundleTags.push_back(
3987 return build(builder, state, cond, opBundleOperands, opBundleTagsAttr);
3992 llvm::OperandBundleDefT<Value> opBundle(
3994 return build(builder, state, cond, opBundle);
3999 return build(builder, state, cond,
"align",
ValueRange{ptr, align});
4005 return build(builder, state, cond,
"separate_storage",
4016 auto ptrsVectorType = getPtrs().getType();
4017 Type expectedPtrsVectorType =
4022 if (ptrsVectorType != expectedPtrsVectorType)
4023 return emitOpError(
"expected operand #1 type to be ")
4024 << expectedPtrsVectorType;
4033 auto ptrsVectorType = getPtrs().getType();
4034 Type expectedPtrsVectorType =
4039 if (ptrsVectorType != expectedPtrsVectorType)
4040 return emitOpError(
"expected operand #2 type to be ")
4041 << expectedPtrsVectorType;
4049 void LLVMDialect::initialize() {
4050 registerAttributes();
4053 addTypes<LLVMVoidType,
4056 LLVMMetadataType>();
4062 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4065 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4069 allowUnknownOperations();
4070 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4073 #define GET_OP_CLASSES
4074 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4076 #define GET_OP_CLASSES
4077 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4079 LogicalResult LLVMDialect::verifyDataLayoutString(
4083 if (maybeDataLayout)
4086 std::string message;
4087 llvm::raw_string_ostream messageStream(message);
4088 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4089 reportError(
"invalid data layout descriptor: " + message);
4094 LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4100 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4102 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4103 return verifyDataLayoutString(
4104 stringAttr.getValue(),
4105 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4108 << LLVM::LLVMDialect::getDataLayoutAttrName()
4109 <<
"' to be a string attributes";
4112 LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4120 StringAttr name = paramAttr.
getName();
4122 auto checkUnitAttrType = [&]() -> LogicalResult {
4123 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4124 return op->
emitError() << name <<
" should be a unit attribute";
4127 auto checkTypeAttrType = [&]() -> LogicalResult {
4128 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4129 return op->
emitError() << name <<
" should be a type attribute";
4132 auto checkIntegerAttrType = [&]() -> LogicalResult {
4133 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4134 return op->
emitError() << name <<
" should be an integer attribute";
4137 auto checkPointerType = [&]() -> LogicalResult {
4138 if (!llvm::isa<LLVMPointerType>(paramType))
4140 << name <<
" attribute attached to non-pointer LLVM type";
4143 auto checkIntegerType = [&]() -> LogicalResult {
4144 if (!llvm::isa<IntegerType>(paramType))
4146 << name <<
" attribute attached to non-integer LLVM type";
4149 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4150 if (failed(checkPointerType()))
4157 if (name == LLVMDialect::getNoAliasAttrName() ||
4158 name == LLVMDialect::getReadonlyAttrName() ||
4159 name == LLVMDialect::getReadnoneAttrName() ||
4160 name == LLVMDialect::getWriteOnlyAttrName() ||
4161 name == LLVMDialect::getNestAttrName() ||
4162 name == LLVMDialect::getNoCaptureAttrName() ||
4163 name == LLVMDialect::getNoFreeAttrName() ||
4164 name == LLVMDialect::getNonNullAttrName()) {
4165 if (failed(checkUnitAttrType()))
4167 if (verifyValueType && failed(checkPointerType()))
4173 if (name == LLVMDialect::getStructRetAttrName() ||
4174 name == LLVMDialect::getByValAttrName() ||
4175 name == LLVMDialect::getByRefAttrName() ||
4176 name == LLVMDialect::getElementTypeAttrName() ||
4177 name == LLVMDialect::getInAllocaAttrName() ||
4178 name == LLVMDialect::getPreallocatedAttrName()) {
4179 if (failed(checkTypeAttrType()))
4181 if (verifyValueType && failed(checkPointerTypeMatches()))
4187 if (name == LLVMDialect::getSExtAttrName() ||
4188 name == LLVMDialect::getZExtAttrName()) {
4189 if (failed(checkUnitAttrType()))
4191 if (verifyValueType && failed(checkIntegerType()))
4197 if (name == LLVMDialect::getAlignAttrName() ||
4198 name == LLVMDialect::getDereferenceableAttrName() ||
4199 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4200 if (failed(checkIntegerAttrType()))
4202 if (verifyValueType && failed(checkPointerType()))
4208 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4209 if (failed(checkIntegerAttrType()))
4215 if (name == LLVMDialect::getNoUndefAttrName() ||
4216 name == LLVMDialect::getInRegAttrName() ||
4217 name == LLVMDialect::getReturnedAttrName())
4218 return checkUnitAttrType();
4224 LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4228 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4231 Type argType = funcOp.getArgumentTypes()[argIdx];
4233 return verifyParameterAttribute(op, argType, argAttr);
4236 LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4240 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4243 Type resType = funcOp.getResultTypes()[resIdx];
4247 if (llvm::isa<LLVMVoidType>(resType))
4248 return op->
emitError() <<
"cannot attach result attributes to functions "
4249 "with a void return";
4253 auto name = resAttr.
getName();
4254 if (name == LLVMDialect::getAllocAlignAttrName() ||
4255 name == LLVMDialect::getAllocatedPointerAttrName() ||
4256 name == LLVMDialect::getByValAttrName() ||
4257 name == LLVMDialect::getByRefAttrName() ||
4258 name == LLVMDialect::getInAllocaAttrName() ||
4259 name == LLVMDialect::getNestAttrName() ||
4260 name == LLVMDialect::getNoCaptureAttrName() ||
4261 name == LLVMDialect::getNoFreeAttrName() ||
4262 name == LLVMDialect::getPreallocatedAttrName() ||
4263 name == LLVMDialect::getReadnoneAttrName() ||
4264 name == LLVMDialect::getReadonlyAttrName() ||
4265 name == LLVMDialect::getReturnedAttrName() ||
4266 name == LLVMDialect::getStackAlignmentAttrName() ||
4267 name == LLVMDialect::getStructRetAttrName() ||
4268 name == LLVMDialect::getWriteOnlyAttrName())
4269 return op->
emitError() << name <<
" is not a valid result attribute";
4270 return verifyParameterAttribute(op, resType, resAttr);
4278 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4279 if (isa<LLVM::LLVMPointerType>(type))
4280 return builder.
create<LLVM::AddressOfOp>(loc, type, symbol);
4281 if (isa<LLVM::UndefAttr>(value))
4282 return builder.
create<LLVM::UndefOp>(loc, type);
4283 if (isa<LLVM::PoisonAttr>(value))
4284 return builder.
create<LLVM::PoisonOp>(loc, type);
4285 if (isa<LLVM::ZeroAttr>(value))
4286 return builder.
create<LLVM::ZeroOp>(loc, type);
4288 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4296 StringRef name, StringRef value,
4297 LLVM::Linkage linkage) {
4300 "expected builder to point to a block constrained in an op");
4303 assert(module &&
"builder points to an op outside of a module");
4309 auto global = moduleBuilder.
create<LLVM::GlobalOp>(
4310 loc, type,
true, linkage, name,
4316 builder.
create<LLVM::AddressOfOp>(loc, ptrType, global.getSymNameAttr());
4317 return builder.
create<LLVM::GEPOp>(loc, ptrType, type, globalPtr,
static OperandRange getSuccessorOperands(Block *block, unsigned successorIndex)
Return the operand range used to transfer operands from block to its successor with the given index.
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
static Operation * materializeConstant(Dialect *dialect, OpBuilder &builder, Attribute value, Type type, Location loc)
A utility function used to materialize a constant for a given attribute and type.
static MLIRContext * getContext(OpFoldResult val)
static int parseOptionalKeywordAlternative(OpAsmParser &parser, ArrayRef< StringRef > keywords)
LogicalResult verifyCallOpVarCalleeType(OpTy callOp)
Verify that the parameter and return types of the variadic callee type match the callOp argument and ...
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)
LogicalResult verifyAtomicMemOp(OpTy memOp, Type valueType, ArrayRef< AtomicOrdering > unsupportedOrderings)
Verifies the attributes and the type of atomic memory access operations.
static void printOneOpBundle(OpAsmPrinter &p, OperandRange operands, TypeRange operandTypes, StringRef tag)
static LogicalResult verifyComdat(Operation *op, std::optional< SymbolRefAttr > attr)
static RetTy parseOptionalLLVMKeyword(OpAsmParser &parser, OperationState &result, EnumTy defaultValue)
Parse an enum from the keyword, or default to the provided default value.
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 resolveOpBundleOperands(OpAsmParser &parser, SMLoc loc, OperationState &state, ArrayRef< SmallVector< OpAsmParser::UnresolvedOperand >> opBundleOperands, ArrayRef< SmallVector< Type >> opBundleOperandTypes, StringAttr opBundleSizesAttrName)
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 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 std::optional< ParseResult > parseOpBundles(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand >> &opBundleOperands, SmallVector< SmallVector< Type >> &opBundleOperandTypes, ArrayAttr &opBundleTags)
static Operation * parentLLVMModule(Operation *op)
static ParseResult parseSwitchOpCases(OpAsmParser &parser, Type flagType, DenseIntElementsAttr &caseValues, SmallVectorImpl< Block * > &caseDestinations, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand >> &caseOperands, SmallVectorImpl< SmallVector< Type >> &caseOperandTypes)
<cases> ::= [ (case (, case )* )? ] <case> ::= integer : bb-id (( ssa-use-and-type-list ))?
static TypeAttr getCallOpVarCalleeType(LLVMFunctionType calleeType)
Gets the variadic callee type for a LLVMFunctionType.
static Type getInsertExtractValueElementType(function_ref< InFlightDiagnostic(StringRef)> emitError, Type containerType, ArrayRef< int64_t > position)
Extract the type at position in the LLVM IR aggregate type containerType.
static ParseResult parseOneOpBundle(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand >> &opBundleOperands, SmallVector< SmallVector< Type >> &opBundleOperandTypes, SmallVector< Attribute > &opBundleTags)
static ParseResult parseIndirectBrOpSucessors(OpAsmParser &parser, Type &flagType, SmallVectorImpl< Block * > &succOperandBlocks, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand >> &succOperands, SmallVectorImpl< SmallVector< Type >> &succOperandsTypes)
static void printIndirectBrOpSucessors(OpAsmPrinter &p, IndirectBrOp op, Type flagType, SuccessorRange succs, OperandRangeRange succOperands, const TypeRangeRange &succOperandsTypes)
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 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 SmallVector< Type, 1 > getCallOpResultTypes(LLVMFunctionType calleeType)
Gets the MLIR Op-like result types of a LLVMFunctionType.
static Type getI1SameShape(Type type)
Returns a boolean type that has the same shape as type.
static void printCommonGlobalAndAlias(OpAsmPrinter &p, OpType op)
static Attribute getBoolAttribute(Type type, MLIRContext *ctx, bool value)
Returns a scalar or vector boolean attribute of the given type.
static LogicalResult verifyCallOpDebugInfo(CallOp callOp, LLVMFuncOp callee)
Verify that an inlinable callsite of a debug-info-bearing function in a debug-info-bearing function h...
static 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 int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
static bool isTypeCompatibleWithAtomicOp(Type type, const DataLayout &dataLayout)
Returns true if the given type is supported by atomic operations.
static void printInsertExtractValueElementType(AsmPrinter &printer, Operation *op, Type valueType, Type containerType, DenseI64ArrayAttr position)
Nothing to print for an inferred type.
#define REGISTER_ENUM_TYPE(Ty)
static std::string diag(const llvm::Value &value)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
static VectorType getVectorType(Type scalarTy, const VectorizationStrategy *strategy)
Returns the vector type resulting from applying the provided vectorization strategy on the scalar typ...
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 ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseOptionalColonTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional colon followed by a type list, which if present must have at least one type.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
virtual ParseResult parseCustomAttributeWithFallback(Attribute &result, Type type, function_ref< ParseResult(Attribute &result, Type type)> parseAttribute)=0
Parse a custom attribute with the provided callback, unless the next token is #, in which case the ge...
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
virtual ParseResult parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
virtual void printAttribute(Attribute attr)
Attributes are known-constant values of operations.
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)
MLIRContext * getContext() const
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
The main mechanism for performing data layout queries.
static DataLayout closest(Operation *op)
Returns the layout of the closest parent operation carrying layout info.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
An attribute that represents a reference to a dense vector or tensor object.
std::enable_if_t<!std::is_base_of< Attribute, T >::value||std::is_same< Attribute, T >::value, T > getSplatValue() const
Return the splat value for this attribute.
auto getValues() const
Return the held element values as a range of the given type.
Type getElementType() const
Return the element type of this DenseElementsAttr.
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.
bool isDynamicIndex(size_t index) const
Returns whether the GEP index at the given position is a dynamic index.
size_t size() const
Returns the amount of indices of the GEPOp.
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.
std::optional< NamedAttribute > getNamed(StringRef name) const
Return the specified named attribute if present, std::nullopt otherwise.
Attribute erase(StringAttr name)
Erase the attribute with the given name from the list.
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
NamedAttribute represents a combination of a name and an Attribute value.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
virtual ParseResult parseSuccessor(Block *&dest)=0
Parse a single operation successor.
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
virtual OptionalParseResult parseOptionalOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single operand if present.
virtual ParseResult parseSuccessorAndUseList(Block *&dest, SmallVectorImpl< Value > &operands)=0
Parse a single operation successor and its operand list.
virtual OptionalParseResult parseOptionalRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region if present.
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printNewline()=0
Print a newline and indent the printer to the start of the current operation.
virtual void printSuccessorAndUseList(Block *successor, ValueRange succOperands)=0
Print the successor and its operands.
void printOperands(const ContainerType &container)
Print a comma separated list of operands.
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes=std::nullopt, ArrayRef< Location > locs=std::nullopt)
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
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...
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class implements Optional functionality for ParseResult.
ParseResult value() const
Access the internal ParseResult value.
bool has_value() const
Returns true if we contain a valid ParseResult value.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
iterator_range< OpIterator > getOps()
This class represents a specific instance of an effect.
static DerivedEffect * get()
Returns a unique instance for the derived effect class.
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.
Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
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.
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)
Builder from ArrayRef<T>.
ArrayRef< T > asArrayRef() const
A named class for passing around the variadic flag.
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...
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 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.
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.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
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.
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Value constantIndex(OpBuilder &builder, Location loc, int64_t i)
Generates a constant of index type.
Visibility
This enum describes C++ inheritance visibility.
std::string stringify(T &&t)
Generically convert a value to a std::string.
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...
const FrozenRewritePatternSet GreedyRewriteConfig bool * changed
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
A callable is either a symbol, or an SSA value, that is referenced by a call-like operation.
This is the representation of an operand reference.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
T & getOrAddProperties()
Get (or create) a properties of the provided type to be set on the operation on creation.
SmallVector< Value, 4 > operands
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addSuccessors(Block *successor)
Adds a successor to the operation sate. successor must not be null.
void addTypes(ArrayRef< Type > newTypes)
Region * addRegion()
Create a region that should be attached to the operation.