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>();
1889 bool switchedToInsertedValue =
false;
1890 while (insertValueOp) {
1892 auto extractPosSize = extractPos.size();
1893 auto insertPosSize = insertPos.size();
1896 if (extractPos == insertPos)
1897 return insertValueOp.getValue();
1911 if (extractPosSize > insertPosSize &&
1912 extractPos.take_front(insertPosSize) == insertPos) {
1913 insertValueOp = insertValueOp.getValue().getDefiningOp<InsertValueOp>();
1914 extractPos = extractPos.drop_front(insertPosSize);
1915 switchedToInsertedValue =
true;
1920 unsigned min =
std::min(extractPosSize, insertPosSize);
1932 if (extractPos.take_front(
min) == insertPos.take_front(
min))
1937 if (!switchedToInsertedValue) {
1940 getContainerMutable().assign(insertValueOp.getContainer());
1941 result = getResult();
1943 insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1949 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1955 if (getRes().
getType() != valueType)
1956 return emitOpError() <<
"Type mismatch: extracting from "
1957 << getContainer().getType() <<
" should produce "
1958 << valueType <<
" but this op returns "
1959 << getRes().getType();
1965 build(builder, state,
1980 [&](StringRef msg) {
1984 return success(!!valueType);
1994 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
2000 if (getValue().
getType() != valueType)
2001 return emitOpError() <<
"Type mismatch: cannot insert "
2002 << getValue().getType() <<
" into "
2003 << getContainer().getType();
2013 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2017 Type expectedType = parent.getFunctionType().getReturnType();
2018 if (llvm::isa<LLVMVoidType>(expectedType)) {
2022 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2026 if (llvm::isa<LLVMVoidType>(expectedType))
2029 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2032 if (expectedType != getArg().
getType()) {
2034 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2048 assert(module &&
"unexpected operation outside of a module");
2053 return dyn_cast_or_null<GlobalOp>(
2058 return dyn_cast_or_null<LLVMFuncOp>(
2063 return dyn_cast_or_null<AliasOp>(
2072 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2073 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2074 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2076 if (!global && !
function && !alias)
2077 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2078 "'llvm.mlir.alias' or 'llvm.func'");
2080 LLVMPointerType type =
getType();
2081 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2082 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2083 return emitOpError(
"pointer address space must match address space of the "
2084 "referenced global or alias");
2091 return getGlobalNameAttr();
2112 getFunctionNameAttr());
2113 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2114 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2116 if (!
function && !alias)
2118 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2121 if (alias.getInitializer()
2122 .walk([&](AddressOfOp addrOp) {
2123 if (addrOp.getGlobal(symbolTable))
2124 return WalkResult::interrupt();
2125 return WalkResult::advance();
2128 return emitOpError(
"must reference an alias to a function");
2131 if ((
function &&
function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2132 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2134 "target function with 'extern_weak' linkage not allowed");
2150 StringRef symName) {
2157 LogicalResult ComdatOp::verifyRegions() {
2158 Region &body = getBody();
2160 if (!isa<ComdatSelectorOp>(op))
2161 return op.emitError(
2162 "only comdat selector symbols can appear in a comdat region");
2172 bool isConstant, Linkage linkage, StringRef name,
2173 Attribute value, uint64_t alignment,
unsigned addrSpace,
2174 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2208 if (!dbgExprs.empty())
2216 p <<
' ' << stringifyLinkage(getLinkage()) <<
' ';
2217 StringRef visibility = stringifyVisibility(getVisibility_());
2218 if (!visibility.empty())
2219 p << visibility <<
' ';
2220 if (getThreadLocal_())
2221 p <<
"thread_local ";
2222 if (
auto unnamedAddr = getUnnamedAddr()) {
2223 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2231 if (
auto value = getValueOrNull())
2234 if (
auto comdat = getComdat())
2235 p <<
" comdat(" << *comdat <<
')';
2241 {SymbolTable::getSymbolAttrName(),
2242 getGlobalTypeAttrName(), getConstantAttrName(),
2243 getValueAttrName(), getLinkageAttrName(),
2244 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2245 getVisibility_AttrName(), getComdatAttrName(),
2246 getUnnamedAddrAttrName()});
2249 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2253 Region &initializer = getInitializerRegion();
2254 if (!initializer.
empty()) {
2261 std::optional<SymbolRefAttr> attr) {
2266 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2267 return op->
emitError() <<
"expected comdat symbol";
2277 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2278 if (blockTags.contains(blockTagOp.getTag())) {
2279 blockTagOp.emitError()
2280 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2281 <<
"' in the same function: ";
2282 return WalkResult::interrupt();
2284 blockTags.insert(blockTagOp.getTag());
2293 template <
typename OpType>
2300 ctx, parseOptionalLLVMKeyword<Linkage>(
2301 parser, result, LLVM::Linkage::External)));
2306 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2307 parser, result, LLVM::Visibility::Default)));
2312 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2332 if (parseCommonGlobalAndAlias<GlobalOp>(parser, result).failed())
2354 SymbolRefAttr comdat;
2367 if (types.size() > 1)
2371 if (types.empty()) {
2372 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2375 strAttr.getValue().size());
2376 types.push_back(arrayType);
2379 "type can only be omitted for string globals");
2385 if (parseResult.
has_value() && failed(*parseResult))
2395 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2396 return intValue.getValue().isZero();
2397 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2398 return fpValue.getValue().isZero();
2399 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2401 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2403 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2410 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2411 LLVMMetadataType, LLVMLabelType>(
getType())
2412 : llvm::isa<PointerElementTypeInterface>(
getType());
2415 "expects type to be a valid element type for an LLVM global");
2417 return emitOpError(
"must appear at the module level");
2419 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2420 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2421 IntegerType elementType =
2422 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2423 if (!elementType || elementType.getWidth() != 8 ||
2424 type.getNumElements() != strAttr.getValue().size())
2426 "requires an i8 array type of the length equal to that of the string "
2430 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2431 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2432 return emitOpError()
2433 <<
"this target extension type cannot be used in a global";
2436 return emitOpError() <<
"global with target extension type can only be "
2437 "initialized with zero-initializer";
2440 if (getLinkage() == Linkage::Common) {
2441 if (
Attribute value = getValueOrNull()) {
2443 return emitOpError()
2444 <<
"expected zero value for '"
2445 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2450 if (getLinkage() == Linkage::Appending) {
2451 if (!llvm::isa<LLVMArrayType>(
getType())) {
2452 return emitOpError() <<
"expected array type for '"
2453 << stringifyLinkage(Linkage::Appending)
2461 std::optional<uint64_t> alignAttr = getAlignment();
2462 if (alignAttr.has_value()) {
2463 uint64_t value = alignAttr.value();
2464 if (!llvm::isPowerOf2_64(value))
2465 return emitError() <<
"alignment attribute is not a power of 2";
2471 LogicalResult GlobalOp::verifyRegions() {
2472 if (
Block *b = getInitializerBlock()) {
2473 ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2474 if (ret.operand_type_begin() == ret.operand_type_end())
2475 return emitOpError(
"initializer region cannot return void");
2476 if (*ret.operand_type_begin() !=
getType())
2477 return emitOpError(
"initializer region type ")
2478 << *ret.operand_type_begin() <<
" does not match global type "
2482 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2483 if (!iface || !iface.hasNoEffect())
2484 return op.emitError()
2485 <<
"ops with side effects not allowed in global initializers";
2488 if (getValueOrNull())
2489 return emitOpError(
"cannot have both initializer value and region");
2504 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2507 return op->
emitError(
"data element must be symbol or #llvm.zero");
2524 if (getCtors().size() == getPriorities().size() &&
2525 getCtors().size() == getData().size())
2528 "ctors, priorities, and data must have the same number of elements");
2549 if (getDtors().size() == getPriorities().size() &&
2550 getDtors().size() == getData().size())
2553 "dtors, priorities, and data must have the same number of elements");
2561 Linkage linkage, StringRef name,
bool dsoLocal,
2581 p <<
' ' << stringifyLinkage(getLinkage()) <<
' ';
2582 StringRef visibility = stringifyVisibility(getVisibility_());
2583 if (!visibility.empty())
2584 p << visibility <<
' ';
2586 if (std::optional<mlir::LLVM::UnnamedAddr> unnamedAddr = getUnnamedAddr()) {
2587 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2592 if (getThreadLocal_())
2593 p <<
"thread_local ";
2597 {SymbolTable::getSymbolAttrName(),
2598 getAliasTypeAttrName(), getLinkageAttrName(),
2599 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2600 getVisibility_AttrName(), getUnnamedAddrAttrName()});
2603 p <<
" : " <<
getType() <<
' ';
2616 if (parseCommonGlobalAndAlias<AliasOp>(parser, result).failed())
2629 if (types.size() > 1)
2643 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2644 LLVMMetadataType, LLVMLabelType>(
getType())
2645 : llvm::isa<PointerElementTypeInterface>(
getType());
2648 "expects type to be a valid element type for an LLVM global alias");
2651 switch (getLinkage()) {
2652 case Linkage::External:
2653 case Linkage::Internal:
2654 case Linkage::Private:
2656 case Linkage::WeakODR:
2657 case Linkage::Linkonce:
2658 case Linkage::LinkonceODR:
2659 case Linkage::AvailableExternally:
2662 return emitOpError()
2663 <<
"'" << stringifyLinkage(getLinkage())
2664 <<
"' linkage not supported in aliases, available options: private, "
2665 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2666 "available_externally";
2672 LogicalResult AliasOp::verifyRegions() {
2673 Block &b = getInitializerBlock();
2675 if (ret.getNumOperands() == 0 ||
2676 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2677 return emitOpError(
"initializer region must always return a pointer");
2680 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2681 if (!iface || !iface.hasNoEffect())
2682 return op.emitError()
2683 <<
"ops with side effects are not allowed in alias initializers";
2689 unsigned AliasOp::getAddrSpace() {
2690 Block &initializer = getInitializerBlock();
2692 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
2693 return ptrTy.getAddressSpace();
2703 auto containerType = v1.
getType();
2707 build(builder, state, vType, v1, v2, mask);
2708 state.addAttributes(attrs);
2721 "expected an LLVM compatible vector type");
2734 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2735 return emitOpError(
"expected a splat operation for scalable vectors");
2745 assert(empty() &&
"function already has an entry block");
2750 LLVMFunctionType type = getFunctionType();
2751 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2752 entry->
addArgument(type.getParamType(i), getLoc());
2757 StringRef name,
Type type, LLVM::Linkage linkage,
2758 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2761 std::optional<uint64_t> functionEntryCount) {
2777 if (functionEntryCount)
2780 if (argAttrs.empty())
2783 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2784 "expected as many argument attribute lists as arguments");
2786 builder, result, argAttrs, std::nullopt,
2787 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2798 if (outputs.size() > 1) {
2799 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2800 "one function result");
2806 for (
auto t : inputs) {
2808 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2809 "type for function arguments");
2812 llvmInputs.push_back(t);
2819 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2820 "type for function results")
2838 getLinkageAttrName(result.
name),
2840 parseOptionalLLVMKeyword<Linkage>(
2841 parser, result, LLVM::Linkage::External)));
2846 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2847 parser, result, LLVM::Visibility::Default)));
2852 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2857 getCConvAttrName(result.
name),
2859 parser, result, LLVM::CConv::C)));
2861 StringAttr nameAttr;
2871 parser,
true, entryArgs, isVariadic, resultTypes,
2876 for (
auto &arg : entryArgs)
2877 argTypes.push_back(arg.type);
2887 int64_t minRange, maxRange;
2894 getVscaleRangeAttrName(result.
name),
2901 SymbolRefAttr comdat;
2912 parser.
getBuilder(), result, entryArgs, resultAttrs,
2913 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2918 return failure(parseResult.
has_value() && failed(*parseResult));
2926 if (getLinkage() != LLVM::Linkage::External)
2927 p << stringifyLinkage(getLinkage()) <<
' ';
2928 StringRef visibility = stringifyVisibility(getVisibility_());
2929 if (!visibility.empty())
2930 p << visibility <<
' ';
2931 if (
auto unnamedAddr = getUnnamedAddr()) {
2932 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2936 if (getCConv() != LLVM::CConv::C)
2937 p << stringifyCConv(getCConv()) <<
' ';
2941 LLVMFunctionType fnType = getFunctionType();
2944 argTypes.reserve(fnType.getNumParams());
2945 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
2946 argTypes.push_back(fnType.getParamType(i));
2948 Type returnType = fnType.getReturnType();
2949 if (!llvm::isa<LLVMVoidType>(returnType))
2950 resTypes.push_back(returnType);
2953 isVarArg(), resTypes);
2956 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
2957 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
2958 << vscale->getMaxRange().getInt() <<
')';
2961 if (
auto comdat = getComdat())
2962 p <<
" comdat(" << *comdat <<
')';
2966 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
2967 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
2968 getComdatAttrName(), getUnnamedAddrAttrName(),
2969 getVscaleRangeAttrName()});
2972 Region &body = getBody();
2973 if (!body.empty()) {
2985 if (getLinkage() == LLVM::Linkage::Common)
2986 return emitOpError() <<
"functions cannot have '"
2987 << stringifyLinkage(LLVM::Linkage::Common)
2994 if (getLinkage() != LLVM::Linkage::External &&
2995 getLinkage() != LLVM::Linkage::ExternWeak)
2996 return emitOpError() <<
"external functions must have '"
2997 << stringifyLinkage(LLVM::Linkage::External)
2999 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3005 if (isNoInline() && isAlwaysInline())
3006 return emitError(
"no_inline and always_inline attributes are incompatible");
3008 if (isOptimizeNone() && !isNoInline())
3009 return emitOpError(
"with optimize_none must also be no_inline");
3011 Type landingpadResultTy;
3012 StringRef diagnosticMessage;
3013 bool isLandingpadTypeConsistent =
3015 const auto checkType = [&](
Type type, StringRef errorMessage) {
3016 if (!landingpadResultTy) {
3017 landingpadResultTy = type;
3020 if (landingpadResultTy != type) {
3021 diagnosticMessage = errorMessage;
3027 .Case<LandingpadOp>([&](
auto landingpad) {
3028 constexpr StringLiteral errorMessage =
3029 "'llvm.landingpad' should have a consistent result type "
3030 "inside a function";
3031 return checkType(landingpad.getType(), errorMessage);
3033 .Case<ResumeOp>([&](
auto resume) {
3034 constexpr StringLiteral errorMessage =
3035 "'llvm.resume' should have a consistent input type inside a "
3037 return checkType(resume.getValue().getType(), errorMessage);
3040 }).wasInterrupted();
3041 if (!isLandingpadTypeConsistent) {
3042 assert(!diagnosticMessage.empty() &&
3043 "Expecting a non-empty diagnostic message");
3055 LogicalResult LLVMFuncOp::verifyRegions() {
3059 unsigned numArguments = getFunctionType().getNumParams();
3060 Block &entryBlock = front();
3061 for (
unsigned i = 0; i < numArguments; ++i) {
3064 return emitOpError(
"entry block argument #")
3065 << i <<
" is not of LLVM type";
3071 Region *LLVMFuncOp::getCallableRegion() {
3100 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3101 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3102 return emitOpError()
3103 <<
"target extension type does not support zero-initializer";
3125 if (
auto vecType = dyn_cast<VectorType>(t)) {
3126 assert(!vecType.isScalable() &&
3127 "number of elements of a scalable vector type is unknown");
3128 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3130 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3131 return arrayType.getNumElements() *
3139 if (
auto vecType = dyn_cast<VectorType>(t)) {
3140 if (vecType.isScalable())
3144 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3150 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3151 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3152 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3153 !arrayType.getElementType().isInteger(8)) {
3154 return emitOpError() <<
"expected array type of "
3155 << sAttr.getValue().size()
3156 <<
" i8 elements for the string constant";
3160 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3161 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3163 return emitOpError() <<
"expected array attribute for a struct constant";
3167 if (arrayAttr.size() != elementTypes.size()) {
3168 return emitOpError() <<
"expected array attribute of size "
3169 << elementTypes.size();
3171 for (
auto elementTy : elementTypes) {
3172 if (!isa<IntegerType, FloatType, LLVMPPCFP128Type>(elementTy)) {
3173 return emitOpError() <<
"expected struct element types to be floating "
3174 "point type or integer type";
3178 for (
size_t i = 0; i < elementTypes.size(); ++i) {
3180 if (!isa<IntegerAttr, FloatAttr>(element)) {
3181 return emitOpError()
3182 <<
"expected struct element attribute types to be floating "
3183 "point type or integer type";
3185 auto elementType = cast<TypedAttr>(element).getType();
3186 if (elementType != elementTypes[i]) {
3187 return emitOpError()
3188 <<
"struct element at index " << i <<
" is of wrong type";
3194 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
3195 return emitOpError() <<
"does not support target extension type.";
3199 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
3200 if (!llvm::isa<IntegerType>(
getType()))
3201 return emitOpError() <<
"expected integer type";
3202 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3203 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
3204 unsigned floatWidth = APFloat::getSizeInBits(sem);
3205 if (
auto floatTy = dyn_cast<FloatType>(
getType())) {
3206 if (floatTy.getWidth() != floatWidth) {
3207 return emitOpError() <<
"expected float type of width " << floatWidth;
3212 if (isa<IntegerType>(
getType()) && !
getType().isInteger(floatWidth)) {
3213 return emitOpError() <<
"expected integer type of width " << floatWidth;
3215 }
else if (isa<ElementsAttr, ArrayAttr>(getValue())) {
3219 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3220 if (!splatElementsAttr)
3221 return emitOpError()
3222 <<
"scalable vector type requires a splat attribute";
3225 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3226 return emitOpError() <<
"expected vector or array type";
3228 int64_t attrNumElements;
3229 if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue()))
3230 attrNumElements = elementsAttr.getNumElements();
3232 attrNumElements = cast<ArrayAttr>(getValue()).size();
3234 return emitOpError()
3235 <<
"type and attribute have a different number of elements: "
3238 return emitOpError()
3239 <<
"only supports integer, float, string or elements attributes";
3245 bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3247 auto typedAttr = dyn_cast<TypedAttr>(value);
3254 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3259 if (isBuildableWith(value, type))
3260 return builder.
create<LLVM::ConstantOp>(loc, cast<TypedAttr>(value));
3265 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3273 AtomicOrdering ordering, StringRef syncscope,
3274 unsigned alignment,
bool isVolatile) {
3275 build(builder, state, val.
getType(), binOp, ptr, val, ordering,
3276 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3279 nullptr,
nullptr,
nullptr);
3283 auto valType = getVal().getType();
3284 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3285 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax) {
3288 return emitOpError(
"expected LLVM IR fixed vector type");
3289 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3292 "expected LLVM IR floating point type for vector element");
3294 return emitOpError(
"expected LLVM IR floating point type");
3296 }
else if (getBinOp() == AtomicBinOp::xchg) {
3299 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3301 auto intType = llvm::dyn_cast<IntegerType>(valType);
3302 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3303 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3305 return emitOpError(
"expected LLVM IR integer type");
3308 if (
static_cast<unsigned>(getOrdering()) <
3309 static_cast<unsigned>(AtomicOrdering::monotonic))
3310 return emitOpError() <<
"expected at least '"
3311 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3324 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3329 AtomicOrdering successOrdering,
3330 AtomicOrdering failureOrdering, StringRef syncscope,
3331 unsigned alignment,
bool isWeak,
bool isVolatile) {
3333 successOrdering, failureOrdering,
3334 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3336 isVolatile,
nullptr,
3337 nullptr,
nullptr,
nullptr);
3341 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3343 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3344 auto valType = getVal().getType();
3347 return emitOpError(
"unexpected LLVM IR type");
3348 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3349 getFailureOrdering() < AtomicOrdering::monotonic)
3350 return emitOpError(
"ordering must be at least 'monotonic'");
3351 if (getFailureOrdering() == AtomicOrdering::release ||
3352 getFailureOrdering() == AtomicOrdering::acq_rel)
3353 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3362 AtomicOrdering ordering, StringRef syncscope) {
3363 build(builder, state, ordering,
3364 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3368 if (getOrdering() == AtomicOrdering::not_atomic ||
3369 getOrdering() == AtomicOrdering::unordered ||
3370 getOrdering() == AtomicOrdering::monotonic)
3371 return emitOpError(
"can be given only acquire, release, acq_rel, "
3372 "and seq_cst orderings");
3382 template <
class ExtOp>
3384 IntegerType inputType, outputType;
3387 return op.emitError(
3388 "input type is a vector but output type is an integer");
3391 return op.emitError(
"input and output vectors are of incompatible shape");
3394 inputType = cast<IntegerType>(
3395 cast<VectorType>(op.getArg().getType()).getElementType());
3396 outputType = cast<IntegerType>(
3397 cast<VectorType>(op.getResult().getType()).getElementType());
3401 inputType = cast<IntegerType>(op.getArg().getType());
3402 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3404 return op.emitError(
3405 "input type is an integer but output type is a vector");
3408 if (outputType.getWidth() <= inputType.getWidth())
3409 return op.emitError(
"integer width of the output type is smaller or "
3410 "equal to the integer width of the input type");
3418 LogicalResult
ZExtOp::verify() {
return verifyExtOp<ZExtOp>(*
this); }
3421 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3425 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3433 LogicalResult
SExtOp::verify() {
return verifyExtOp<SExtOp>(*
this); }
3440 template <
typename T>
3442 typename T::FoldAdaptor adaptor) {
3444 if (castOp.getArg().getType() == castOp.getType())
3445 return castOp.getArg();
3446 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3448 if (prev.getArg().getType() == castOp.getType())
3449 return prev.getArg();
3451 castOp.getArgMutable().set(prev.getArg());
3452 return Value{castOp};
3457 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3462 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3464 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3469 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3470 return emitOpError(
"can only cast pointers from and to pointers");
3475 auto isVector = llvm::IsaPred<VectorType>;
3479 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3480 return emitOpError(
"cannot cast pointer to vector of pointers");
3482 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3483 return emitOpError(
"cannot cast vector of pointers to pointer");
3487 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3488 return emitOpError(
"cannot cast pointers of different address spaces, "
3489 "use 'llvm.addrspacecast' instead");
3498 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3502 Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3510 adaptor.getDynamicIndices());
3514 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
3515 if (integer.getValue().isZero())
3522 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3529 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3530 gepArgs.emplace_back(val);
3532 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3538 gepArgs.emplace_back(integer.getInt());
3546 getDynamicIndicesMutable().assign(dynamicIndices);
3547 setRawConstantIndices(rawConstantIndices);
3548 return Value{*
this};
3554 Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3561 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3565 if (rhs.getValue().getZExtValue() >=
3566 getLhs().
getType().getIntOrFloatBitWidth())
3569 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3581 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3585 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3597 if (!getIntrin().starts_with(
"llvm."))
3598 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3606 build(builder, state,
TypeRange{}, intrin, args,
3607 FastmathFlagsAttr{},
3614 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3615 build(builder, state,
TypeRange{}, intrin, args,
3622 mlir::Type resultType, mlir::StringAttr intrin,
3624 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
3632 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3633 build(builder, state, resultTypes, intrin, args, fastMathFlags,
3640 StringAttr intrinAttr;
3644 ArrayAttr opBundleTags;
3658 return mlir::failure();
3661 return mlir::failure();
3666 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
3667 result && failed(*result))
3669 if (opBundleTags && !opBundleTags.empty())
3671 CallIntrinsicOp::getOpBundleTagsAttrName(result.
name).getValue(),
3675 return mlir::failure();
3680 operands, argAttrs, resultAttrs))
3683 parser.
getBuilder(), result, argAttrs, resultAttrs,
3684 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
3687 opBundleOperandTypes,
3688 getOpBundleSizesAttrName(result.
name)))
3691 int32_t numOpBundleOperands = 0;
3692 for (
const auto &operands : opBundleOperands)
3693 numOpBundleOperands += operands.size();
3696 CallIntrinsicOp::getOperandSegmentSizeAttr(),
3698 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
3700 return mlir::success();
3708 p <<
"(" << args <<
")";
3711 if (!getOpBundleOperands().empty()) {
3714 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
3718 {getOperandSegmentSizesAttrName(),
3719 getOpBundleSizesAttrName(), getIntrinAttrName(),
3720 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
3721 getResAttrsAttrName()});
3727 p, args.
getTypes(), getArgAttrsAttr(),
3728 false, getResultTypes(), getResAttrsAttr());
3741 .Case<AccessGroupAttr, AliasScopeAttr, AliasScopeDomainAttr,
3742 DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
3743 DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr,
3744 DIGlobalVariableAttr, DIGlobalVariableExpressionAttr,
3745 DIImportedEntityAttr, DILabelAttr, DILexicalBlockAttr,
3746 DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
3747 DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
3748 DISubprogramAttr, DISubroutineTypeAttr, LoopAnnotationAttr,
3749 LoopVectorizeAttr, LoopInterleaveAttr, LoopUnrollAttr,
3750 LoopUnrollAndJamAttr, LoopLICMAttr, LoopDistributeAttr,
3751 LoopPipelineAttr, LoopPeeledAttr, LoopUnswitchAttr, TBAARootAttr,
3752 TBAATagAttr, TBAATypeDescriptorAttr>([&](
auto attr) {
3753 os << decltype(attr)::getMnemonic();
3754 return AliasResult::OverridableAlias;
3768 return emitOpError(
"must appear at the module level");
3779 return emitOpError(
"must appear at the module level");
3781 if (!isa<ModuleFlagAttr>(flag))
3782 return emitOpError(
"expected a module flag attribute");
3790 void InlineAsmOp::getEffects(
3793 if (getHasSideEffects()) {
3806 getBlockAddr().getFunction());
3807 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
3810 return emitOpError(
"must reference a function defined by 'llvm.func'");
3820 BlockTagOp BlockAddressOp::getBlockTagOp() {
3826 BlockTagOp blockTagOp =
nullptr;
3827 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
3828 if (labelOp.getTag() == getBlockAddr().getTag()) {
3829 blockTagOp = labelOp;
3838 if (!getBlockTagOp())
3840 "expects an existing block label target in the referenced function");
3847 OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
3854 assert(index < getNumSuccessors() &&
"invalid successor index");
3866 rangeSegments.push_back(range.size());
3880 Block *destination = nullptr;
3881 SmallVector<OpAsmParser::UnresolvedOperand> operands;
3882 SmallVector<Type> operandTypes;
3884 if (parser.parseSuccessor(destination).failed())
3887 if (succeeded(parser.parseOptionalLParen())) {
3888 if (failed(parser.parseOperandList(
3889 operands, OpAsmParser::Delimiter::None)) ||
3890 failed(parser.parseColonTypeList(operandTypes)) ||
3891 failed(parser.parseRParen()))
3894 succOperandBlocks.push_back(destination);
3895 succOperands.emplace_back(operands);
3896 succOperandsTypes.emplace_back(operandTypes);
3899 "successor blocks")))
3910 llvm::zip(succs, succOperands),
3916 if (!succOperands.empty())
3927 return build(builder, state, cond, {},
3933 ArrayRef<llvm::OperandBundleDefT<Value>> opBundles) {
3936 opBundleOperands.reserve(opBundles.size());
3937 opBundleTags.reserve(opBundles.size());
3939 for (
const llvm::OperandBundleDefT<Value> &bundle : opBundles) {
3940 opBundleOperands.emplace_back(bundle.inputs());
3941 opBundleTags.push_back(
3946 return build(builder, state, cond, opBundleOperands, opBundleTagsAttr);
3951 llvm::OperandBundleDefT<Value> opBundle(
3953 return build(builder, state, cond, opBundle);
3958 return build(builder, state, cond,
"align",
ValueRange{ptr, align});
3964 return build(builder, state, cond,
"separate_storage",
3975 auto ptrsVectorType = getPtrs().getType();
3976 Type expectedPtrsVectorType =
3981 if (ptrsVectorType != expectedPtrsVectorType)
3982 return emitOpError(
"expected operand #1 type to be ")
3983 << expectedPtrsVectorType;
3992 auto ptrsVectorType = getPtrs().getType();
3993 Type expectedPtrsVectorType =
3998 if (ptrsVectorType != expectedPtrsVectorType)
3999 return emitOpError(
"expected operand #2 type to be ")
4000 << expectedPtrsVectorType;
4008 void LLVMDialect::initialize() {
4009 registerAttributes();
4012 addTypes<LLVMVoidType,
4015 LLVMMetadataType>();
4021 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4024 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4028 allowUnknownOperations();
4030 addInterfaces<LLVMOpAsmDialectInterface>();
4032 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4035 #define GET_OP_CLASSES
4036 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
4038 #define GET_OP_CLASSES
4039 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
4041 LogicalResult LLVMDialect::verifyDataLayoutString(
4045 if (maybeDataLayout)
4048 std::string message;
4049 llvm::raw_string_ostream messageStream(message);
4050 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4051 reportError(
"invalid data layout descriptor: " + message);
4056 LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4062 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4064 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4065 return verifyDataLayoutString(
4066 stringAttr.getValue(),
4067 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4070 << LLVM::LLVMDialect::getDataLayoutAttrName()
4071 <<
"' to be a string attributes";
4074 LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4082 StringAttr name = paramAttr.
getName();
4084 auto checkUnitAttrType = [&]() -> LogicalResult {
4085 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4086 return op->
emitError() << name <<
" should be a unit attribute";
4089 auto checkTypeAttrType = [&]() -> LogicalResult {
4090 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4091 return op->
emitError() << name <<
" should be a type attribute";
4094 auto checkIntegerAttrType = [&]() -> LogicalResult {
4095 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4096 return op->
emitError() << name <<
" should be an integer attribute";
4099 auto checkPointerType = [&]() -> LogicalResult {
4100 if (!llvm::isa<LLVMPointerType>(paramType))
4102 << name <<
" attribute attached to non-pointer LLVM type";
4105 auto checkIntegerType = [&]() -> LogicalResult {
4106 if (!llvm::isa<IntegerType>(paramType))
4108 << name <<
" attribute attached to non-integer LLVM type";
4111 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4112 if (failed(checkPointerType()))
4119 if (name == LLVMDialect::getNoAliasAttrName() ||
4120 name == LLVMDialect::getReadonlyAttrName() ||
4121 name == LLVMDialect::getReadnoneAttrName() ||
4122 name == LLVMDialect::getWriteOnlyAttrName() ||
4123 name == LLVMDialect::getNestAttrName() ||
4124 name == LLVMDialect::getNoCaptureAttrName() ||
4125 name == LLVMDialect::getNoFreeAttrName() ||
4126 name == LLVMDialect::getNonNullAttrName()) {
4127 if (failed(checkUnitAttrType()))
4129 if (verifyValueType && failed(checkPointerType()))
4135 if (name == LLVMDialect::getStructRetAttrName() ||
4136 name == LLVMDialect::getByValAttrName() ||
4137 name == LLVMDialect::getByRefAttrName() ||
4138 name == LLVMDialect::getElementTypeAttrName() ||
4139 name == LLVMDialect::getInAllocaAttrName() ||
4140 name == LLVMDialect::getPreallocatedAttrName()) {
4141 if (failed(checkTypeAttrType()))
4143 if (verifyValueType && failed(checkPointerTypeMatches()))
4149 if (name == LLVMDialect::getSExtAttrName() ||
4150 name == LLVMDialect::getZExtAttrName()) {
4151 if (failed(checkUnitAttrType()))
4153 if (verifyValueType && failed(checkIntegerType()))
4159 if (name == LLVMDialect::getAlignAttrName() ||
4160 name == LLVMDialect::getDereferenceableAttrName() ||
4161 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4162 if (failed(checkIntegerAttrType()))
4164 if (verifyValueType && failed(checkPointerType()))
4170 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4171 if (failed(checkIntegerAttrType()))
4177 if (name == LLVMDialect::getNoUndefAttrName() ||
4178 name == LLVMDialect::getInRegAttrName() ||
4179 name == LLVMDialect::getReturnedAttrName())
4180 return checkUnitAttrType();
4186 LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4190 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4193 Type argType = funcOp.getArgumentTypes()[argIdx];
4195 return verifyParameterAttribute(op, argType, argAttr);
4198 LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4202 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4205 Type resType = funcOp.getResultTypes()[resIdx];
4209 if (llvm::isa<LLVMVoidType>(resType))
4210 return op->
emitError() <<
"cannot attach result attributes to functions "
4211 "with a void return";
4215 auto name = resAttr.
getName();
4216 if (name == LLVMDialect::getAllocAlignAttrName() ||
4217 name == LLVMDialect::getAllocatedPointerAttrName() ||
4218 name == LLVMDialect::getByValAttrName() ||
4219 name == LLVMDialect::getByRefAttrName() ||
4220 name == LLVMDialect::getInAllocaAttrName() ||
4221 name == LLVMDialect::getNestAttrName() ||
4222 name == LLVMDialect::getNoCaptureAttrName() ||
4223 name == LLVMDialect::getNoFreeAttrName() ||
4224 name == LLVMDialect::getPreallocatedAttrName() ||
4225 name == LLVMDialect::getReadnoneAttrName() ||
4226 name == LLVMDialect::getReadonlyAttrName() ||
4227 name == LLVMDialect::getReturnedAttrName() ||
4228 name == LLVMDialect::getStackAlignmentAttrName() ||
4229 name == LLVMDialect::getStructRetAttrName() ||
4230 name == LLVMDialect::getWriteOnlyAttrName())
4231 return op->
emitError() << name <<
" is not a valid result attribute";
4232 return verifyParameterAttribute(op, resType, resAttr);
4240 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4241 if (isa<LLVM::LLVMPointerType>(type))
4242 return builder.
create<LLVM::AddressOfOp>(loc, type, symbol);
4243 if (isa<LLVM::UndefAttr>(value))
4244 return builder.
create<LLVM::UndefOp>(loc, type);
4245 if (isa<LLVM::PoisonAttr>(value))
4246 return builder.
create<LLVM::PoisonOp>(loc, type);
4247 if (isa<LLVM::ZeroAttr>(value))
4248 return builder.
create<LLVM::ZeroOp>(loc, type);
4250 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4258 StringRef name, StringRef value,
4259 LLVM::Linkage linkage) {
4262 "expected builder to point to a block constrained in an op");
4265 assert(module &&
"builder points to an op outside of a module");
4271 auto global = moduleBuilder.
create<LLVM::GlobalOp>(
4272 loc, type,
true, linkage, name,
4278 builder.
create<LLVM::AddressOfOp>(loc, ptrType, global.getSymNameAttr());
4279 return builder.
create<LLVM::GEPOp>(loc, ptrType, type, globalPtr,
static OperandRange getSuccessorOperands(Block *block, unsigned successorIndex)
Return the operand range used to transfer operands from block to its successor with the given index.
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
static Operation * materializeConstant(Dialect *dialect, OpBuilder &builder, Attribute value, Type type, Location loc)
A utility function used to materialize a constant for a given attribute and type.
static MLIRContext * getContext(OpFoldResult val)
static int parseOptionalKeywordAlternative(OpAsmParser &parser, ArrayRef< StringRef > keywords)
LogicalResult verifyCallOpVarCalleeType(OpTy callOp)
Verify that the parameter and return types of the variadic callee type match the callOp argument and ...
LogicalResult checkGlobalXtorData(Operation *op, ArrayAttr data)
static ParseResult parseGEPIndices(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &indices, DenseI32ArrayAttr &rawConstantIndices)
static LogicalResult verifyOperandBundles(OpType &op)
static ParseResult parseCmpOp(OpAsmParser &parser, OperationState &result)
LogicalResult verifyAtomicMemOp(OpTy memOp, Type valueType, ArrayRef< AtomicOrdering > unsupportedOrderings)
Verifies the attributes and the type of atomic memory access operations.
static void printOneOpBundle(OpAsmPrinter &p, OperandRange operands, TypeRange operandTypes, StringRef tag)
static LogicalResult verifyComdat(Operation *op, std::optional< SymbolRefAttr > attr)
static RetTy parseOptionalLLVMKeyword(OpAsmParser &parser, OperationState &result, EnumTy defaultValue)
Parse an enum from the keyword, or default to the provided default value.
static LLVMFunctionType getLLVMFuncType(MLIRContext *context, TypeRange results, ValueRange args)
Constructs a LLVMFunctionType from MLIR results and args.
static void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type flagType, DenseIntElementsAttr caseValues, SuccessorRange caseDestinations, OperandRangeRange caseOperands, const TypeRangeRange &caseOperandTypes)
static ParseResult resolveOpBundleOperands(OpAsmParser &parser, SMLoc loc, OperationState &state, ArrayRef< SmallVector< OpAsmParser::UnresolvedOperand >> opBundleOperands, ArrayRef< SmallVector< Type >> opBundleOperandTypes, StringAttr opBundleSizesAttrName)
static ParseResult parseOptionalCallFuncPtr(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operands)
Parses an optional function pointer operand before the call argument list for indirect calls,...
static bool isZeroAttribute(Attribute value)
static void printGEPIndices(OpAsmPrinter &printer, LLVM::GEPOp gepOp, OperandRange indices, DenseI32ArrayAttr rawConstantIndices)
static LLVMStructType getValAndBoolStructType(Type valType)
Returns an LLVM struct type that contains a value type and a boolean type.
static void printOpBundles(OpAsmPrinter &p, Operation *op, OperandRangeRange opBundleOperands, TypeRangeRange opBundleOperandTypes, std::optional< ArrayAttr > opBundleTags)
static void printShuffleType(AsmPrinter &printer, Operation *op, Type v1Type, Type resType, DenseI32ArrayAttr mask)
Nothing to do when the result type is inferred.
static LogicalResult verifyBlockTags(LLVMFuncOp funcOp)
static Type buildLLVMFunctionType(OpAsmParser &parser, SMLoc loc, ArrayRef< Type > inputs, ArrayRef< Type > outputs, function_interface_impl::VariadicFlag variadicFlag)
static auto processFMFAttr(ArrayRef< NamedAttribute > attrs)
static std::optional< ParseResult > parseOpBundles(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand >> &opBundleOperands, SmallVector< SmallVector< Type >> &opBundleOperandTypes, ArrayAttr &opBundleTags)
static Operation * parentLLVMModule(Operation *op)
static ParseResult parseSwitchOpCases(OpAsmParser &parser, Type flagType, DenseIntElementsAttr &caseValues, SmallVectorImpl< Block * > &caseDestinations, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand >> &caseOperands, SmallVectorImpl< SmallVector< Type >> &caseOperandTypes)
<cases> ::= [ (case (, case )* )? ] <case> ::= integer : bb-id (( ssa-use-and-type-list ))?
static TypeAttr getCallOpVarCalleeType(LLVMFunctionType calleeType)
Gets the variadic callee type for a LLVMFunctionType.
static Type getInsertExtractValueElementType(function_ref< InFlightDiagnostic(StringRef)> emitError, Type containerType, ArrayRef< int64_t > position)
Extract the type at position in the LLVM IR aggregate type containerType.
static ParseResult parseOneOpBundle(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand >> &opBundleOperands, SmallVector< SmallVector< Type >> &opBundleOperandTypes, SmallVector< Attribute > &opBundleTags)
static ParseResult parseIndirectBrOpSucessors(OpAsmParser &parser, Type &flagType, SmallVectorImpl< Block * > &succOperandBlocks, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand >> &succOperands, SmallVectorImpl< SmallVector< Type >> &succOperandsTypes)
static void printIndirectBrOpSucessors(OpAsmPrinter &p, IndirectBrOp op, Type flagType, SuccessorRange succs, OperandRangeRange succOperands, const TypeRangeRange &succOperandsTypes)
static 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,...
static VectorType getVectorType(Type scalarTy, const VectorizationStrategy *strategy)
Returns the vector type resulting from applying the provided vectorization strategy on the scalar typ...
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.
@ Square
Square brackets surrounding zero or more operands.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseColonTypeList(SmallVectorImpl< Type > &result)=0
Parse a colon followed by a type list, which must have at least one type.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseOptionalColonTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional colon followed by a type list, which if present must have at least one type.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
virtual ParseResult parseCustomAttributeWithFallback(Attribute &result, Type type, function_ref< ParseResult(Attribute &result, Type type)> parseAttribute)=0
Parse a custom attribute with the provided callback, unless the next token is #, in which case the ge...
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
virtual ParseResult parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
virtual void printAttribute(Attribute attr)
Attributes are known-constant values of operations.
This class provides an abstraction over the different types of ranges over Blocks.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
static BoolAttr get(MLIRContext *context, bool value)
This class is a general helper class for creating context-global objects like types,...
IntegerAttr getI32IntegerAttr(int32_t value)
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
IntegerAttr getI64IntegerAttr(int64_t value)
Ty getType(Args &&...args)
Get or construct an instance of the type Ty with provided arguments.
StringAttr getStringAttr(const Twine &bytes)
TypedAttr getZeroAttr(Type type)
MLIRContext * getContext() const
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
The main mechanism for performing data layout queries.
static DataLayout closest(Operation *op)
Returns the layout of the closest parent operation carrying layout info.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
An attribute that represents a reference to a dense vector or tensor object.
std::enable_if_t<!std::is_base_of< Attribute, T >::value||std::is_same< Attribute, T >::value, T > getSplatValue() const
Return the splat value for this attribute.
auto getValues() const
Return the held element values as a range of the given type.
Type getElementType() const
Return the element type of this DenseElementsAttr.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
An attribute that represents a reference to a dense integer vector or tensor object.
static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg)
Get an instance of a DenseIntElementsAttr with the given arguments.
A symbol reference with a reference path containing a single element.
StringRef getValue() const
Returns the name of the held symbol reference.
StringAttr getAttr() const
Returns the name of the held symbol reference as a StringAttr.
This class represents a fused location whose metadata is known to be an instance of the given type.
This class represents a diagnostic that is inflight and set to be reported.
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
Class used for building a 'llvm.getelementptr'.
Class used for convenient access and iteration over GEP indices.
bool isDynamicIndex(size_t index) const
Returns whether the GEP index at the given position is a dynamic index.
size_t size() const
Returns the amount of indices of the GEPOp.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
This class provides a mutable adaptor for a range of operands.
std::optional< NamedAttribute > getNamed(StringRef name) const
Return the specified named attribute if present, std::nullopt otherwise.
Attribute erase(StringAttr name)
Erase the attribute with the given name from the list.
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
NamedAttribute represents a combination of a name and an Attribute value.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
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.
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
bool wasInterrupted() const
Returns true if the walk was interrupted.
static WalkResult interrupt()
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
Builder from ArrayRef<T>.
ArrayRef< T > asArrayRef() const
A named class for passing around the variadic flag.
Value createGlobalString(Location loc, OpBuilder &builder, StringRef name, StringRef value, Linkage linkage)
Create an LLVM global containing the string "value" at the module containing surrounding the insertio...
Type getVectorType(Type elementType, unsigned numElements, bool isScalable=false)
Creates an LLVM dialect-compatible vector type with the given element type and length.
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
bool isCompatibleOuterType(Type type)
Returns true if the given outer type is compatible with the LLVM dialect without checking its potenti...
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
constexpr int kGEPConstantBitWidth
Bit-width of a 'GEPConstantIndex' within GEPArg.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
void printFunctionSignature(OpAsmPrinter &p, TypeRange argTypes, ArrayAttr argAttrs, bool isVariadic, TypeRange resultTypes, ArrayAttr resultAttrs, Region *body=nullptr, bool printEmptyResult=true)
Print a function signature for a call or callable operation.
ParseResult parseFunctionSignature(OpAsmParser &parser, SmallVectorImpl< Type > &argTypes, SmallVectorImpl< DictionaryAttr > &argAttrs, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs, bool mustParseEmptyResult=true)
Parses a function signature using parser.
void addArgAndResultAttrs(Builder &builder, OperationState &result, ArrayRef< DictionaryAttr > argAttrs, ArrayRef< DictionaryAttr > resultAttrs, StringAttr argAttrsName, StringAttr resAttrsName)
Adds argument and result attributes, provided as argAttrs and resultAttrs arguments,...
void walk(Operation *op, function_ref< void(Region *)> callback, WalkOrder order)
Walk all of the regions, blocks, or operations nested under (and including) the given operation.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
ParseResult parseFunctionSignatureWithArguments(OpAsmParser &parser, bool allowVariadic, SmallVectorImpl< OpAsmParser::Argument > &arguments, bool &isVariadic, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses a function signature using parser.
void printFunctionAttributes(OpAsmPrinter &p, Operation *op, ArrayRef< StringRef > elided={})
Prints the list of function prefixed with the "attributes" keyword.
void printFunctionSignature(OpAsmPrinter &p, FunctionOpInterface op, ArrayRef< Type > argTypes, bool isVariadic, ArrayRef< Type > resultTypes)
Prints the signature of the function-like operation op.
Operation::operand_range getIndices(Operation *op)
Get the indices that the given load/store operation is operating on.
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Value constantIndex(OpBuilder &builder, Location loc, int64_t i)
Generates a constant of index type.
Visibility
This enum describes C++ inheritance visibility.
std::string stringify(T &&t)
Generically convert a value to a std::string.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
detail::constant_int_value_binder m_ConstantInt(IntegerAttr::ValueType *bind_value)
Matches a constant holding a scalar/vector/tensor integer (splat) and writes the integer value to bin...
const FrozenRewritePatternSet GreedyRewriteConfig bool * changed
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
A callable is either a symbol, or an SSA value, that is referenced by a call-like operation.
This is the representation of an operand reference.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
T & getOrAddProperties()
Get (or create) a properties of the provided type to be set on the operation on creation.
SmallVector< Value, 4 > operands
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addSuccessors(Block *successor)
Adds a successor to the operation sate. successor must not be null.
void addTypes(ArrayRef< Type > newTypes)
Region * addRegion()
Create a region that should be attached to the operation.