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 (getCaseValues() &&
594 return emitError(
"expects case value type to match condition value type");
599 assert(index < getNumSuccessors() &&
"invalid successor index");
601 : getCaseOperandsMutable(index - 1));
608 constexpr int32_t GEPOp::kDynamicIndex;
612 getDynamicIndices());
617 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
618 return vectorType.getElementType();
630 for (
const GEPArg &iter : indices) {
635 bool requiresConst = !rawConstantIndices.empty() &&
636 isa_and_nonnull<LLVMStructType>(currType);
637 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
641 rawConstantIndices.push_back(intC.getSExtValue());
643 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
644 dynamicIndices.push_back(val);
647 rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
652 if (rawConstantIndices.size() == 1 || !currType)
656 .Case<VectorType, LLVMArrayType>([](
auto containerType) {
657 return containerType.getElementType();
659 .Case([&](LLVMStructType structType) ->
Type {
660 int64_t memberIndex = rawConstantIndices.back();
661 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
662 structType.getBody().size())
663 return structType.getBody()[memberIndex];
666 .Default(
Type(
nullptr));
672 GEPNoWrapFlags noWrapFlags,
691 GEPNoWrapFlags noWrapFlags,
693 build(builder, result, resultType, elementType, basePtr,
703 auto idxParser = [&]() -> ParseResult {
708 if (failed(parsedInteger.
value()))
714 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
728 llvm::interleaveComma(
731 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
734 printer << cast<IntegerAttr>(cst).getInt();
744 if (indexPos >= indices.
size())
749 .Case<LLVMStructType>([&](LLVMStructType structType) -> LogicalResult {
750 auto attr = dyn_cast<IntegerAttr>(indices[indexPos]);
752 return emitOpError() <<
"expected index " << indexPos
753 <<
" indexing a struct to be constant";
755 int32_t gepIndex = attr.getInt();
758 static_cast<size_t>(gepIndex) >= elementTypes.size())
759 return emitOpError() <<
"index " << indexPos
760 <<
" indexing a struct is out of bounds";
765 indices, emitOpError);
767 .Case<VectorType, LLVMArrayType>(
768 [&](
auto containerType) -> LogicalResult {
770 indexPos + 1, indices, emitOpError);
772 .Default([&](
auto otherType) -> LogicalResult {
774 <<
"type " << otherType <<
" cannot be indexed (index #"
787 if (
static_cast<size_t>(
788 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
789 getDynamicIndices().size())
790 return emitOpError(
"expected as many dynamic indices as specified in '")
791 << getRawConstantIndicesAttrName().getValue() <<
"'";
793 if (getNoWrapFlags() == GEPNoWrapFlags::inboundsFlag)
794 return emitOpError(
"'inbounds_flag' cannot be used directly.");
797 [&] {
return emitOpError(); });
804 void LoadOp::getEffects(
813 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
814 getOrdering() != AtomicOrdering::unordered)) {
825 if (!isa<IntegerType, LLVMPointerType>(type))
830 if (bitWidth.isScalable())
833 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
837 template <
typename OpTy>
840 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
843 return memOp.emitOpError(
"unsupported type ")
844 << valueType <<
" for atomic access";
845 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
846 return memOp.emitOpError(
"unsupported ordering '")
847 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
848 if (!memOp.getAlignment())
849 return memOp.emitOpError(
"expected alignment for atomic access");
852 if (memOp.getSyncscope())
853 return memOp.emitOpError(
854 "expected syncscope to be null for non-atomic access");
859 Type valueType = getResult().getType();
861 {AtomicOrdering::release, AtomicOrdering::acq_rel});
865 Value addr,
unsigned alignment,
bool isVolatile,
866 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
867 AtomicOrdering ordering, StringRef syncscope) {
868 build(builder, state, type, addr,
870 isNonTemporal, isInvariant, isInvariantGroup, ordering,
871 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
882 void StoreOp::getEffects(
891 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
892 getOrdering() != AtomicOrdering::unordered)) {
899 Type valueType = getValue().getType();
901 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
905 Value addr,
unsigned alignment,
bool isVolatile,
906 bool isNonTemporal,
bool isInvariantGroup,
907 AtomicOrdering ordering, StringRef syncscope) {
908 build(builder, state, value, addr,
910 isNonTemporal, isInvariantGroup, ordering,
911 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
913 nullptr,
nullptr,
nullptr);
923 Type resultType = calleeType.getReturnType();
924 if (!isa<LLVM::LLVMVoidType>(resultType))
925 results.push_back(resultType);
931 return calleeType.isVarArg() ?
TypeAttr::get(calleeType) :
nullptr;
941 resultType = results.front();
948 build(builder, state, results, builder.
getStringAttr(callee), args);
958 assert(callee &&
"expected non-null callee in direct call builder");
959 build(builder, state, results,
960 nullptr, callee, args,
nullptr,
963 nullptr,
nullptr,
nullptr,
973 LLVMFunctionType calleeType, StringRef callee,
975 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
979 LLVMFunctionType calleeType, StringAttr callee,
997 nullptr,
nullptr,
nullptr,
1003 LLVMFunctionType calleeType,
ValueRange args) {
1008 nullptr,
nullptr,
nullptr,
1009 nullptr,
nullptr,
nullptr,
1020 auto calleeType = func.getFunctionType();
1024 nullptr,
nullptr,
nullptr,
1025 nullptr,
nullptr,
nullptr,
1039 return getOperand(0);
1045 auto symRef = cast<SymbolRefAttr>(callee);
1046 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1049 return setOperand(0, cast<Value>(callee));
1053 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1058 getCalleeOperands().size());
1065 if (callee.isExternal())
1067 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1071 auto hasSubprogram = [](
Operation *op) {
1076 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1078 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1080 return callOp.emitError()
1081 <<
"inlinable function call in a function with a DISubprogram "
1082 "location must have a debug location";
1088 template <
typename OpTy>
1090 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1095 if (!varCalleeType->isVarArg())
1096 return callOp.emitOpError(
1097 "expected var_callee_type to be a variadic function type");
1101 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1102 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1103 << callOp.getArgOperands().size() <<
" parameters";
1106 for (
auto [paramType, operand] :
1107 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1108 if (paramType != operand.getType())
1109 return callOp.emitOpError()
1110 <<
"var_callee_type parameter type mismatch: " << paramType
1111 <<
" != " << operand.getType();
1114 if (!callOp.getNumResults()) {
1115 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1116 return callOp.emitOpError(
"expected var_callee_type to return void");
1118 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1119 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1120 << varCalleeType->getReturnType()
1121 <<
" != " << callOp.getResult().getType();
1126 template <
typename OpType>
1129 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1131 auto isStringAttr = [](
Attribute tagAttr) {
1132 return isa<StringAttr>(tagAttr);
1134 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1135 return op.emitError(
"operand bundle tag must be a StringAttr");
1137 size_t numOpBundles = opBundleOperands.size();
1138 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1139 if (numOpBundles != numOpBundleTags)
1140 return op.emitError(
"expected ")
1141 << numOpBundles <<
" operand bundle tags, but actually got "
1157 bool isIndirect =
false;
1163 if (!getNumOperands())
1165 "must have either a `callee` attribute or at least an operand");
1166 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1168 return emitOpError(
"indirect call expects a pointer as callee: ")
1169 << getOperand(0).getType();
1176 return emitOpError()
1178 <<
"' does not reference a symbol in the current scope";
1179 auto fn = dyn_cast<LLVMFuncOp>(callee);
1181 return emitOpError() <<
"'" << calleeName.
getValue()
1182 <<
"' does not reference a valid LLVM function";
1186 fnType = fn.getFunctionType();
1189 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1191 return emitOpError(
"callee does not have a functional type: ") << fnType;
1193 if (funcType.isVarArg() && !getVarCalleeType())
1194 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1198 if (!funcType.isVarArg() &&
1199 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1200 return emitOpError() <<
"incorrect number of operands ("
1201 << (getCalleeOperands().size() - isIndirect)
1202 <<
") for callee (expecting: "
1203 << funcType.getNumParams() <<
")";
1205 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1206 return emitOpError() <<
"incorrect number of operands ("
1207 << (getCalleeOperands().size() - isIndirect)
1208 <<
") for varargs callee (expecting at least: "
1209 << funcType.getNumParams() <<
")";
1211 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1212 if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1213 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1214 << getOperand(i + isIndirect).getType()
1215 <<
" != " << funcType.getParamType(i);
1217 if (getNumResults() == 0 &&
1218 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1219 return emitOpError() <<
"expected function call to produce a value";
1221 if (getNumResults() != 0 &&
1222 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1223 return emitOpError()
1224 <<
"calling function with void result must not produce values";
1226 if (getNumResults() > 1)
1227 return emitOpError()
1228 <<
"expected LLVM function call to produce 0 or 1 result";
1230 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1231 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1232 <<
" != " << funcType.getReturnType();
1238 auto callee = getCallee();
1239 bool isDirect = callee.has_value();
1244 if (getCConv() != LLVM::CConv::C)
1245 p << stringifyCConv(getCConv()) <<
' ';
1248 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1257 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1258 p <<
'(' << args <<
')';
1261 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1262 p <<
" vararg(" << *varCalleeType <<
")";
1264 if (!getOpBundleOperands().empty()) {
1267 getOpBundleOperands().getTypes(), getOpBundleTags());
1271 {getCalleeAttrName(), getTailCallKindAttrName(),
1272 getVarCalleeTypeAttrName(), getCConvAttrName(),
1273 getOperandSegmentSizesAttrName(),
1274 getOpBundleSizesAttrName(),
1275 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1276 getResAttrsAttrName()});
1280 p << getOperand(0).getType() <<
", ";
1284 p, args.getTypes(), getArgAttrsAttr(),
1285 false, getResultTypes(), getResAttrsAttr());
1300 types.emplace_back();
1305 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1310 resTypes, resultAttrs)) {
1312 return parser.
emitError(trailingTypesLoc,
1313 "expected direct call to have 1 trailing types");
1314 return parser.
emitError(trailingTypesLoc,
1315 "expected trailing function type");
1318 if (resTypes.size() > 1)
1319 return parser.
emitError(trailingTypesLoc,
1320 "expected function with 0 or 1 result");
1321 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1322 return parser.
emitError(trailingTypesLoc,
1323 "expected a non-void result type");
1329 llvm::append_range(types, argTypes);
1333 if (resTypes.size() != 0)
1347 if (failed(*parseResult))
1348 return *parseResult;
1349 operands.push_back(funcPtrOperand);
1358 StringAttr opBundleSizesAttrName) {
1359 unsigned opBundleIndex = 0;
1360 for (
const auto &[operands, types] :
1361 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1362 if (operands.size() != types.size())
1363 return parser.
emitError(loc,
"expected ")
1365 <<
" types for operand bundle operands for operand bundle #"
1366 << opBundleIndex <<
", but actually got " << types.size();
1372 opBundleSizes.reserve(opBundleOperands.size());
1373 for (
const auto &operands : opBundleOperands)
1374 opBundleSizes.push_back(operands.size());
1377 opBundleSizesAttrName,
1389 SymbolRefAttr funcAttr;
1390 TypeAttr varCalleeType;
1394 ArrayAttr opBundleTags;
1398 getCConvAttrName(result.
name),
1400 parser, result, LLVM::CConv::C)));
1403 getTailCallKindAttrName(result.
name),
1405 parseOptionalLLVMKeyword<TailCallKind>(
1411 bool isDirect = operands.empty();
1424 StringAttr varCalleeTypeAttrName =
1425 CallOp::getVarCalleeTypeAttrName(result.
name);
1437 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1438 result && failed(*result))
1440 if (opBundleTags && !opBundleTags.empty())
1441 result.
addAttribute(CallOp::getOpBundleTagsAttrName(result.
name).getValue(),
1451 argAttrs, resultAttrs))
1454 parser.
getBuilder(), result, argAttrs, resultAttrs,
1455 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
1457 opBundleOperandTypes,
1458 getOpBundleSizesAttrName(result.
name)))
1461 int32_t numOpBundleOperands = 0;
1462 for (
const auto &operands : opBundleOperands)
1463 numOpBundleOperands += operands.size();
1466 CallOp::getOperandSegmentSizeAttr(),
1468 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1472 LLVMFunctionType CallOp::getCalleeFunctionType() {
1473 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1474 return *varCalleeType;
1485 auto calleeType = func.getFunctionType();
1488 nullptr,
nullptr, normalOps, unwindOps,
1489 nullptr,
nullptr, {}, {}, normal, unwind);
1496 build(builder, state, tys,
1497 nullptr, callee, ops,
nullptr,
1498 nullptr, normalOps, unwindOps,
nullptr,
nullptr, {}, {},
1508 nullptr,
nullptr, normalOps, unwindOps,
1509 nullptr,
nullptr, {}, {}, normal, unwind);
1513 assert(index < getNumSuccessors() &&
"invalid successor index");
1515 : getUnwindDestOperandsMutable());
1523 return getOperand(0);
1529 auto symRef = cast<SymbolRefAttr>(callee);
1530 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1533 return setOperand(0, cast<Value>(callee));
1537 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1542 getCalleeOperands().size());
1549 Block *unwindDest = getUnwindDest();
1550 if (unwindDest->
empty())
1551 return emitError(
"must have at least one operation in unwind destination");
1554 if (!isa<LandingpadOp>(unwindDest->
front()))
1555 return emitError(
"first operation in unwind destination should be a "
1556 "llvm.landingpad operation");
1565 auto callee = getCallee();
1566 bool isDirect = callee.has_value();
1571 if (getCConv() != LLVM::CConv::C)
1572 p << stringifyCConv(getCConv()) <<
' ';
1580 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1587 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1588 p <<
" vararg(" << *varCalleeType <<
")";
1590 if (!getOpBundleOperands().empty()) {
1593 getOpBundleOperands().getTypes(), getOpBundleTags());
1597 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1598 getCConvAttrName(), getVarCalleeTypeAttrName(),
1599 getOpBundleSizesAttrName(),
1600 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1601 getResAttrsAttrName()});
1605 p << getOperand(0).getType() <<
", ";
1607 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1609 false, getResultTypes(), getResAttrsAttr());
1622 SymbolRefAttr funcAttr;
1623 TypeAttr varCalleeType;
1626 ArrayAttr opBundleTags;
1627 Block *normalDest, *unwindDest;
1633 getCConvAttrName(result.
name),
1635 parser, result, LLVM::CConv::C)));
1640 bool isDirect = operands.empty();
1656 StringAttr varCalleeTypeAttrName =
1657 InvokeOp::getVarCalleeTypeAttrName(result.
name);
1669 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1670 result && failed(*result))
1672 if (opBundleTags && !opBundleTags.empty())
1674 InvokeOp::getOpBundleTagsAttrName(result.
name).getValue(),
1684 argAttrs, resultAttrs))
1687 parser.
getBuilder(), result, argAttrs, resultAttrs,
1688 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
1691 opBundleOperandTypes,
1692 getOpBundleSizesAttrName(result.
name)))
1699 int32_t numOpBundleOperands = 0;
1700 for (
const auto &operands : opBundleOperands)
1701 numOpBundleOperands += operands.size();
1704 InvokeOp::getOperandSegmentSizeAttr(),
1706 static_cast<int32_t>(normalOperands.size()),
1707 static_cast<int32_t>(unwindOperands.size()),
1708 numOpBundleOperands}));
1712 LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1713 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1714 return *varCalleeType;
1724 if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1725 if (!func.getPersonality())
1727 "llvm.landingpad needs to be in a function with a personality");
1733 if (!getCleanup() && getOperands().empty())
1734 return emitError(
"landingpad instruction expects at least one clause or "
1735 "cleanup attribute");
1737 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1738 value = getOperand(idx);
1739 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1746 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1749 <<
"global addresses expected as operand to "
1750 "bitcast used in clauses for landingpad";
1758 << idx <<
" is not a known constant - null, addressof, bitcast";
1765 p << (getCleanup() ?
" cleanup " :
" ");
1768 for (
auto value : getOperands()) {
1771 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1772 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1819 Type llvmType = containerType;
1821 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1829 for (int64_t idx : position) {
1830 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1831 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1832 emitError(
"position out of bounds: ") << idx;
1835 llvmType = arrayType.getElementType();
1836 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1838 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1839 emitError(
"position out of bounds: ") << idx;
1842 llvmType = structType.getBody()[idx];
1844 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1855 for (int64_t idx : position) {
1856 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1857 llvmType = structType.getBody()[idx];
1859 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1864 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1865 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
1867 newPos.append(getPosition().begin(), getPosition().end());
1868 setPosition(newPos);
1869 getContainerMutable().set(extractValueOp.getContainer());
1877 if (isa<SplatElementsAttr>(constval))
1879 if (getPosition().size() == 1)
1884 auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1887 bool switchedToInsertedValue =
false;
1888 while (insertValueOp) {
1890 auto extractPosSize = extractPos.size();
1891 auto insertPosSize = insertPos.size();
1894 if (extractPos == insertPos)
1895 return insertValueOp.getValue();
1909 if (extractPosSize > insertPosSize &&
1910 extractPos.take_front(insertPosSize) == insertPos) {
1911 insertValueOp = insertValueOp.getValue().getDefiningOp<InsertValueOp>();
1912 extractPos = extractPos.drop_front(insertPosSize);
1913 switchedToInsertedValue =
true;
1918 unsigned min =
std::min(extractPosSize, insertPosSize);
1930 if (extractPos.take_front(
min) == insertPos.take_front(
min))
1935 if (!switchedToInsertedValue) {
1938 getContainerMutable().assign(insertValueOp.getContainer());
1939 result = getResult();
1941 insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1947 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1953 if (getRes().
getType() != valueType)
1954 return emitOpError() <<
"Type mismatch: extracting from "
1955 << getContainer().getType() <<
" should produce "
1956 << valueType <<
" but this op returns "
1957 << getRes().getType();
1963 build(builder, state,
1978 [&](StringRef msg) {
1982 return success(!!valueType);
1992 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1998 if (getValue().
getType() != valueType)
1999 return emitOpError() <<
"Type mismatch: cannot insert "
2000 << getValue().getType() <<
" into "
2001 << getContainer().getType();
2011 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2015 Type expectedType = parent.getFunctionType().getReturnType();
2016 if (llvm::isa<LLVMVoidType>(expectedType)) {
2020 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2024 if (llvm::isa<LLVMVoidType>(expectedType))
2027 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2030 if (expectedType != getArg().
getType()) {
2032 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2046 assert(module &&
"unexpected operation outside of a module");
2051 return dyn_cast_or_null<GlobalOp>(
2056 return dyn_cast_or_null<LLVMFuncOp>(
2061 return dyn_cast_or_null<AliasOp>(
2070 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2071 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2072 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2074 if (!global && !
function && !alias)
2075 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2076 "'llvm.mlir.alias' or 'llvm.func'");
2078 LLVMPointerType type =
getType();
2079 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2080 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2081 return emitOpError(
"pointer address space must match address space of the "
2082 "referenced global or alias");
2089 return getGlobalNameAttr();
2110 getFunctionNameAttr());
2111 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2112 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2114 if (!
function && !alias)
2116 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2119 if (alias.getInitializer()
2120 .walk([&](AddressOfOp addrOp) {
2121 if (addrOp.getGlobal(symbolTable))
2122 return WalkResult::interrupt();
2123 return WalkResult::advance();
2126 return emitOpError(
"must reference an alias to a function");
2129 if ((
function &&
function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2130 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2132 "target function with 'extern_weak' linkage not allowed");
2148 StringRef symName) {
2155 LogicalResult ComdatOp::verifyRegions() {
2156 Region &body = getBody();
2158 if (!isa<ComdatSelectorOp>(op))
2159 return op.emitError(
2160 "only comdat selector symbols can appear in a comdat region");
2170 bool isConstant, Linkage linkage, StringRef name,
2171 Attribute value, uint64_t alignment,
unsigned addrSpace,
2172 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2206 if (!dbgExprs.empty())
2213 template <
typename OpType>
2215 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2216 StringRef visibility = stringifyVisibility(op.getVisibility_());
2217 if (!visibility.empty())
2218 p << visibility <<
' ';
2219 if (op.getThreadLocal_())
2220 p <<
"thread_local ";
2221 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2222 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2229 printCommonGlobalAndAlias<GlobalOp>(p, *
this);
2234 if (
auto value = getValueOrNull())
2237 if (
auto comdat = getComdat())
2238 p <<
" comdat(" << *comdat <<
')';
2244 {SymbolTable::getSymbolAttrName(),
2245 getGlobalTypeAttrName(), getConstantAttrName(),
2246 getValueAttrName(), getLinkageAttrName(),
2247 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2248 getVisibility_AttrName(), getComdatAttrName(),
2249 getUnnamedAddrAttrName()});
2252 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2256 Region &initializer = getInitializerRegion();
2257 if (!initializer.
empty()) {
2264 std::optional<SymbolRefAttr> attr) {
2269 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2270 return op->
emitError() <<
"expected comdat symbol";
2280 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2281 if (blockTags.contains(blockTagOp.getTag())) {
2282 blockTagOp.emitError()
2283 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2284 <<
"' in the same function: ";
2285 return WalkResult::interrupt();
2287 blockTags.insert(blockTagOp.getTag());
2296 template <
typename OpType>
2303 ctx, parseOptionalLLVMKeyword<Linkage>(
2304 parser, result, LLVM::Linkage::External)));
2309 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2310 parser, result, LLVM::Visibility::Default)));
2319 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2335 if (parseCommonGlobalAndAlias<GlobalOp>(parser, result).failed())
2357 SymbolRefAttr comdat;
2370 if (types.size() > 1)
2374 if (types.empty()) {
2375 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2378 strAttr.getValue().size());
2379 types.push_back(arrayType);
2382 "type can only be omitted for string globals");
2388 if (parseResult.
has_value() && failed(*parseResult))
2398 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2399 return intValue.getValue().isZero();
2400 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2401 return fpValue.getValue().isZero();
2402 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2404 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2406 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2413 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2414 LLVMMetadataType, LLVMLabelType>(
getType())
2415 : llvm::isa<PointerElementTypeInterface>(
getType());
2418 "expects type to be a valid element type for an LLVM global");
2420 return emitOpError(
"must appear at the module level");
2422 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2423 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2424 IntegerType elementType =
2425 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2426 if (!elementType || elementType.getWidth() != 8 ||
2427 type.getNumElements() != strAttr.getValue().size())
2429 "requires an i8 array type of the length equal to that of the string "
2433 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2434 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2435 return emitOpError()
2436 <<
"this target extension type cannot be used in a global";
2439 return emitOpError() <<
"global with target extension type can only be "
2440 "initialized with zero-initializer";
2443 if (getLinkage() == Linkage::Common) {
2444 if (
Attribute value = getValueOrNull()) {
2446 return emitOpError()
2447 <<
"expected zero value for '"
2448 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2453 if (getLinkage() == Linkage::Appending) {
2454 if (!llvm::isa<LLVMArrayType>(
getType())) {
2455 return emitOpError() <<
"expected array type for '"
2456 << stringifyLinkage(Linkage::Appending)
2464 std::optional<uint64_t> alignAttr = getAlignment();
2465 if (alignAttr.has_value()) {
2466 uint64_t value = alignAttr.value();
2467 if (!llvm::isPowerOf2_64(value))
2468 return emitError() <<
"alignment attribute is not a power of 2";
2474 LogicalResult GlobalOp::verifyRegions() {
2475 if (
Block *b = getInitializerBlock()) {
2476 ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2477 if (ret.operand_type_begin() == ret.operand_type_end())
2478 return emitOpError(
"initializer region cannot return void");
2479 if (*ret.operand_type_begin() !=
getType())
2480 return emitOpError(
"initializer region type ")
2481 << *ret.operand_type_begin() <<
" does not match global type "
2485 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2486 if (!iface || !iface.hasNoEffect())
2487 return op.emitError()
2488 <<
"ops with side effects not allowed in global initializers";
2491 if (getValueOrNull())
2492 return emitOpError(
"cannot have both initializer value and region");
2507 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2510 return op->
emitError(
"data element must be symbol or #llvm.zero");
2527 if (getCtors().size() == getPriorities().size() &&
2528 getCtors().size() == getData().size())
2531 "ctors, priorities, and data must have the same number of elements");
2552 if (getDtors().size() == getPriorities().size() &&
2553 getDtors().size() == getData().size())
2556 "dtors, priorities, and data must have the same number of elements");
2564 Linkage linkage, StringRef name,
bool dsoLocal,
2584 printCommonGlobalAndAlias<AliasOp>(p, *
this);
2588 {SymbolTable::getSymbolAttrName(),
2589 getAliasTypeAttrName(), getLinkageAttrName(),
2590 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2591 getVisibility_AttrName(), getUnnamedAddrAttrName()});
2594 p <<
" : " <<
getType() <<
' ';
2607 if (parseCommonGlobalAndAlias<AliasOp>(parser, result).failed())
2620 if (types.size() > 1)
2634 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2635 LLVMMetadataType, LLVMLabelType>(
getType())
2636 : llvm::isa<PointerElementTypeInterface>(
getType());
2639 "expects type to be a valid element type for an LLVM global alias");
2642 switch (getLinkage()) {
2643 case Linkage::External:
2644 case Linkage::Internal:
2645 case Linkage::Private:
2647 case Linkage::WeakODR:
2648 case Linkage::Linkonce:
2649 case Linkage::LinkonceODR:
2650 case Linkage::AvailableExternally:
2653 return emitOpError()
2654 <<
"'" << stringifyLinkage(getLinkage())
2655 <<
"' linkage not supported in aliases, available options: private, "
2656 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2657 "available_externally";
2663 LogicalResult AliasOp::verifyRegions() {
2664 Block &b = getInitializerBlock();
2666 if (ret.getNumOperands() == 0 ||
2667 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2668 return emitOpError(
"initializer region must always return a pointer");
2671 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2672 if (!iface || !iface.hasNoEffect())
2673 return op.emitError()
2674 <<
"ops with side effects are not allowed in alias initializers";
2680 unsigned AliasOp::getAddrSpace() {
2681 Block &initializer = getInitializerBlock();
2683 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2684 return ptrTy.getAddressSpace();
2694 auto containerType = v1.
getType();
2698 build(builder, state, vType, v1, v2, mask);
2699 state.addAttributes(attrs);
2712 "expected an LLVM compatible vector type");
2725 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2726 return emitOpError(
"expected a splat operation for scalable vectors");
2736 assert(empty() &&
"function already has an entry block");
2741 LLVMFunctionType type = getFunctionType();
2742 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2743 entry->
addArgument(type.getParamType(i), getLoc());
2748 StringRef name,
Type type, LLVM::Linkage linkage,
2749 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2752 std::optional<uint64_t> functionEntryCount) {
2768 if (functionEntryCount)
2771 if (argAttrs.empty())
2774 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2775 "expected as many argument attribute lists as arguments");
2777 builder, result, argAttrs, std::nullopt,
2778 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2789 if (outputs.size() > 1) {
2790 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2791 "one function result");
2797 for (
auto t : inputs) {
2799 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2800 "type for function arguments");
2803 llvmInputs.push_back(t);
2810 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2811 "type for function results")
2829 getLinkageAttrName(result.
name),
2831 parseOptionalLLVMKeyword<Linkage>(
2832 parser, result, LLVM::Linkage::External)));
2837 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2838 parser, result, LLVM::Visibility::Default)));
2843 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2848 getCConvAttrName(result.
name),
2850 parser, result, LLVM::CConv::C)));
2852 StringAttr nameAttr;
2862 parser,
true, entryArgs, isVariadic, resultTypes,
2867 for (
auto &arg : entryArgs)
2868 argTypes.push_back(arg.type);
2878 int64_t minRange, maxRange;
2885 getVscaleRangeAttrName(result.
name),
2892 SymbolRefAttr comdat;
2903 parser.
getBuilder(), result, entryArgs, resultAttrs,
2904 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2909 return failure(parseResult.
has_value() && failed(*parseResult));
2917 if (getLinkage() != LLVM::Linkage::External)
2918 p << stringifyLinkage(getLinkage()) <<
' ';
2919 StringRef visibility = stringifyVisibility(getVisibility_());
2920 if (!visibility.empty())
2921 p << visibility <<
' ';
2922 if (
auto unnamedAddr = getUnnamedAddr()) {
2923 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2927 if (getCConv() != LLVM::CConv::C)
2928 p << stringifyCConv(getCConv()) <<
' ';
2932 LLVMFunctionType fnType = getFunctionType();
2935 argTypes.reserve(fnType.getNumParams());
2936 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
2937 argTypes.push_back(fnType.getParamType(i));
2939 Type returnType = fnType.getReturnType();
2940 if (!llvm::isa<LLVMVoidType>(returnType))
2941 resTypes.push_back(returnType);
2944 isVarArg(), resTypes);
2947 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
2948 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
2949 << vscale->getMaxRange().getInt() <<
')';
2952 if (
auto comdat = getComdat())
2953 p <<
" comdat(" << *comdat <<
')';
2957 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
2958 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
2959 getComdatAttrName(), getUnnamedAddrAttrName(),
2960 getVscaleRangeAttrName()});
2963 Region &body = getBody();
2964 if (!body.empty()) {
2976 if (getLinkage() == LLVM::Linkage::Common)
2977 return emitOpError() <<
"functions cannot have '"
2978 << stringifyLinkage(LLVM::Linkage::Common)
2985 if (getLinkage() != LLVM::Linkage::External &&
2986 getLinkage() != LLVM::Linkage::ExternWeak)
2987 return emitOpError() <<
"external functions must have '"
2988 << stringifyLinkage(LLVM::Linkage::External)
2990 << stringifyLinkage(LLVM::Linkage::ExternWeak)
2996 if (isNoInline() && isAlwaysInline())
2997 return emitError(
"no_inline and always_inline attributes are incompatible");
2999 if (isOptimizeNone() && !isNoInline())
3000 return emitOpError(
"with optimize_none must also be no_inline");
3002 Type landingpadResultTy;
3003 StringRef diagnosticMessage;
3004 bool isLandingpadTypeConsistent =
3006 const auto checkType = [&](
Type type, StringRef errorMessage) {
3007 if (!landingpadResultTy) {
3008 landingpadResultTy = type;
3011 if (landingpadResultTy != type) {
3012 diagnosticMessage = errorMessage;
3018 .Case<LandingpadOp>([&](
auto landingpad) {
3019 constexpr StringLiteral errorMessage =
3020 "'llvm.landingpad' should have a consistent result type "
3021 "inside a function";
3022 return checkType(landingpad.getType(), errorMessage);
3024 .Case<ResumeOp>([&](
auto resume) {
3025 constexpr StringLiteral errorMessage =
3026 "'llvm.resume' should have a consistent input type inside a "
3028 return checkType(resume.getValue().getType(), errorMessage);
3031 }).wasInterrupted();
3032 if (!isLandingpadTypeConsistent) {
3033 assert(!diagnosticMessage.empty() &&
3034 "Expecting a non-empty diagnostic message");
3046 LogicalResult LLVMFuncOp::verifyRegions() {
3050 unsigned numArguments = getFunctionType().getNumParams();
3051 Block &entryBlock = front();
3052 for (
unsigned i = 0; i < numArguments; ++i) {
3055 return emitOpError(
"entry block argument #")
3056 << i <<
" is not of LLVM type";
3062 Region *LLVMFuncOp::getCallableRegion() {
3091 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3092 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3093 return emitOpError()
3094 <<
"target extension type does not support zero-initializer";
3116 if (
auto vecType = dyn_cast<VectorType>(t)) {
3117 assert(!vecType.isScalable() &&
3118 "number of elements of a scalable vector type is unknown");
3119 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3121 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3122 return arrayType.getNumElements() *
3130 if (
auto vecType = dyn_cast<VectorType>(t)) {
3131 if (vecType.isScalable())
3135 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3143 LLVM::LLVMArrayType arrayType,
3144 ArrayAttr arrayAttr,
int dim) {
3145 if (arrayType.getNumElements() != arrayAttr.size())
3146 return op.emitOpError()
3147 <<
"array attribute size does not match array type size in "
3149 << dim <<
": " << arrayAttr.size() <<
" vs. "
3150 << arrayType.getNumElements();
3155 if (
auto subArrayType =
3156 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3158 if (elementsVerified.insert(elementAttr).second) {
3159 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3161 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3163 return op.emitOpError()
3164 <<
"nested attribute for sub-array in dimension " << dim
3165 <<
" at index " << idx
3166 <<
" must be a zero, or undef, or array attribute";
3180 auto structType = dyn_cast<LLVM::LLVMStructType>(arrayType.getElementType());
3182 return op.emitOpError() <<
"for array with an array attribute must have a "
3183 "struct element type";
3187 size_t numStructElements = structType.getBody().size();
3189 if (elementsVerified.insert(elementAttr).second) {
3190 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3192 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3194 return op.emitOpError()
3195 <<
"nested attribute for struct element at index " << idx
3196 <<
" must be a zero, or undef, or array attribute";
3197 if (subArrayAttr.size() != numStructElements)
3198 return op.emitOpError()
3199 <<
"nested array attribute size for struct element at index "
3200 << idx <<
" must match struct size: " << subArrayAttr.size()
3201 <<
" vs. " << numStructElements;
3209 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3210 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3211 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3212 !arrayType.getElementType().isInteger(8)) {
3213 return emitOpError() <<
"expected array type of "
3214 << sAttr.getValue().size()
3215 <<
" i8 elements for the string constant";
3219 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3220 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3222 return emitOpError() <<
"expected array attribute for a struct constant";
3226 if (arrayAttr.size() != elementTypes.size()) {
3227 return emitOpError() <<
"expected array attribute of size "
3228 << elementTypes.size();
3230 for (
auto elementTy : elementTypes) {
3231 if (!isa<IntegerType, FloatType, LLVMPPCFP128Type>(elementTy)) {
3232 return emitOpError() <<
"expected struct element types to be floating "
3233 "point type or integer type";
3237 for (
size_t i = 0; i < elementTypes.size(); ++i) {
3239 if (!isa<IntegerAttr, FloatAttr>(element)) {
3240 return emitOpError()
3241 <<
"expected struct element attribute types to be floating "
3242 "point type or integer type";
3244 auto elementType = cast<TypedAttr>(element).getType();
3245 if (elementType != elementTypes[i]) {
3246 return emitOpError()
3247 <<
"struct element at index " << i <<
" is of wrong type";
3253 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
3254 return emitOpError() <<
"does not support target extension type.";
3258 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
3259 if (!llvm::isa<IntegerType>(
getType()))
3260 return emitOpError() <<
"expected integer type";
3261 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3262 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
3263 unsigned floatWidth = APFloat::getSizeInBits(sem);
3264 if (
auto floatTy = dyn_cast<FloatType>(
getType())) {
3265 if (floatTy.getWidth() != floatWidth) {
3266 return emitOpError() <<
"expected float type of width " << floatWidth;
3271 if (isa<IntegerType>(
getType()) && !
getType().isInteger(floatWidth)) {
3272 return emitOpError() <<
"expected integer type of width " << floatWidth;
3274 }
else if (isa<ElementsAttr>(getValue())) {
3278 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3279 if (!splatElementsAttr)
3280 return emitOpError()
3281 <<
"scalable vector type requires a splat attribute";
3284 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3285 return emitOpError() <<
"expected vector or array type";
3287 if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3288 int64_t attrNumElements = elementsAttr.getNumElements();
3290 return emitOpError()
3291 <<
"type and attribute have a different number of elements: "
3294 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3295 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3297 return emitOpError() <<
"expected array type";
3302 return emitOpError()
3303 <<
"only supports integer, float, string or elements attributes";
3309 bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3311 auto typedAttr = dyn_cast<TypedAttr>(value);
3318 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3323 if (isBuildableWith(value, type))
3324 return builder.
create<LLVM::ConstantOp>(loc, cast<TypedAttr>(value));
3329 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3337 AtomicOrdering ordering, StringRef syncscope,
3338 unsigned alignment,
bool isVolatile) {
3339 build(builder, state, val.
getType(), binOp, ptr, val, ordering,
3340 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3343 nullptr,
nullptr,
nullptr);
3347 auto valType = getVal().getType();
3348 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3349 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3350 getBinOp() == AtomicBinOp::fminimum ||
3351 getBinOp() == AtomicBinOp::fmaximum) {
3354 return emitOpError(
"expected LLVM IR fixed vector type");
3355 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3358 "expected LLVM IR floating point type for vector element");
3360 return emitOpError(
"expected LLVM IR floating point type");
3362 }
else if (getBinOp() == AtomicBinOp::xchg) {
3365 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3367 auto intType = llvm::dyn_cast<IntegerType>(valType);
3368 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3369 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3371 return emitOpError(
"expected LLVM IR integer type");
3374 if (
static_cast<unsigned>(getOrdering()) <
3375 static_cast<unsigned>(AtomicOrdering::monotonic))
3376 return emitOpError() <<
"expected at least '"
3377 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3390 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3395 AtomicOrdering successOrdering,
3396 AtomicOrdering failureOrdering, StringRef syncscope,
3397 unsigned alignment,
bool isWeak,
bool isVolatile) {
3399 successOrdering, failureOrdering,
3400 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3402 isVolatile,
nullptr,
3403 nullptr,
nullptr,
nullptr);
3407 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3409 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3410 auto valType = getVal().getType();
3413 return emitOpError(
"unexpected LLVM IR type");
3414 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3415 getFailureOrdering() < AtomicOrdering::monotonic)
3416 return emitOpError(
"ordering must be at least 'monotonic'");
3417 if (getFailureOrdering() == AtomicOrdering::release ||
3418 getFailureOrdering() == AtomicOrdering::acq_rel)
3419 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3428 AtomicOrdering ordering, StringRef syncscope) {
3429 build(builder, state, ordering,
3430 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3434 if (getOrdering() == AtomicOrdering::not_atomic ||
3435 getOrdering() == AtomicOrdering::unordered ||
3436 getOrdering() == AtomicOrdering::monotonic)
3437 return emitOpError(
"can be given only acquire, release, acq_rel, "
3438 "and seq_cst orderings");
3448 template <
class ExtOp>
3450 IntegerType inputType, outputType;
3453 return op.emitError(
3454 "input type is a vector but output type is an integer");
3457 return op.emitError(
"input and output vectors are of incompatible shape");
3460 inputType = cast<IntegerType>(
3461 cast<VectorType>(op.getArg().getType()).getElementType());
3462 outputType = cast<IntegerType>(
3463 cast<VectorType>(op.getResult().getType()).getElementType());
3467 inputType = cast<IntegerType>(op.getArg().getType());
3468 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3470 return op.emitError(
3471 "input type is an integer but output type is a vector");
3474 if (outputType.getWidth() <= inputType.getWidth())
3475 return op.emitError(
"integer width of the output type is smaller or "
3476 "equal to the integer width of the input type");
3484 LogicalResult
ZExtOp::verify() {
return verifyExtOp<ZExtOp>(*
this); }
3487 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3491 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3499 LogicalResult
SExtOp::verify() {
return verifyExtOp<SExtOp>(*
this); }
3506 template <
typename T>
3508 typename T::FoldAdaptor adaptor) {
3510 if (castOp.getArg().getType() == castOp.getType())
3511 return castOp.getArg();
3512 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3514 if (prev.getArg().getType() == castOp.getType())
3515 return prev.getArg();
3517 castOp.getArgMutable().set(prev.getArg());
3518 return Value{castOp};
3523 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3528 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3530 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3535 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3536 return emitOpError(
"can only cast pointers from and to pointers");
3541 auto isVector = llvm::IsaPred<VectorType>;
3545 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3546 return emitOpError(
"cannot cast pointer to vector of pointers");
3548 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3549 return emitOpError(
"cannot cast vector of pointers to pointer");
3553 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3554 return emitOpError(
"cannot cast pointers of different address spaces, "
3555 "use 'llvm.addrspacecast' instead");
3564 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3568 Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3576 adaptor.getDynamicIndices());
3580 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
3581 if (integer.getValue().isZero())
3588 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3595 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3596 gepArgs.emplace_back(val);
3598 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3604 gepArgs.emplace_back(integer.getInt());
3612 getDynamicIndicesMutable().assign(dynamicIndices);
3613 setRawConstantIndices(rawConstantIndices);
3614 return Value{*
this};
3620 Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3627 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3631 if (rhs.getValue().getZExtValue() >=
3632 getLhs().
getType().getIntOrFloatBitWidth())
3635 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3647 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3651 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3663 if (!getIntrin().starts_with(
"llvm."))
3664 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3672 build(builder, state,
TypeRange{}, intrin, args,
3673 FastmathFlagsAttr{},
3680 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3681 build(builder, state,
TypeRange{}, intrin, args,
3688 mlir::Type resultType, mlir::StringAttr intrin,
3690 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
3698 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3699 build(builder, state, resultTypes, intrin, args, fastMathFlags,
3706 StringAttr intrinAttr;
3710 ArrayAttr opBundleTags;
3724 return mlir::failure();
3727 return mlir::failure();
3732 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
3733 result && failed(*result))
3735 if (opBundleTags && !opBundleTags.empty())
3737 CallIntrinsicOp::getOpBundleTagsAttrName(result.
name).getValue(),
3741 return mlir::failure();
3746 operands, argAttrs, resultAttrs))
3749 parser.
getBuilder(), result, argAttrs, resultAttrs,
3750 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
3753 opBundleOperandTypes,
3754 getOpBundleSizesAttrName(result.
name)))
3757 int32_t numOpBundleOperands = 0;
3758 for (
const auto &operands : opBundleOperands)
3759 numOpBundleOperands += operands.size();
3762 CallIntrinsicOp::getOperandSegmentSizeAttr(),
3764 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
3766 return mlir::success();
3774 p <<
"(" << args <<
")";
3777 if (!getOpBundleOperands().empty()) {
3780 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
3784 {getOperandSegmentSizesAttrName(),
3785 getOpBundleSizesAttrName(), getIntrinAttrName(),
3786 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
3787 getResAttrsAttrName()});
3793 p, args.
getTypes(), getArgAttrsAttr(),
3794 false, getResultTypes(), getResAttrsAttr());
3804 return emitOpError(
"must appear at the module level");
3815 return emitOpError(
"must appear at the module level");
3817 if (!isa<ModuleFlagAttr>(flag))
3818 return emitOpError(
"expected a module flag attribute");
3826 void InlineAsmOp::getEffects(
3829 if (getHasSideEffects()) {
3842 getBlockAddr().getFunction());
3843 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
3846 return emitOpError(
"must reference a function defined by 'llvm.func'");
3856 BlockTagOp BlockAddressOp::getBlockTagOp() {
3862 BlockTagOp blockTagOp =
nullptr;
3863 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
3864 if (labelOp.getTag() == getBlockAddr().getTag()) {
3865 blockTagOp = labelOp;
3874 if (!getBlockTagOp())
3876 "expects an existing block label target in the referenced function");
3883 OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
3890 assert(index < getNumSuccessors() &&
"invalid successor index");
3902 rangeSegments.push_back(range.size());
3916 Block *destination = nullptr;
3917 SmallVector<OpAsmParser::UnresolvedOperand> operands;
3918 SmallVector<Type> operandTypes;
3920 if (parser.parseSuccessor(destination).failed())
3923 if (succeeded(parser.parseOptionalLParen())) {
3924 if (failed(parser.parseOperandList(
3925 operands, OpAsmParser::Delimiter::None)) ||
3926 failed(parser.parseColonTypeList(operandTypes)) ||
3927 failed(parser.parseRParen()))
3930 succOperandBlocks.push_back(destination);
3931 succOperands.emplace_back(operands);
3932 succOperandsTypes.emplace_back(operandTypes);
3935 "successor blocks")))
3946 llvm::zip(succs, succOperands),
3952 if (!succOperands.empty())
3963 return build(builder, state, cond, {},
3969 ArrayRef<llvm::OperandBundleDefT<Value>> opBundles) {
3972 opBundleOperands.reserve(opBundles.size());
3973 opBundleTags.reserve(opBundles.size());
3975 for (
const llvm::OperandBundleDefT<Value> &bundle : opBundles) {
3976 opBundleOperands.emplace_back(bundle.inputs());
3977 opBundleTags.push_back(
3982 return build(builder, state, cond, opBundleOperands, opBundleTagsAttr);
3987 llvm::OperandBundleDefT<Value> opBundle(
3989 return build(builder, state, cond, opBundle);
3994 return build(builder, state, cond,
"align",
ValueRange{ptr, align});
4000 return build(builder, state, cond,
"separate_storage",
4011 auto ptrsVectorType = getPtrs().getType();
4012 Type expectedPtrsVectorType =
4017 if (ptrsVectorType != expectedPtrsVectorType)
4018 return emitOpError(
"expected operand #1 type to be ")
4019 << expectedPtrsVectorType;
4028 auto ptrsVectorType = getPtrs().getType();
4029 Type expectedPtrsVectorType =
4034 if (ptrsVectorType != expectedPtrsVectorType)
4035 return emitOpError(
"expected operand #2 type to be ")
4036 << expectedPtrsVectorType;
4045 if (!getTailCallKindAttr())
4048 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4050 "tail call kind 'musttail' is not supported by this operation");
4059 void LLVMDialect::initialize() {
4060 registerAttributes();
4063 addTypes<LLVMVoidType,
4066 LLVMMetadataType>();
4072 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4075 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4079 allowUnknownOperations();
4080 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4083 #define GET_OP_CLASSES
4084 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4086 #define GET_OP_CLASSES
4087 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4089 LogicalResult LLVMDialect::verifyDataLayoutString(
4093 if (maybeDataLayout)
4096 std::string message;
4097 llvm::raw_string_ostream messageStream(message);
4098 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4099 reportError(
"invalid data layout descriptor: " + message);
4104 LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4110 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4112 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4113 return verifyDataLayoutString(
4114 stringAttr.getValue(),
4115 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4118 << LLVM::LLVMDialect::getDataLayoutAttrName()
4119 <<
"' to be a string attributes";
4122 LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4130 StringAttr name = paramAttr.
getName();
4132 auto checkUnitAttrType = [&]() -> LogicalResult {
4133 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4134 return op->
emitError() << name <<
" should be a unit attribute";
4137 auto checkTypeAttrType = [&]() -> LogicalResult {
4138 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4139 return op->
emitError() << name <<
" should be a type attribute";
4142 auto checkIntegerAttrType = [&]() -> LogicalResult {
4143 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4144 return op->
emitError() << name <<
" should be an integer attribute";
4147 auto checkPointerType = [&]() -> LogicalResult {
4148 if (!llvm::isa<LLVMPointerType>(paramType))
4150 << name <<
" attribute attached to non-pointer LLVM type";
4153 auto checkIntegerType = [&]() -> LogicalResult {
4154 if (!llvm::isa<IntegerType>(paramType))
4156 << name <<
" attribute attached to non-integer LLVM type";
4159 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4160 if (failed(checkPointerType()))
4167 if (name == LLVMDialect::getNoAliasAttrName() ||
4168 name == LLVMDialect::getReadonlyAttrName() ||
4169 name == LLVMDialect::getReadnoneAttrName() ||
4170 name == LLVMDialect::getWriteOnlyAttrName() ||
4171 name == LLVMDialect::getNestAttrName() ||
4172 name == LLVMDialect::getNoCaptureAttrName() ||
4173 name == LLVMDialect::getNoFreeAttrName() ||
4174 name == LLVMDialect::getNonNullAttrName()) {
4175 if (failed(checkUnitAttrType()))
4177 if (verifyValueType && failed(checkPointerType()))
4183 if (name == LLVMDialect::getStructRetAttrName() ||
4184 name == LLVMDialect::getByValAttrName() ||
4185 name == LLVMDialect::getByRefAttrName() ||
4186 name == LLVMDialect::getElementTypeAttrName() ||
4187 name == LLVMDialect::getInAllocaAttrName() ||
4188 name == LLVMDialect::getPreallocatedAttrName()) {
4189 if (failed(checkTypeAttrType()))
4191 if (verifyValueType && failed(checkPointerTypeMatches()))
4197 if (name == LLVMDialect::getSExtAttrName() ||
4198 name == LLVMDialect::getZExtAttrName()) {
4199 if (failed(checkUnitAttrType()))
4201 if (verifyValueType && failed(checkIntegerType()))
4207 if (name == LLVMDialect::getAlignAttrName() ||
4208 name == LLVMDialect::getDereferenceableAttrName() ||
4209 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4210 if (failed(checkIntegerAttrType()))
4212 if (verifyValueType && failed(checkPointerType()))
4218 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4219 if (failed(checkIntegerAttrType()))
4225 if (name == LLVMDialect::getNoUndefAttrName() ||
4226 name == LLVMDialect::getInRegAttrName() ||
4227 name == LLVMDialect::getReturnedAttrName())
4228 return checkUnitAttrType();
4234 LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4238 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4241 Type argType = funcOp.getArgumentTypes()[argIdx];
4243 return verifyParameterAttribute(op, argType, argAttr);
4246 LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4250 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4253 Type resType = funcOp.getResultTypes()[resIdx];
4257 if (llvm::isa<LLVMVoidType>(resType))
4258 return op->
emitError() <<
"cannot attach result attributes to functions "
4259 "with a void return";
4263 auto name = resAttr.
getName();
4264 if (name == LLVMDialect::getAllocAlignAttrName() ||
4265 name == LLVMDialect::getAllocatedPointerAttrName() ||
4266 name == LLVMDialect::getByValAttrName() ||
4267 name == LLVMDialect::getByRefAttrName() ||
4268 name == LLVMDialect::getInAllocaAttrName() ||
4269 name == LLVMDialect::getNestAttrName() ||
4270 name == LLVMDialect::getNoCaptureAttrName() ||
4271 name == LLVMDialect::getNoFreeAttrName() ||
4272 name == LLVMDialect::getPreallocatedAttrName() ||
4273 name == LLVMDialect::getReadnoneAttrName() ||
4274 name == LLVMDialect::getReadonlyAttrName() ||
4275 name == LLVMDialect::getReturnedAttrName() ||
4276 name == LLVMDialect::getStackAlignmentAttrName() ||
4277 name == LLVMDialect::getStructRetAttrName() ||
4278 name == LLVMDialect::getWriteOnlyAttrName())
4279 return op->
emitError() << name <<
" is not a valid result attribute";
4280 return verifyParameterAttribute(op, resType, resAttr);
4288 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4289 if (isa<LLVM::LLVMPointerType>(type))
4290 return builder.
create<LLVM::AddressOfOp>(loc, type, symbol);
4291 if (isa<LLVM::UndefAttr>(value))
4292 return builder.
create<LLVM::UndefOp>(loc, type);
4293 if (isa<LLVM::PoisonAttr>(value))
4294 return builder.
create<LLVM::PoisonOp>(loc, type);
4295 if (isa<LLVM::ZeroAttr>(value))
4296 return builder.
create<LLVM::ZeroOp>(loc, type);
4298 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4306 StringRef name, StringRef value,
4307 LLVM::Linkage linkage) {
4310 "expected builder to point to a block constrained in an op");
4313 assert(module &&
"builder points to an op outside of a module");
4319 auto global = moduleBuilder.
create<LLVM::GlobalOp>(
4320 loc, type,
true, linkage, name,
4326 builder.
create<LLVM::AddressOfOp>(loc, ptrType, global.getSymNameAttr());
4327 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.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
This class provides an abstraction for a range of TypeRange.
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
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.