29 #include "llvm/ADT/SCCIterator.h"
30 #include "llvm/ADT/TypeSwitch.h"
31 #include "llvm/AsmParser/Parser.h"
32 #include "llvm/Bitcode/BitcodeReader.h"
33 #include "llvm/Bitcode/BitcodeWriter.h"
34 #include "llvm/IR/Attributes.h"
35 #include "llvm/IR/Function.h"
36 #include "llvm/IR/Type.h"
37 #include "llvm/Support/Error.h"
38 #include "llvm/Support/Mutex.h"
39 #include "llvm/Support/SourceMgr.h"
46 using mlir::LLVM::cconv::getMaxEnumValForCConv;
47 using mlir::LLVM::linkage::getMaxEnumValForLinkage;
48 using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
50 #include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
61 if (attr.
getName() ==
"fastmathFlags") {
63 FastmathFlagsAttr::get(attr.getValue().getContext(), {});
81 << name <<
"' does not reference a valid LLVM function";
82 if (func.isExternal())
83 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
109 template <
typename Ty>
110 struct EnumTraits {};
112 #define REGISTER_ENUM_TYPE(Ty) \
114 struct EnumTraits<Ty> { \
115 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
116 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
129 template <
typename EnumTy,
typename RetTy = EnumTy>
132 EnumTy defaultValue) {
134 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
139 return static_cast<RetTy
>(defaultValue);
140 return static_cast<RetTy
>(index);
152 if (!operands.empty()) {
155 llvm::interleaveComma(operandTypes, p);
164 std::optional<ArrayAttr> opBundleTags) {
165 if (opBundleOperands.empty())
167 assert(opBundleTags &&
"expect operand bundle tags");
170 llvm::interleaveComma(
171 llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
173 auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
191 return p.
emitError(currentParserLoc,
"expect operand bundle tag");
202 opBundleOperands.push_back(std::move(operands));
203 opBundleOperandTypes.push_back(std::move(types));
213 ArrayAttr &opBundleTags) {
221 auto bundleParser = [&] {
241 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
242 <<
", " << getOperand(1);
244 p <<
" : " << getLhs().getType();
248 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
249 <<
", " << getOperand(1);
251 p <<
" : " << getLhs().getType();
258 template <
typename CmpPredicateType>
260 StringAttr predicateAttr;
263 SMLoc predicateLoc, trailingTypeLoc;
275 int64_t predicateValue = 0;
276 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
277 std::optional<ICmpPredicate> predicate =
278 symbolizeICmpPredicate(predicateAttr.getValue());
281 <<
"'" << predicateAttr.getValue()
282 <<
"' is an incorrect value of the 'predicate' attribute";
283 predicateValue =
static_cast<int64_t
>(*predicate);
285 std::optional<FCmpPredicate> predicate =
286 symbolizeFCmpPredicate(predicateAttr.getValue());
289 <<
"'" << predicateAttr.getValue()
290 <<
"' is an incorrect value of the 'predicate' attribute";
291 predicateValue =
static_cast<int64_t
>(*predicate);
301 "expected LLVM dialect-compatible type");
307 return parseCmpOp<ICmpPredicate>(parser, result);
311 return parseCmpOp<FCmpPredicate>(parser, result);
317 ShapedType shapedType = dyn_cast<ShapedType>(type);
324 if (getPredicate() != ICmpPredicate::eq &&
325 getPredicate() != ICmpPredicate::ne)
329 if (getLhs() == getRhs())
331 getPredicate() == ICmpPredicate::eq);
334 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
336 getPredicate() == ICmpPredicate::ne);
339 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
340 Value lhs = getLhs();
341 Value rhs = getRhs();
342 getLhsMutable().assign(rhs);
343 getRhsMutable().assign(lhs);
361 p <<
' ' << getArraySize() <<
" x " << getElemType();
362 if (getAlignment() && *getAlignment() != 0)
364 {kElemTypeAttrName, getInallocaAttrName()});
368 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
369 p <<
" : " << funcTy;
377 SMLoc trailingTypeLoc;
389 std::optional<NamedAttribute> alignmentAttr =
391 if (alignmentAttr.has_value()) {
392 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
395 "expected integer alignment");
396 if (alignmentInt.getValue().isZero())
401 auto funcType = llvm::dyn_cast<FunctionType>(type);
402 if (!funcType || funcType.getNumInputs() != 1 ||
403 funcType.getNumResults() != 1)
406 "expected trailing function type with one argument and one result");
411 Type resultType = funcType.getResult(0);
412 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
415 result.
addTypes({funcType.getResult(0)});
421 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
422 targetExtType && !targetExtType.supportsMemOps())
424 <<
"this target extension type cannot be used in alloca";
434 assert(index == 0 &&
"invalid successor index");
443 assert(index < getNumSuccessors() &&
"invalid successor index");
445 : getFalseDestOperandsMutable());
451 std::optional<std::pair<uint32_t, uint32_t>> weights) {
456 static_cast<int32_t
>(weights->second)});
458 build(builder, result, condition, trueOperands, falseOperands, weightsAttr,
459 {}, trueDest, falseDest);
473 if (!branchWeights.empty())
476 build(builder, result, value, defaultOperands, caseOperands, caseValues,
477 weightsAttr, defaultDestination, caseDestinations);
486 if (!caseValues.empty()) {
488 static_cast<int64_t
>(caseValues.size()), value.
getType());
492 build(builder, result, value, defaultDestination, defaultOperands,
493 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
502 if (!caseValues.empty()) {
504 static_cast<int64_t
>(caseValues.size()), value.
getType());
508 build(builder, result, value, defaultDestination, defaultOperands,
509 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
525 auto parseCase = [&]() {
529 values.push_back(APInt(bitWidth, value,
true));
542 caseDestinations.push_back(destination);
543 caseOperands.emplace_back(operands);
544 caseOperandTypes.emplace_back(operandTypes);
550 ShapedType caseValueType =
570 llvm::zip(caseValues, caseDestinations),
586 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
588 getCaseValues()->size() !=
589 static_cast<int64_t
>(getCaseDestinations().size())))
590 return emitOpError(
"expects number of case values to match number of "
591 "case destinations");
592 if (getBranchWeights() && getBranchWeights()->size() != getNumSuccessors())
593 return emitError(
"expects number of branch weights to match number of "
595 << getBranchWeights()->size() <<
" vs " << getNumSuccessors();
596 if (getCaseValues() &&
598 return emitError(
"expects case value type to match condition value type");
603 assert(index < getNumSuccessors() &&
"invalid successor index");
605 : getCaseOperandsMutable(index - 1));
612 constexpr int32_t GEPOp::kDynamicIndex;
616 getDynamicIndices());
621 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
622 return vectorType.getElementType();
634 for (
const GEPArg &iter : indices) {
639 bool requiresConst = !rawConstantIndices.empty() &&
640 isa_and_nonnull<LLVMStructType>(currType);
641 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
645 rawConstantIndices.push_back(intC.getSExtValue());
647 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
648 dynamicIndices.push_back(val);
651 rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
656 if (rawConstantIndices.size() == 1 || !currType)
660 .Case<VectorType, LLVMArrayType>([](
auto containerType) {
661 return containerType.getElementType();
663 .Case([&](LLVMStructType structType) ->
Type {
664 int64_t memberIndex = rawConstantIndices.back();
665 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
666 structType.getBody().size())
667 return structType.getBody()[memberIndex];
670 .Default(
Type(
nullptr));
697 build(builder, result, resultType, elementType, basePtr,
707 auto idxParser = [&]() -> ParseResult {
712 if (failed(parsedInteger.
value()))
718 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
732 llvm::interleaveComma(
735 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
738 printer << cast<IntegerAttr>(cst).getInt();
748 if (indexPos >= indices.
size())
753 .Case<LLVMStructType>([&](LLVMStructType structType) -> LogicalResult {
754 auto attr = dyn_cast<IntegerAttr>(indices[indexPos]);
756 return emitOpError() <<
"expected index " << indexPos
757 <<
" indexing a struct to be constant";
759 int32_t gepIndex = attr.getInt();
762 static_cast<size_t>(gepIndex) >= elementTypes.size())
763 return emitOpError() <<
"index " << indexPos
764 <<
" indexing a struct is out of bounds";
769 indices, emitOpError);
771 .Case<VectorType, LLVMArrayType>(
772 [&](
auto containerType) -> LogicalResult {
774 indexPos + 1, indices, emitOpError);
776 .Default([&](
auto otherType) -> LogicalResult {
778 <<
"type " << otherType <<
" cannot be indexed (index #"
791 if (
static_cast<size_t>(
792 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
793 getDynamicIndices().size())
794 return emitOpError(
"expected as many dynamic indices as specified in '")
795 << getRawConstantIndicesAttrName().getValue() <<
"'";
798 [&] {
return emitOpError(); });
805 void LoadOp::getEffects(
814 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
815 getOrdering() != AtomicOrdering::unordered)) {
826 if (!isa<IntegerType, LLVMPointerType>(type))
831 if (bitWidth.isScalable())
834 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
838 template <
typename OpTy>
841 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
844 return memOp.emitOpError(
"unsupported type ")
845 << valueType <<
" for atomic access";
846 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
847 return memOp.emitOpError(
"unsupported ordering '")
848 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
849 if (!memOp.getAlignment())
850 return memOp.emitOpError(
"expected alignment for atomic access");
853 if (memOp.getSyncscope())
854 return memOp.emitOpError(
855 "expected syncscope to be null for non-atomic access");
860 Type valueType = getResult().getType();
862 {AtomicOrdering::release, AtomicOrdering::acq_rel});
866 Value addr,
unsigned alignment,
bool isVolatile,
867 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
868 AtomicOrdering ordering, StringRef syncscope) {
869 build(builder, state, type, addr,
871 isNonTemporal, isInvariant, isInvariantGroup, ordering,
872 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
883 void StoreOp::getEffects(
892 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
893 getOrdering() != AtomicOrdering::unordered)) {
900 Type valueType = getValue().getType();
902 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
906 Value addr,
unsigned alignment,
bool isVolatile,
907 bool isNonTemporal,
bool isInvariantGroup,
908 AtomicOrdering ordering, StringRef syncscope) {
909 build(builder, state, value, addr,
911 isNonTemporal, isInvariantGroup, ordering,
912 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
914 nullptr,
nullptr,
nullptr);
924 Type resultType = calleeType.getReturnType();
925 if (!isa<LLVM::LLVMVoidType>(resultType))
926 results.push_back(resultType);
932 return calleeType.isVarArg() ?
TypeAttr::get(calleeType) :
nullptr;
942 resultType = results.front();
949 build(builder, state, results, builder.
getStringAttr(callee), args);
959 assert(callee &&
"expected non-null callee in direct call builder");
960 build(builder, state, results,
961 nullptr, callee, args,
nullptr,
965 nullptr,
nullptr,
nullptr,
975 LLVMFunctionType calleeType, StringRef callee,
977 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
981 LLVMFunctionType calleeType, StringAttr callee,
999 nullptr,
nullptr,
nullptr,
1005 LLVMFunctionType calleeType,
ValueRange args) {
1010 nullptr,
nullptr,
nullptr,
1011 nullptr,
nullptr,
nullptr,
1022 auto calleeType = func.getFunctionType();
1026 nullptr,
nullptr,
nullptr,
1027 nullptr,
nullptr,
nullptr,
1041 return getOperand(0);
1047 auto symRef = cast<SymbolRefAttr>(callee);
1048 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1051 return setOperand(0, cast<Value>(callee));
1055 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1060 getCalleeOperands().size());
1067 if (callee.isExternal())
1069 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1073 auto hasSubprogram = [](
Operation *op) {
1078 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1080 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1082 return callOp.emitError()
1083 <<
"inlinable function call in a function with a DISubprogram "
1084 "location must have a debug location";
1090 template <
typename OpTy>
1092 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1097 if (!varCalleeType->isVarArg())
1098 return callOp.emitOpError(
1099 "expected var_callee_type to be a variadic function type");
1103 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1104 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1105 << callOp.getArgOperands().size() <<
" parameters";
1108 for (
auto [paramType, operand] :
1109 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1110 if (paramType != operand.getType())
1111 return callOp.emitOpError()
1112 <<
"var_callee_type parameter type mismatch: " << paramType
1113 <<
" != " << operand.getType();
1116 if (!callOp.getNumResults()) {
1117 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1118 return callOp.emitOpError(
"expected var_callee_type to return void");
1120 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1121 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1122 << varCalleeType->getReturnType()
1123 <<
" != " << callOp.getResult().getType();
1128 template <
typename OpType>
1131 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1133 auto isStringAttr = [](
Attribute tagAttr) {
1134 return isa<StringAttr>(tagAttr);
1136 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1137 return op.emitError(
"operand bundle tag must be a StringAttr");
1139 size_t numOpBundles = opBundleOperands.size();
1140 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1141 if (numOpBundles != numOpBundleTags)
1142 return op.emitError(
"expected ")
1143 << numOpBundles <<
" operand bundle tags, but actually got "
1159 bool isIndirect =
false;
1165 if (!getNumOperands())
1167 "must have either a `callee` attribute or at least an operand");
1168 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1170 return emitOpError(
"indirect call expects a pointer as callee: ")
1171 << getOperand(0).getType();
1178 return emitOpError()
1180 <<
"' does not reference a symbol in the current scope";
1181 auto fn = dyn_cast<LLVMFuncOp>(callee);
1183 return emitOpError() <<
"'" << calleeName.
getValue()
1184 <<
"' does not reference a valid LLVM function";
1188 fnType = fn.getFunctionType();
1191 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1193 return emitOpError(
"callee does not have a functional type: ") << fnType;
1195 if (funcType.isVarArg() && !getVarCalleeType())
1196 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1200 if (!funcType.isVarArg() &&
1201 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1202 return emitOpError() <<
"incorrect number of operands ("
1203 << (getCalleeOperands().size() - isIndirect)
1204 <<
") for callee (expecting: "
1205 << funcType.getNumParams() <<
")";
1207 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1208 return emitOpError() <<
"incorrect number of operands ("
1209 << (getCalleeOperands().size() - isIndirect)
1210 <<
") for varargs callee (expecting at least: "
1211 << funcType.getNumParams() <<
")";
1213 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1214 if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1215 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1216 << getOperand(i + isIndirect).getType()
1217 <<
" != " << funcType.getParamType(i);
1219 if (getNumResults() == 0 &&
1220 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1221 return emitOpError() <<
"expected function call to produce a value";
1223 if (getNumResults() != 0 &&
1224 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1225 return emitOpError()
1226 <<
"calling function with void result must not produce values";
1228 if (getNumResults() > 1)
1229 return emitOpError()
1230 <<
"expected LLVM function call to produce 0 or 1 result";
1232 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1233 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1234 <<
" != " << funcType.getReturnType();
1240 auto callee = getCallee();
1241 bool isDirect = callee.has_value();
1246 if (getCConv() != LLVM::CConv::C)
1247 p << stringifyCConv(getCConv()) <<
' ';
1250 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1259 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1260 p <<
'(' << args <<
')';
1263 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1264 p <<
" vararg(" << *varCalleeType <<
")";
1266 if (!getOpBundleOperands().empty()) {
1269 getOpBundleOperands().getTypes(), getOpBundleTags());
1273 {getCalleeAttrName(), getTailCallKindAttrName(),
1274 getVarCalleeTypeAttrName(), getCConvAttrName(),
1275 getOperandSegmentSizesAttrName(),
1276 getOpBundleSizesAttrName(),
1277 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1278 getResAttrsAttrName()});
1282 p << getOperand(0).getType() <<
", ";
1286 p, args.getTypes(), getArgAttrsAttr(),
1287 false, getResultTypes(), getResAttrsAttr());
1302 types.emplace_back();
1307 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1312 resTypes, resultAttrs)) {
1314 return parser.
emitError(trailingTypesLoc,
1315 "expected direct call to have 1 trailing types");
1316 return parser.
emitError(trailingTypesLoc,
1317 "expected trailing function type");
1320 if (resTypes.size() > 1)
1321 return parser.
emitError(trailingTypesLoc,
1322 "expected function with 0 or 1 result");
1323 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1324 return parser.
emitError(trailingTypesLoc,
1325 "expected a non-void result type");
1331 llvm::append_range(types, argTypes);
1335 if (resTypes.size() != 0)
1349 if (failed(*parseResult))
1350 return *parseResult;
1351 operands.push_back(funcPtrOperand);
1360 StringAttr opBundleSizesAttrName) {
1361 unsigned opBundleIndex = 0;
1362 for (
const auto &[operands, types] :
1363 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1364 if (operands.size() != types.size())
1365 return parser.
emitError(loc,
"expected ")
1367 <<
" types for operand bundle operands for operand bundle #"
1368 << opBundleIndex <<
", but actually got " << types.size();
1374 opBundleSizes.reserve(opBundleOperands.size());
1375 for (
const auto &operands : opBundleOperands)
1376 opBundleSizes.push_back(operands.size());
1379 opBundleSizesAttrName,
1391 SymbolRefAttr funcAttr;
1392 TypeAttr varCalleeType;
1396 ArrayAttr opBundleTags;
1400 getCConvAttrName(result.
name),
1402 parser, result, LLVM::CConv::C)));
1405 getTailCallKindAttrName(result.
name),
1407 parseOptionalLLVMKeyword<TailCallKind>(
1413 bool isDirect = operands.empty();
1426 StringAttr varCalleeTypeAttrName =
1427 CallOp::getVarCalleeTypeAttrName(result.
name);
1439 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1440 result && failed(*result))
1442 if (opBundleTags && !opBundleTags.empty())
1443 result.
addAttribute(CallOp::getOpBundleTagsAttrName(result.
name).getValue(),
1453 argAttrs, resultAttrs))
1456 parser.
getBuilder(), result, argAttrs, resultAttrs,
1457 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
1459 opBundleOperandTypes,
1460 getOpBundleSizesAttrName(result.
name)))
1463 int32_t numOpBundleOperands = 0;
1464 for (
const auto &operands : opBundleOperands)
1465 numOpBundleOperands += operands.size();
1468 CallOp::getOperandSegmentSizeAttr(),
1470 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1474 LLVMFunctionType CallOp::getCalleeFunctionType() {
1475 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1476 return *varCalleeType;
1487 auto calleeType = func.getFunctionType();
1490 nullptr,
nullptr, normalOps, unwindOps,
1491 nullptr,
nullptr, {}, {}, normal, unwind);
1498 build(builder, state, tys,
1499 nullptr, callee, ops,
nullptr,
1500 nullptr, normalOps, unwindOps,
nullptr,
nullptr, {}, {},
1510 nullptr,
nullptr, normalOps, unwindOps,
1511 nullptr,
nullptr, {}, {}, normal, unwind);
1515 assert(index < getNumSuccessors() &&
"invalid successor index");
1517 : getUnwindDestOperandsMutable());
1525 return getOperand(0);
1531 auto symRef = cast<SymbolRefAttr>(callee);
1532 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1535 return setOperand(0, cast<Value>(callee));
1539 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1544 getCalleeOperands().size());
1551 Block *unwindDest = getUnwindDest();
1552 if (unwindDest->
empty())
1553 return emitError(
"must have at least one operation in unwind destination");
1556 if (!isa<LandingpadOp>(unwindDest->
front()))
1557 return emitError(
"first operation in unwind destination should be a "
1558 "llvm.landingpad operation");
1567 auto callee = getCallee();
1568 bool isDirect = callee.has_value();
1573 if (getCConv() != LLVM::CConv::C)
1574 p << stringifyCConv(getCConv()) <<
' ';
1582 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1589 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1590 p <<
" vararg(" << *varCalleeType <<
")";
1592 if (!getOpBundleOperands().empty()) {
1595 getOpBundleOperands().getTypes(), getOpBundleTags());
1599 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1600 getCConvAttrName(), getVarCalleeTypeAttrName(),
1601 getOpBundleSizesAttrName(),
1602 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1603 getResAttrsAttrName()});
1607 p << getOperand(0).getType() <<
", ";
1609 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1611 false, getResultTypes(), getResAttrsAttr());
1624 SymbolRefAttr funcAttr;
1625 TypeAttr varCalleeType;
1628 ArrayAttr opBundleTags;
1629 Block *normalDest, *unwindDest;
1635 getCConvAttrName(result.
name),
1637 parser, result, LLVM::CConv::C)));
1642 bool isDirect = operands.empty();
1658 StringAttr varCalleeTypeAttrName =
1659 InvokeOp::getVarCalleeTypeAttrName(result.
name);
1671 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1672 result && failed(*result))
1674 if (opBundleTags && !opBundleTags.empty())
1676 InvokeOp::getOpBundleTagsAttrName(result.
name).getValue(),
1686 argAttrs, resultAttrs))
1689 parser.
getBuilder(), result, argAttrs, resultAttrs,
1690 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
1693 opBundleOperandTypes,
1694 getOpBundleSizesAttrName(result.
name)))
1701 int32_t numOpBundleOperands = 0;
1702 for (
const auto &operands : opBundleOperands)
1703 numOpBundleOperands += operands.size();
1706 InvokeOp::getOperandSegmentSizeAttr(),
1708 static_cast<int32_t>(normalOperands.size()),
1709 static_cast<int32_t>(unwindOperands.size()),
1710 numOpBundleOperands}));
1714 LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1715 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1716 return *varCalleeType;
1726 if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1727 if (!func.getPersonality())
1729 "llvm.landingpad needs to be in a function with a personality");
1735 if (!getCleanup() && getOperands().empty())
1736 return emitError(
"landingpad instruction expects at least one clause or "
1737 "cleanup attribute");
1739 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1740 value = getOperand(idx);
1741 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1748 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1751 <<
"global addresses expected as operand to "
1752 "bitcast used in clauses for landingpad";
1760 << idx <<
" is not a known constant - null, addressof, bitcast";
1767 p << (getCleanup() ?
" cleanup " :
" ");
1770 for (
auto value : getOperands()) {
1773 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1774 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1821 Type llvmType = containerType;
1823 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1831 for (int64_t idx : position) {
1832 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1833 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1834 emitError(
"position out of bounds: ") << idx;
1837 llvmType = arrayType.getElementType();
1838 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1840 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1841 emitError(
"position out of bounds: ") << idx;
1844 llvmType = structType.getBody()[idx];
1846 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1857 for (int64_t idx : position) {
1858 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1859 llvmType = structType.getBody()[idx];
1861 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1866 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1867 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
1869 newPos.append(getPosition().begin(), getPosition().end());
1870 setPosition(newPos);
1871 getContainerMutable().set(extractValueOp.getContainer());
1879 if (isa<SplatElementsAttr>(constval))
1881 if (getPosition().size() == 1)
1886 auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1888 while (insertValueOp) {
1889 if (getPosition() == insertValueOp.getPosition())
1890 return insertValueOp.getValue();
1892 std::min(getPosition().size(), insertValueOp.getPosition().size());
1903 if (getPosition().take_front(
min) ==
1904 insertValueOp.getPosition().take_front(
min))
1910 getContainerMutable().assign(insertValueOp.getContainer());
1911 result = getResult();
1912 insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1918 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1924 if (getRes().
getType() != valueType)
1925 return emitOpError() <<
"Type mismatch: extracting from "
1926 << getContainer().getType() <<
" should produce "
1927 << valueType <<
" but this op returns "
1928 << getRes().getType();
1934 build(builder, state,
1949 [&](StringRef msg) {
1953 return success(!!valueType);
1963 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1969 if (getValue().
getType() != valueType)
1970 return emitOpError() <<
"Type mismatch: cannot insert "
1971 << getValue().getType() <<
" into "
1972 << getContainer().getType();
1982 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
1986 Type expectedType = parent.getFunctionType().getReturnType();
1987 if (llvm::isa<LLVMVoidType>(expectedType)) {
1991 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1995 if (llvm::isa<LLVMVoidType>(expectedType))
1998 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2001 if (expectedType != getArg().
getType()) {
2003 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2017 assert(module &&
"unexpected operation outside of a module");
2022 return dyn_cast_or_null<GlobalOp>(
2027 return dyn_cast_or_null<LLVMFuncOp>(
2032 return dyn_cast_or_null<AliasOp>(
2041 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2042 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2043 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2045 if (!global && !
function && !alias)
2046 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2047 "'llvm.mlir.alias' or 'llvm.func'");
2049 LLVMPointerType type =
getType();
2050 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2051 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2052 return emitOpError(
"pointer address space must match address space of the "
2053 "referenced global or alias");
2060 return getGlobalNameAttr();
2081 getFunctionNameAttr());
2082 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2083 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2085 if (!
function && !alias)
2087 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2090 if (alias.getInitializer()
2091 .walk([&](AddressOfOp addrOp) {
2092 if (addrOp.getGlobal(symbolTable))
2093 return WalkResult::interrupt();
2094 return WalkResult::advance();
2097 return emitOpError(
"must reference an alias to a function");
2100 if ((
function &&
function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2101 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2103 "target function with 'extern_weak' linkage not allowed");
2119 StringRef symName) {
2126 LogicalResult ComdatOp::verifyRegions() {
2127 Region &body = getBody();
2129 if (!isa<ComdatSelectorOp>(op))
2130 return op.emitError(
2131 "only comdat selector symbols can appear in a comdat region");
2141 bool isConstant, Linkage linkage, StringRef name,
2142 Attribute value, uint64_t alignment,
unsigned addrSpace,
2143 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2177 if (!dbgExprs.empty())
2185 p <<
' ' << stringifyLinkage(getLinkage()) <<
' ';
2186 StringRef visibility = stringifyVisibility(getVisibility_());
2187 if (!visibility.empty())
2188 p << visibility <<
' ';
2189 if (getThreadLocal_())
2190 p <<
"thread_local ";
2191 if (
auto unnamedAddr = getUnnamedAddr()) {
2192 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2200 if (
auto value = getValueOrNull())
2203 if (
auto comdat = getComdat())
2204 p <<
" comdat(" << *comdat <<
')';
2210 {SymbolTable::getSymbolAttrName(),
2211 getGlobalTypeAttrName(), getConstantAttrName(),
2212 getValueAttrName(), getLinkageAttrName(),
2213 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2214 getVisibility_AttrName(), getComdatAttrName(),
2215 getUnnamedAddrAttrName()});
2218 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2222 Region &initializer = getInitializerRegion();
2223 if (!initializer.
empty()) {
2230 std::optional<SymbolRefAttr> attr) {
2235 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2236 return op->
emitError() <<
"expected comdat symbol";
2243 BlockTagOp badBlockTagOp;
2245 .
walk([&](BlockTagOp blockTagOp) {
2246 if (blockTags.contains(blockTagOp.getTag())) {
2247 badBlockTagOp = blockTagOp;
2248 return WalkResult::interrupt();
2250 blockTags.insert(blockTagOp.getTag());
2253 .wasInterrupted()) {
2254 badBlockTagOp.emitError()
2255 <<
"duplicate block tag '" << badBlockTagOp.getTag().getId()
2256 <<
"' in the same function: ";
2265 template <
typename OpType>
2272 ctx, parseOptionalLLVMKeyword<Linkage>(
2273 parser, result, LLVM::Linkage::External)));
2278 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2279 parser, result, LLVM::Visibility::Default)));
2284 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2304 if (parseCommonGlobalAndAlias<GlobalOp>(parser, result).failed())
2326 SymbolRefAttr comdat;
2339 if (types.size() > 1)
2343 if (types.empty()) {
2344 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2347 strAttr.getValue().size());
2348 types.push_back(arrayType);
2351 "type can only be omitted for string globals");
2357 if (parseResult.
has_value() && failed(*parseResult))
2367 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2368 return intValue.getValue().isZero();
2369 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2370 return fpValue.getValue().isZero();
2371 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2373 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2375 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2382 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2383 LLVMMetadataType, LLVMLabelType>(
getType())
2384 : llvm::isa<PointerElementTypeInterface>(
getType());
2387 "expects type to be a valid element type for an LLVM global");
2389 return emitOpError(
"must appear at the module level");
2391 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2392 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2393 IntegerType elementType =
2394 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2395 if (!elementType || elementType.getWidth() != 8 ||
2396 type.getNumElements() != strAttr.getValue().size())
2398 "requires an i8 array type of the length equal to that of the string "
2402 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2403 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2404 return emitOpError()
2405 <<
"this target extension type cannot be used in a global";
2408 return emitOpError() <<
"global with target extension type can only be "
2409 "initialized with zero-initializer";
2412 if (getLinkage() == Linkage::Common) {
2413 if (
Attribute value = getValueOrNull()) {
2415 return emitOpError()
2416 <<
"expected zero value for '"
2417 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2422 if (getLinkage() == Linkage::Appending) {
2423 if (!llvm::isa<LLVMArrayType>(
getType())) {
2424 return emitOpError() <<
"expected array type for '"
2425 << stringifyLinkage(Linkage::Appending)
2433 std::optional<uint64_t> alignAttr = getAlignment();
2434 if (alignAttr.has_value()) {
2435 uint64_t value = alignAttr.value();
2436 if (!llvm::isPowerOf2_64(value))
2437 return emitError() <<
"alignment attribute is not a power of 2";
2443 LogicalResult GlobalOp::verifyRegions() {
2444 if (
Block *b = getInitializerBlock()) {
2445 ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2446 if (ret.operand_type_begin() == ret.operand_type_end())
2447 return emitOpError(
"initializer region cannot return void");
2448 if (*ret.operand_type_begin() !=
getType())
2449 return emitOpError(
"initializer region type ")
2450 << *ret.operand_type_begin() <<
" does not match global type "
2454 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2455 if (!iface || !iface.hasNoEffect())
2456 return op.emitError()
2457 <<
"ops with side effects not allowed in global initializers";
2460 if (getValueOrNull())
2461 return emitOpError(
"cannot have both initializer value and region");
2476 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2479 return op->
emitError(
"data element must be symbol or #llvm.zero");
2496 if (getCtors().size() == getPriorities().size() &&
2497 getCtors().size() == getData().size())
2500 "ctors, priorities, and data must have the same number of elements");
2521 if (getDtors().size() == getPriorities().size() &&
2522 getDtors().size() == getData().size())
2525 "dtors, priorities, and data must have the same number of elements");
2533 Linkage linkage, StringRef name,
bool dsoLocal,
2553 p <<
' ' << stringifyLinkage(getLinkage()) <<
' ';
2554 StringRef visibility = stringifyVisibility(getVisibility_());
2555 if (!visibility.empty())
2556 p << visibility <<
' ';
2558 if (std::optional<mlir::LLVM::UnnamedAddr> unnamedAddr = getUnnamedAddr()) {
2559 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2564 if (getThreadLocal_())
2565 p <<
"thread_local ";
2569 {SymbolTable::getSymbolAttrName(),
2570 getAliasTypeAttrName(), getLinkageAttrName(),
2571 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2572 getVisibility_AttrName(), getUnnamedAddrAttrName()});
2575 p <<
" : " <<
getType() <<
' ';
2588 if (parseCommonGlobalAndAlias<AliasOp>(parser, result).failed())
2601 if (types.size() > 1)
2615 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2616 LLVMMetadataType, LLVMLabelType>(
getType())
2617 : llvm::isa<PointerElementTypeInterface>(
getType());
2620 "expects type to be a valid element type for an LLVM global alias");
2623 switch (getLinkage()) {
2624 case Linkage::External:
2625 case Linkage::Internal:
2626 case Linkage::Private:
2628 case Linkage::WeakODR:
2629 case Linkage::Linkonce:
2630 case Linkage::LinkonceODR:
2631 case Linkage::AvailableExternally:
2634 return emitOpError()
2635 <<
"'" << stringifyLinkage(getLinkage())
2636 <<
"' linkage not supported in aliases, available options: private, "
2637 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2638 "available_externally";
2644 LogicalResult AliasOp::verifyRegions() {
2645 Block &b = getInitializerBlock();
2647 if (ret.getNumOperands() == 0 ||
2648 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2649 return emitOpError(
"initializer region must always return a pointer");
2652 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2653 if (!iface || !iface.hasNoEffect())
2654 return op.emitError()
2655 <<
"ops with side effects are not allowed in alias initializers";
2661 unsigned AliasOp::getAddrSpace() {
2662 Block &initializer = getInitializerBlock();
2664 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2665 return ptrTy.getAddressSpace();
2675 auto containerType = v1.
getType();
2679 build(builder, state, vType, v1, v2, mask);
2680 state.addAttributes(attrs);
2693 "expected an LLVM compatible vector type");
2706 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2707 return emitOpError(
"expected a splat operation for scalable vectors");
2717 assert(empty() &&
"function already has an entry block");
2722 LLVMFunctionType type = getFunctionType();
2723 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2724 entry->
addArgument(type.getParamType(i), getLoc());
2729 StringRef name,
Type type, LLVM::Linkage linkage,
2730 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2733 std::optional<uint64_t> functionEntryCount) {
2749 if (functionEntryCount)
2752 if (argAttrs.empty())
2755 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2756 "expected as many argument attribute lists as arguments");
2758 builder, result, argAttrs, std::nullopt,
2759 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2770 if (outputs.size() > 1) {
2771 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2772 "one function result");
2778 for (
auto t : inputs) {
2780 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2781 "type for function arguments");
2784 llvmInputs.push_back(t);
2791 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2792 "type for function results")
2810 getLinkageAttrName(result.
name),
2812 parseOptionalLLVMKeyword<Linkage>(
2813 parser, result, LLVM::Linkage::External)));
2818 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2819 parser, result, LLVM::Visibility::Default)));
2824 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2829 getCConvAttrName(result.
name),
2831 parser, result, LLVM::CConv::C)));
2833 StringAttr nameAttr;
2843 parser,
true, entryArgs, isVariadic, resultTypes,
2848 for (
auto &arg : entryArgs)
2849 argTypes.push_back(arg.type);
2859 int64_t minRange, maxRange;
2866 getVscaleRangeAttrName(result.
name),
2873 SymbolRefAttr comdat;
2884 parser.
getBuilder(), result, entryArgs, resultAttrs,
2885 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2890 return failure(parseResult.
has_value() && failed(*parseResult));
2898 if (getLinkage() != LLVM::Linkage::External)
2899 p << stringifyLinkage(getLinkage()) <<
' ';
2900 StringRef visibility = stringifyVisibility(getVisibility_());
2901 if (!visibility.empty())
2902 p << visibility <<
' ';
2903 if (
auto unnamedAddr = getUnnamedAddr()) {
2904 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2908 if (getCConv() != LLVM::CConv::C)
2909 p << stringifyCConv(getCConv()) <<
' ';
2913 LLVMFunctionType fnType = getFunctionType();
2916 argTypes.reserve(fnType.getNumParams());
2917 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
2918 argTypes.push_back(fnType.getParamType(i));
2920 Type returnType = fnType.getReturnType();
2921 if (!llvm::isa<LLVMVoidType>(returnType))
2922 resTypes.push_back(returnType);
2925 isVarArg(), resTypes);
2928 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
2929 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
2930 << vscale->getMaxRange().getInt() <<
')';
2933 if (
auto comdat = getComdat())
2934 p <<
" comdat(" << *comdat <<
')';
2938 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
2939 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
2940 getComdatAttrName(), getUnnamedAddrAttrName(),
2941 getVscaleRangeAttrName()});
2944 Region &body = getBody();
2945 if (!body.empty()) {
2957 if (getLinkage() == LLVM::Linkage::Common)
2958 return emitOpError() <<
"functions cannot have '"
2959 << stringifyLinkage(LLVM::Linkage::Common)
2966 if (getLinkage() != LLVM::Linkage::External &&
2967 getLinkage() != LLVM::Linkage::ExternWeak)
2968 return emitOpError() <<
"external functions must have '"
2969 << stringifyLinkage(LLVM::Linkage::External)
2971 << stringifyLinkage(LLVM::Linkage::ExternWeak)
2977 if (isNoInline() && isAlwaysInline())
2978 return emitError(
"no_inline and always_inline attributes are incompatible");
2980 if (isOptimizeNone() && !isNoInline())
2981 return emitOpError(
"with optimize_none must also be no_inline");
2983 Type landingpadResultTy;
2984 StringRef diagnosticMessage;
2985 bool isLandingpadTypeConsistent =
2987 const auto checkType = [&](
Type type, StringRef errorMessage) {
2988 if (!landingpadResultTy) {
2989 landingpadResultTy = type;
2992 if (landingpadResultTy != type) {
2993 diagnosticMessage = errorMessage;
2999 .Case<LandingpadOp>([&](
auto landingpad) {
3000 constexpr StringLiteral errorMessage =
3001 "'llvm.landingpad' should have a consistent result type "
3002 "inside a function";
3003 return checkType(landingpad.getType(), errorMessage);
3005 .Case<ResumeOp>([&](
auto resume) {
3006 constexpr StringLiteral errorMessage =
3007 "'llvm.resume' should have a consistent input type inside a "
3009 return checkType(resume.getValue().getType(), errorMessage);
3012 }).wasInterrupted();
3013 if (!isLandingpadTypeConsistent) {
3014 assert(!diagnosticMessage.empty() &&
3015 "Expecting a non-empty diagnostic message");
3027 LogicalResult LLVMFuncOp::verifyRegions() {
3031 unsigned numArguments = getFunctionType().getNumParams();
3032 Block &entryBlock = front();
3033 for (
unsigned i = 0; i < numArguments; ++i) {
3036 return emitOpError(
"entry block argument #")
3037 << i <<
" is not of LLVM type";
3043 Region *LLVMFuncOp::getCallableRegion() {
3072 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3073 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3074 return emitOpError()
3075 <<
"target extension type does not support zero-initializer";
3097 if (
auto vecType = dyn_cast<VectorType>(t)) {
3098 assert(!vecType.isScalable() &&
3099 "number of elements of a scalable vector type is unknown");
3100 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3102 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3103 return arrayType.getNumElements() *
3111 if (
auto vecType = dyn_cast<VectorType>(t)) {
3112 if (vecType.isScalable())
3116 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3122 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3123 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3124 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3125 !arrayType.getElementType().isInteger(8)) {
3126 return emitOpError() <<
"expected array type of "
3127 << sAttr.getValue().size()
3128 <<
" i8 elements for the string constant";
3132 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3133 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3135 return emitOpError() <<
"expected array attribute for a struct constant";
3139 if (arrayAttr.size() != elementTypes.size()) {
3140 return emitOpError() <<
"expected array attribute of size "
3141 << elementTypes.size();
3143 for (
auto elementTy : elementTypes) {
3144 if (!isa<IntegerType, FloatType, LLVMPPCFP128Type>(elementTy)) {
3145 return emitOpError() <<
"expected struct element types to be floating "
3146 "point type or integer type";
3150 for (
size_t i = 0; i < elementTypes.size(); ++i) {
3152 if (!isa<IntegerAttr, FloatAttr>(element)) {
3153 return emitOpError()
3154 <<
"expected struct element attribute types to be floating "
3155 "point type or integer type";
3157 auto elementType = cast<TypedAttr>(element).getType();
3158 if (elementType != elementTypes[i]) {
3159 return emitOpError()
3160 <<
"struct element at index " << i <<
" is of wrong type";
3166 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
3167 return emitOpError() <<
"does not support target extension type.";
3171 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
3172 if (!llvm::isa<IntegerType>(
getType()))
3173 return emitOpError() <<
"expected integer type";
3174 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3175 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
3176 unsigned floatWidth = APFloat::getSizeInBits(sem);
3177 if (
auto floatTy = dyn_cast<FloatType>(
getType())) {
3178 if (floatTy.getWidth() != floatWidth) {
3179 return emitOpError() <<
"expected float type of width " << floatWidth;
3184 if (isa<IntegerType>(
getType()) && !
getType().isInteger(floatWidth)) {
3185 return emitOpError() <<
"expected integer type of width " << floatWidth;
3187 }
else if (isa<ElementsAttr, ArrayAttr>(getValue())) {
3191 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3192 if (!splatElementsAttr)
3193 return emitOpError()
3194 <<
"scalable vector type requires a splat attribute";
3197 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3198 return emitOpError() <<
"expected vector or array type";
3200 int64_t attrNumElements;
3201 if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue()))
3202 attrNumElements = elementsAttr.getNumElements();
3204 attrNumElements = cast<ArrayAttr>(getValue()).size();
3206 return emitOpError()
3207 <<
"type and attribute have a different number of elements: "
3210 return emitOpError()
3211 <<
"only supports integer, float, string or elements attributes";
3217 bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3219 auto typedAttr = dyn_cast<TypedAttr>(value);
3226 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3231 if (isBuildableWith(value, type))
3232 return builder.
create<LLVM::ConstantOp>(loc, cast<TypedAttr>(value));
3237 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3245 AtomicOrdering ordering, StringRef syncscope,
3246 unsigned alignment,
bool isVolatile) {
3247 build(builder, state, val.
getType(), binOp, ptr, val, ordering,
3248 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3251 nullptr,
nullptr,
nullptr);
3255 auto valType = getVal().getType();
3256 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3257 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax) {
3260 return emitOpError(
"expected LLVM IR fixed vector type");
3261 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3264 "expected LLVM IR floating point type for vector element");
3266 return emitOpError(
"expected LLVM IR floating point type");
3268 }
else if (getBinOp() == AtomicBinOp::xchg) {
3271 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3273 auto intType = llvm::dyn_cast<IntegerType>(valType);
3274 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3275 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3277 return emitOpError(
"expected LLVM IR integer type");
3280 if (
static_cast<unsigned>(getOrdering()) <
3281 static_cast<unsigned>(AtomicOrdering::monotonic))
3282 return emitOpError() <<
"expected at least '"
3283 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3296 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3301 AtomicOrdering successOrdering,
3302 AtomicOrdering failureOrdering, StringRef syncscope,
3303 unsigned alignment,
bool isWeak,
bool isVolatile) {
3305 successOrdering, failureOrdering,
3306 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3308 isVolatile,
nullptr,
3309 nullptr,
nullptr,
nullptr);
3313 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3315 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3316 auto valType = getVal().getType();
3319 return emitOpError(
"unexpected LLVM IR type");
3320 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3321 getFailureOrdering() < AtomicOrdering::monotonic)
3322 return emitOpError(
"ordering must be at least 'monotonic'");
3323 if (getFailureOrdering() == AtomicOrdering::release ||
3324 getFailureOrdering() == AtomicOrdering::acq_rel)
3325 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3334 AtomicOrdering ordering, StringRef syncscope) {
3335 build(builder, state, ordering,
3336 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3340 if (getOrdering() == AtomicOrdering::not_atomic ||
3341 getOrdering() == AtomicOrdering::unordered ||
3342 getOrdering() == AtomicOrdering::monotonic)
3343 return emitOpError(
"can be given only acquire, release, acq_rel, "
3344 "and seq_cst orderings");
3354 template <
class ExtOp>
3356 IntegerType inputType, outputType;
3359 return op.emitError(
3360 "input type is a vector but output type is an integer");
3363 return op.emitError(
"input and output vectors are of incompatible shape");
3366 inputType = cast<IntegerType>(
3367 cast<VectorType>(op.getArg().getType()).getElementType());
3368 outputType = cast<IntegerType>(
3369 cast<VectorType>(op.getResult().getType()).getElementType());
3373 inputType = cast<IntegerType>(op.getArg().getType());
3374 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3376 return op.emitError(
3377 "input type is an integer but output type is a vector");
3380 if (outputType.getWidth() <= inputType.getWidth())
3381 return op.emitError(
"integer width of the output type is smaller or "
3382 "equal to the integer width of the input type");
3390 LogicalResult
ZExtOp::verify() {
return verifyExtOp<ZExtOp>(*
this); }
3393 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3397 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3405 LogicalResult
SExtOp::verify() {
return verifyExtOp<SExtOp>(*
this); }
3412 template <
typename T>
3414 typename T::FoldAdaptor adaptor) {
3416 if (castOp.getArg().getType() == castOp.getType())
3417 return castOp.getArg();
3418 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3420 if (prev.getArg().getType() == castOp.getType())
3421 return prev.getArg();
3423 castOp.getArgMutable().set(prev.getArg());
3424 return Value{castOp};
3429 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3434 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3436 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3441 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3442 return emitOpError(
"can only cast pointers from and to pointers");
3447 auto isVector = llvm::IsaPred<VectorType>;
3451 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3452 return emitOpError(
"cannot cast pointer to vector of pointers");
3454 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3455 return emitOpError(
"cannot cast vector of pointers to pointer");
3459 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3460 return emitOpError(
"cannot cast pointers of different address spaces, "
3461 "use 'llvm.addrspacecast' instead");
3470 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3474 Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3482 adaptor.getDynamicIndices());
3486 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
3487 if (integer.getValue().isZero())
3494 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3501 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3502 gepArgs.emplace_back(val);
3504 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3510 gepArgs.emplace_back(integer.getInt());
3518 getDynamicIndicesMutable().assign(dynamicIndices);
3519 setRawConstantIndices(rawConstantIndices);
3520 return Value{*
this};
3526 Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3533 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3537 if (rhs.getValue().getZExtValue() >=
3538 getLhs().
getType().getIntOrFloatBitWidth())
3541 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3553 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3557 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3569 if (!getIntrin().starts_with(
"llvm."))
3570 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3578 build(builder, state,
TypeRange{}, intrin, args,
3579 FastmathFlagsAttr{},
3586 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3587 build(builder, state,
TypeRange{}, intrin, args,
3594 mlir::Type resultType, mlir::StringAttr intrin,
3596 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
3604 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3605 build(builder, state, resultTypes, intrin, args, fastMathFlags,
3612 StringAttr intrinAttr;
3616 ArrayAttr opBundleTags;
3630 return mlir::failure();
3633 return mlir::failure();
3638 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
3639 result && failed(*result))
3641 if (opBundleTags && !opBundleTags.empty())
3643 CallIntrinsicOp::getOpBundleTagsAttrName(result.
name).getValue(),
3647 return mlir::failure();
3652 operands, argAttrs, resultAttrs))
3655 parser.
getBuilder(), result, argAttrs, resultAttrs,
3656 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
3659 opBundleOperandTypes,
3660 getOpBundleSizesAttrName(result.
name)))
3663 int32_t numOpBundleOperands = 0;
3664 for (
const auto &operands : opBundleOperands)
3665 numOpBundleOperands += operands.size();
3668 CallIntrinsicOp::getOperandSegmentSizeAttr(),
3670 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
3672 return mlir::success();
3680 p <<
"(" << args <<
")";
3683 if (!getOpBundleOperands().empty()) {
3686 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
3690 {getOperandSegmentSizesAttrName(),
3691 getOpBundleSizesAttrName(), getIntrinAttrName(),
3692 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
3693 getResAttrsAttrName()});
3699 p, args.
getTypes(), getArgAttrsAttr(),
3700 false, getResultTypes(), getResAttrsAttr());
3713 .Case<AccessGroupAttr, AliasScopeAttr, AliasScopeDomainAttr,
3714 DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
3715 DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr,
3716 DIGlobalVariableAttr, DIGlobalVariableExpressionAttr,
3717 DIImportedEntityAttr, DILabelAttr, DILexicalBlockAttr,
3718 DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
3719 DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
3720 DISubprogramAttr, DISubroutineTypeAttr, LoopAnnotationAttr,
3721 LoopVectorizeAttr, LoopInterleaveAttr, LoopUnrollAttr,
3722 LoopUnrollAndJamAttr, LoopLICMAttr, LoopDistributeAttr,
3723 LoopPipelineAttr, LoopPeeledAttr, LoopUnswitchAttr, TBAARootAttr,
3724 TBAATagAttr, TBAATypeDescriptorAttr>([&](
auto attr) {
3725 os << decltype(attr)::getMnemonic();
3726 return AliasResult::OverridableAlias;
3740 return emitOpError(
"must appear at the module level");
3751 return emitOpError(
"must appear at the module level");
3753 if (!isa<ModuleFlagAttr>(flag))
3754 return emitOpError(
"expected a module flag attribute");
3762 void InlineAsmOp::getEffects(
3765 if (getHasSideEffects()) {
3778 getBlockAddr().getFunction());
3779 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
3782 return emitOpError(
"must reference a function defined by 'llvm.func'");
3792 BlockTagOp BlockAddressOp::getBlockTagOp() {
3798 BlockTagOp blockTagOp =
nullptr;
3799 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
3800 if (labelOp.getTag() == getBlockAddr().getTag()) {
3801 blockTagOp = labelOp;
3810 if (!getBlockTagOp())
3812 "expects an existing block label target in the referenced function");
3819 OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
3827 return build(builder, state, cond, {},
3833 ArrayRef<llvm::OperandBundleDefT<Value>> opBundles) {
3836 opBundleOperands.reserve(opBundles.size());
3837 opBundleTags.reserve(opBundles.size());
3839 for (
const llvm::OperandBundleDefT<Value> &bundle : opBundles) {
3840 opBundleOperands.emplace_back(bundle.inputs());
3841 opBundleTags.push_back(
3846 return build(builder, state, cond, opBundleOperands, opBundleTagsAttr);
3851 llvm::OperandBundleDefT<Value> opBundle(
3853 return build(builder, state, cond, opBundle);
3858 return build(builder, state, cond,
"align",
ValueRange{ptr, align});
3864 return build(builder, state, cond,
"separate_storage",
3875 auto ptrsVectorType = getPtrs().getType();
3876 Type expectedPtrsVectorType =
3881 if (ptrsVectorType != expectedPtrsVectorType)
3882 return emitOpError(
"expected operand #1 type to be ")
3883 << expectedPtrsVectorType;
3892 auto ptrsVectorType = getPtrs().getType();
3893 Type expectedPtrsVectorType =
3898 if (ptrsVectorType != expectedPtrsVectorType)
3899 return emitOpError(
"expected operand #2 type to be ")
3900 << expectedPtrsVectorType;
3908 void LLVMDialect::initialize() {
3909 registerAttributes();
3912 addTypes<LLVMVoidType,
3915 LLVMMetadataType>();
3921 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3924 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3928 allowUnknownOperations();
3930 addInterfaces<LLVMOpAsmDialectInterface>();
3932 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
3935 #define GET_OP_CLASSES
3936 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3938 #define GET_OP_CLASSES
3939 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3941 LogicalResult LLVMDialect::verifyDataLayoutString(
3945 if (maybeDataLayout)
3948 std::string message;
3949 llvm::raw_string_ostream messageStream(message);
3950 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
3951 reportError(
"invalid data layout descriptor: " + message);
3956 LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
3962 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
3964 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
3965 return verifyDataLayoutString(
3966 stringAttr.getValue(),
3967 [op](
const Twine &message) { op->emitOpError() << message.str(); });
3970 << LLVM::LLVMDialect::getDataLayoutAttrName()
3971 <<
"' to be a string attributes";
3974 LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
3982 StringAttr name = paramAttr.
getName();
3984 auto checkUnitAttrType = [&]() -> LogicalResult {
3985 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
3986 return op->
emitError() << name <<
" should be a unit attribute";
3989 auto checkTypeAttrType = [&]() -> LogicalResult {
3990 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
3991 return op->
emitError() << name <<
" should be a type attribute";
3994 auto checkIntegerAttrType = [&]() -> LogicalResult {
3995 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
3996 return op->
emitError() << name <<
" should be an integer attribute";
3999 auto checkPointerType = [&]() -> LogicalResult {
4000 if (!llvm::isa<LLVMPointerType>(paramType))
4002 << name <<
" attribute attached to non-pointer LLVM type";
4005 auto checkIntegerType = [&]() -> LogicalResult {
4006 if (!llvm::isa<IntegerType>(paramType))
4008 << name <<
" attribute attached to non-integer LLVM type";
4011 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4012 if (failed(checkPointerType()))
4019 if (name == LLVMDialect::getNoAliasAttrName() ||
4020 name == LLVMDialect::getReadonlyAttrName() ||
4021 name == LLVMDialect::getReadnoneAttrName() ||
4022 name == LLVMDialect::getWriteOnlyAttrName() ||
4023 name == LLVMDialect::getNestAttrName() ||
4024 name == LLVMDialect::getNoCaptureAttrName() ||
4025 name == LLVMDialect::getNoFreeAttrName() ||
4026 name == LLVMDialect::getNonNullAttrName()) {
4027 if (failed(checkUnitAttrType()))
4029 if (verifyValueType && failed(checkPointerType()))
4035 if (name == LLVMDialect::getStructRetAttrName() ||
4036 name == LLVMDialect::getByValAttrName() ||
4037 name == LLVMDialect::getByRefAttrName() ||
4038 name == LLVMDialect::getElementTypeAttrName() ||
4039 name == LLVMDialect::getInAllocaAttrName() ||
4040 name == LLVMDialect::getPreallocatedAttrName()) {
4041 if (failed(checkTypeAttrType()))
4043 if (verifyValueType && failed(checkPointerTypeMatches()))
4049 if (name == LLVMDialect::getSExtAttrName() ||
4050 name == LLVMDialect::getZExtAttrName()) {
4051 if (failed(checkUnitAttrType()))
4053 if (verifyValueType && failed(checkIntegerType()))
4059 if (name == LLVMDialect::getAlignAttrName() ||
4060 name == LLVMDialect::getDereferenceableAttrName() ||
4061 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4062 if (failed(checkIntegerAttrType()))
4064 if (verifyValueType && failed(checkPointerType()))
4070 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4071 if (failed(checkIntegerAttrType()))
4077 if (name == LLVMDialect::getNoUndefAttrName() ||
4078 name == LLVMDialect::getInRegAttrName() ||
4079 name == LLVMDialect::getReturnedAttrName())
4080 return checkUnitAttrType();
4086 LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4090 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4093 Type argType = funcOp.getArgumentTypes()[argIdx];
4095 return verifyParameterAttribute(op, argType, argAttr);
4098 LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4102 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4105 Type resType = funcOp.getResultTypes()[resIdx];
4109 if (llvm::isa<LLVMVoidType>(resType))
4110 return op->
emitError() <<
"cannot attach result attributes to functions "
4111 "with a void return";
4115 auto name = resAttr.
getName();
4116 if (name == LLVMDialect::getAllocAlignAttrName() ||
4117 name == LLVMDialect::getAllocatedPointerAttrName() ||
4118 name == LLVMDialect::getByValAttrName() ||
4119 name == LLVMDialect::getByRefAttrName() ||
4120 name == LLVMDialect::getInAllocaAttrName() ||
4121 name == LLVMDialect::getNestAttrName() ||
4122 name == LLVMDialect::getNoCaptureAttrName() ||
4123 name == LLVMDialect::getNoFreeAttrName() ||
4124 name == LLVMDialect::getPreallocatedAttrName() ||
4125 name == LLVMDialect::getReadnoneAttrName() ||
4126 name == LLVMDialect::getReadonlyAttrName() ||
4127 name == LLVMDialect::getReturnedAttrName() ||
4128 name == LLVMDialect::getStackAlignmentAttrName() ||
4129 name == LLVMDialect::getStructRetAttrName() ||
4130 name == LLVMDialect::getWriteOnlyAttrName())
4131 return op->
emitError() << name <<
" is not a valid result attribute";
4132 return verifyParameterAttribute(op, resType, resAttr);
4140 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4141 if (isa<LLVM::LLVMPointerType>(type))
4142 return builder.
create<LLVM::AddressOfOp>(loc, type, symbol);
4143 if (isa<LLVM::UndefAttr>(value))
4144 return builder.
create<LLVM::UndefOp>(loc, type);
4145 if (isa<LLVM::PoisonAttr>(value))
4146 return builder.
create<LLVM::PoisonOp>(loc, type);
4147 if (isa<LLVM::ZeroAttr>(value))
4148 return builder.
create<LLVM::ZeroOp>(loc, type);
4150 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4158 StringRef name, StringRef value,
4159 LLVM::Linkage linkage) {
4162 "expected builder to point to a block constrained in an op");
4165 assert(module &&
"builder points to an op outside of a module");
4171 auto global = moduleBuilder.
create<LLVM::GlobalOp>(
4172 loc, type,
true, linkage, name,
4178 builder.
create<LLVM::AddressOfOp>(loc, ptrType, global.getSymNameAttr());
4179 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 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 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,...
The possible results of an alias query.
@ NoAlias
The two locations do not alias at all.
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.
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.
OpAsmDialectInterface(Dialect *dialect)
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
virtual ParseResult parseSuccessor(Block *&dest)=0
Parse a single operation successor.
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
virtual OptionalParseResult parseOptionalOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single operand if present.
virtual ParseResult parseSuccessorAndUseList(Block *&dest, SmallVectorImpl< Value > &operands)=0
Parse a single operation successor and its operand list.
virtual OptionalParseResult parseOptionalRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region if present.
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printNewline()=0
Print a newline and indent the printer to the start of the current operation.
virtual void printSuccessorAndUseList(Block *successor, ValueRange succOperands)=0
Print the successor and its operands.
void printOperands(const ContainerType &container)
Print a comma separated list of operands.
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes=std::nullopt, ArrayRef< Location > locs=std::nullopt)
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
This class represents a single result from folding an operation.
This class provides the API for ops that are known to be isolated from above.
A trait used to provide symbol table functionalities to a region operation.
This class represents a contiguous range of operand ranges, e.g.
This class implements the operand iterators for the Operation class.
type_range getTypes() const
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class implements Optional functionality for ParseResult.
ParseResult value() const
Access the internal ParseResult value.
bool has_value() const
Returns true if we contain a valid ParseResult value.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
iterator_range< OpIterator > getOps()
This class represents a specific instance of an effect.
static DerivedEffect * get()
Returns a unique instance for the derived effect class.
This class models how operands are forwarded to block arguments in control flow.
This class implements the successor iterators for Block.
This class represents a collection of SymbolTables.
Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
This class provides an abstraction for a range of TypeRange.
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class provides an abstraction over the different types of ranges over Values.
type_range getTypes() const
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
static WalkResult advance()
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.
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.