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 IntegerOverflowFlags flags) {
68 auto flagsAttr = dyn_cast<IntegerOverflowFlagsAttr>(attr);
70 return emitError() <<
"expected 'overflowFlags' attribute to be an "
71 "IntegerOverflowFlagsAttr, but got "
74 flags = flagsAttr.getValue();
80 IntegerOverflowFlags &flags) {
82 flags = IntegerOverflowFlags::none;
92 std::optional<IntegerOverflowFlags> flag =
93 symbolizeIntegerOverflowFlags(kw);
96 "invalid overflow flag: expected nsw, nuw, or none");
97 flags = flags | *flag;
103 IntegerOverflowFlags flags) {
104 if (flags == IntegerOverflowFlags::none)
108 if (bitEnumContainsAny(flags, IntegerOverflowFlags::nsw))
109 strs.push_back(
"nsw");
110 if (bitEnumContainsAny(flags, IntegerOverflowFlags::nuw))
111 strs.push_back(
"nuw");
112 llvm::interleaveComma(strs, p);
125 if (attr.
getName() ==
"fastmathFlags") {
127 FastmathFlagsAttr::get(attr.getValue().getContext(), {});
132 return filteredAttrs;
145 << name <<
"' does not reference a valid LLVM function";
146 if (func.isExternal())
147 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
173 template <
typename Ty>
174 struct EnumTraits {};
176 #define REGISTER_ENUM_TYPE(Ty) \
178 struct EnumTraits<Ty> { \
179 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
180 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
193 template <
typename EnumTy,
typename RetTy = EnumTy>
196 EnumTy defaultValue) {
198 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
203 return static_cast<RetTy
>(defaultValue);
204 return static_cast<RetTy
>(index);
216 if (!operands.empty()) {
219 llvm::interleaveComma(operandTypes, p);
228 std::optional<ArrayAttr> opBundleTags) {
229 if (opBundleOperands.empty())
231 assert(opBundleTags &&
"expect operand bundle tags");
234 llvm::interleaveComma(
235 llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
237 auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
255 return p.
emitError(currentParserLoc,
"expect operand bundle tag");
266 opBundleOperands.push_back(std::move(operands));
267 opBundleOperandTypes.push_back(std::move(types));
277 ArrayAttr &opBundleTags) {
285 auto bundleParser = [&] {
305 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
306 <<
", " << getOperand(1);
308 p <<
" : " << getLhs().getType();
312 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
313 <<
", " << getOperand(1);
315 p <<
" : " << getLhs().getType();
322 template <
typename CmpPredicateType>
324 StringAttr predicateAttr;
327 SMLoc predicateLoc, trailingTypeLoc;
339 int64_t predicateValue = 0;
340 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
341 std::optional<ICmpPredicate> predicate =
342 symbolizeICmpPredicate(predicateAttr.getValue());
345 <<
"'" << predicateAttr.getValue()
346 <<
"' is an incorrect value of the 'predicate' attribute";
347 predicateValue =
static_cast<int64_t
>(*predicate);
349 std::optional<FCmpPredicate> predicate =
350 symbolizeFCmpPredicate(predicateAttr.getValue());
353 <<
"'" << predicateAttr.getValue()
354 <<
"' is an incorrect value of the 'predicate' attribute";
355 predicateValue =
static_cast<int64_t
>(*predicate);
365 "expected LLVM dialect-compatible type");
371 return parseCmpOp<ICmpPredicate>(parser, result);
375 return parseCmpOp<FCmpPredicate>(parser, result);
381 ShapedType shapedType = dyn_cast<ShapedType>(type);
388 if (getPredicate() != ICmpPredicate::eq &&
389 getPredicate() != ICmpPredicate::ne)
393 if (getLhs() == getRhs())
395 getPredicate() == ICmpPredicate::eq);
398 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
400 getPredicate() == ICmpPredicate::ne);
403 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
404 Value lhs = getLhs();
405 Value rhs = getRhs();
406 getLhsMutable().assign(rhs);
407 getRhsMutable().assign(lhs);
425 p <<
' ' << getArraySize() <<
" x " << getElemType();
426 if (getAlignment() && *getAlignment() != 0)
428 {kElemTypeAttrName, getInallocaAttrName()});
432 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
433 p <<
" : " << funcTy;
441 SMLoc trailingTypeLoc;
453 std::optional<NamedAttribute> alignmentAttr =
455 if (alignmentAttr.has_value()) {
456 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
459 "expected integer alignment");
460 if (alignmentInt.getValue().isZero())
465 auto funcType = llvm::dyn_cast<FunctionType>(type);
466 if (!funcType || funcType.getNumInputs() != 1 ||
467 funcType.getNumResults() != 1)
470 "expected trailing function type with one argument and one result");
475 Type resultType = funcType.getResult(0);
476 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
479 result.
addTypes({funcType.getResult(0)});
485 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
486 targetExtType && !targetExtType.supportsMemOps())
488 <<
"this target extension type cannot be used in alloca";
498 assert(index == 0 &&
"invalid successor index");
507 assert(index < getNumSuccessors() &&
"invalid successor index");
509 : getFalseDestOperandsMutable());
515 std::optional<std::pair<uint32_t, uint32_t>> weights) {
520 static_cast<int32_t
>(weights->second)});
522 build(builder, result, condition, trueOperands, falseOperands, weightsAttr,
523 {}, trueDest, falseDest);
537 if (!branchWeights.empty())
540 build(builder, result, value, defaultOperands, caseOperands, caseValues,
541 weightsAttr, defaultDestination, caseDestinations);
550 if (!caseValues.empty()) {
552 static_cast<int64_t
>(caseValues.size()), value.
getType());
556 build(builder, result, value, defaultDestination, defaultOperands,
557 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
566 if (!caseValues.empty()) {
568 static_cast<int64_t
>(caseValues.size()), value.
getType());
572 build(builder, result, value, defaultDestination, defaultOperands,
573 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
589 auto parseCase = [&]() {
593 values.push_back(APInt(bitWidth, value,
true));
606 caseDestinations.push_back(destination);
607 caseOperands.emplace_back(operands);
608 caseOperandTypes.emplace_back(operandTypes);
614 ShapedType caseValueType =
634 llvm::zip(caseValues, caseDestinations),
637 p << std::get<0>(i).getLimitedValue();
650 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
652 getCaseValues()->size() !=
653 static_cast<int64_t
>(getCaseDestinations().size())))
654 return emitOpError(
"expects number of case values to match number of "
655 "case destinations");
656 if (getBranchWeights() && getBranchWeights()->size() != getNumSuccessors())
657 return emitError(
"expects number of branch weights to match number of "
659 << getBranchWeights()->size() <<
" vs " << getNumSuccessors();
660 if (getCaseValues() &&
662 return emitError(
"expects case value type to match condition value type");
667 assert(index < getNumSuccessors() &&
"invalid successor index");
669 : getCaseOperandsMutable(index - 1));
676 constexpr int32_t GEPOp::kDynamicIndex;
680 getDynamicIndices());
685 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
686 return vectorType.getElementType();
687 if (
auto scalableVectorType = llvm::dyn_cast<LLVMScalableVectorType>(type))
688 return scalableVectorType.getElementType();
689 if (
auto fixedVectorType = llvm::dyn_cast<LLVMFixedVectorType>(type))
690 return fixedVectorType.getElementType();
702 for (
const GEPArg &iter : indices) {
707 bool requiresConst = !rawConstantIndices.empty() &&
708 isa_and_nonnull<LLVMStructType>(currType);
709 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
713 rawConstantIndices.push_back(intC.getSExtValue());
715 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
716 dynamicIndices.push_back(val);
719 rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
724 if (rawConstantIndices.size() == 1 || !currType)
729 .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
730 LLVMArrayType>([](
auto containerType) {
731 return containerType.getElementType();
733 .Case([&](LLVMStructType structType) ->
Type {
734 int64_t memberIndex = rawConstantIndices.back();
735 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
736 structType.getBody().size())
737 return structType.getBody()[memberIndex];
740 .Default(
Type(
nullptr));
767 build(builder, result, resultType, elementType, basePtr,
777 auto idxParser = [&]() -> ParseResult {
782 if (failed(parsedInteger.
value()))
788 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
802 llvm::interleaveComma(
805 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
808 printer << cast<IntegerAttr>(cst).getInt();
818 if (indexPos >= indices.
size())
823 .Case<LLVMStructType>([&](LLVMStructType structType) -> LogicalResult {
824 auto attr = dyn_cast<IntegerAttr>(indices[indexPos]);
826 return emitOpError() <<
"expected index " << indexPos
827 <<
" indexing a struct to be constant";
829 int32_t gepIndex = attr.getInt();
832 static_cast<size_t>(gepIndex) >= elementTypes.size())
833 return emitOpError() <<
"index " << indexPos
834 <<
" indexing a struct is out of bounds";
839 indices, emitOpError);
841 .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
842 LLVMArrayType>([&](
auto containerType) -> LogicalResult {
844 indices, emitOpError);
846 .Default([&](
auto otherType) -> LogicalResult {
848 <<
"type " << otherType <<
" cannot be indexed (index #"
861 if (
static_cast<size_t>(
862 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
863 getDynamicIndices().size())
864 return emitOpError(
"expected as many dynamic indices as specified in '")
865 << getRawConstantIndicesAttrName().getValue() <<
"'";
868 [&] {
return emitOpError(); });
875 void LoadOp::getEffects(
884 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
885 getOrdering() != AtomicOrdering::unordered)) {
896 if (!isa<IntegerType, LLVMPointerType>(type))
901 if (bitWidth.isScalable())
904 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
908 template <
typename OpTy>
911 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
914 return memOp.emitOpError(
"unsupported type ")
915 << valueType <<
" for atomic access";
916 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
917 return memOp.emitOpError(
"unsupported ordering '")
918 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
919 if (!memOp.getAlignment())
920 return memOp.emitOpError(
"expected alignment for atomic access");
923 if (memOp.getSyncscope())
924 return memOp.emitOpError(
925 "expected syncscope to be null for non-atomic access");
930 Type valueType = getResult().getType();
932 {AtomicOrdering::release, AtomicOrdering::acq_rel});
936 Value addr,
unsigned alignment,
bool isVolatile,
937 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
938 AtomicOrdering ordering, StringRef syncscope) {
939 build(builder, state, type, addr,
941 isNonTemporal, isInvariant, isInvariantGroup, ordering,
942 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
952 void StoreOp::getEffects(
961 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
962 getOrdering() != AtomicOrdering::unordered)) {
969 Type valueType = getValue().getType();
971 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
975 Value addr,
unsigned alignment,
bool isVolatile,
976 bool isNonTemporal,
bool isInvariantGroup,
977 AtomicOrdering ordering, StringRef syncscope) {
978 build(builder, state, value, addr,
980 isNonTemporal, isInvariantGroup, ordering,
981 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
983 nullptr,
nullptr,
nullptr);
993 Type resultType = calleeType.getReturnType();
994 if (!isa<LLVM::LLVMVoidType>(resultType))
995 results.push_back(resultType);
1001 return calleeType.isVarArg() ?
TypeAttr::get(calleeType) :
nullptr;
1008 if (results.empty())
1011 resultType = results.front();
1018 build(builder, state, results, builder.
getStringAttr(callee), args);
1028 assert(callee &&
"expected non-null callee in direct call builder");
1029 build(builder, state, results,
1030 nullptr, callee, args,
nullptr,
1034 nullptr,
nullptr,
nullptr,
1041 LLVMFunctionType calleeType, StringRef callee,
1043 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1047 LLVMFunctionType calleeType, StringAttr callee,
1064 nullptr,
nullptr,
nullptr);
1068 LLVMFunctionType calleeType,
ValueRange args) {
1073 nullptr,
nullptr,
nullptr,
1074 nullptr,
nullptr,
nullptr,
1082 auto calleeType = func.getFunctionType();
1086 nullptr,
nullptr,
nullptr,
1087 nullptr,
nullptr,
nullptr,
1098 return getOperand(0);
1104 auto symRef = cast<SymbolRefAttr>(callee);
1105 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1108 return setOperand(0, cast<Value>(callee));
1112 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1117 getCalleeOperands().size());
1124 if (callee.isExternal())
1126 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1130 auto hasSubprogram = [](
Operation *op) {
1135 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1137 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1139 return callOp.emitError()
1140 <<
"inlinable function call in a function with a DISubprogram "
1141 "location must have a debug location";
1147 template <
typename OpTy>
1149 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1154 if (!varCalleeType->isVarArg())
1155 return callOp.emitOpError(
1156 "expected var_callee_type to be a variadic function type");
1160 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1161 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1162 << callOp.getArgOperands().size() <<
" parameters";
1165 for (
auto [paramType, operand] :
1166 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1167 if (paramType != operand.getType())
1168 return callOp.emitOpError()
1169 <<
"var_callee_type parameter type mismatch: " << paramType
1170 <<
" != " << operand.getType();
1173 if (!callOp.getNumResults()) {
1174 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1175 return callOp.emitOpError(
"expected var_callee_type to return void");
1177 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1178 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1179 << varCalleeType->getReturnType()
1180 <<
" != " << callOp.getResult().getType();
1185 template <
typename OpType>
1188 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1190 auto isStringAttr = [](
Attribute tagAttr) {
1191 return isa<StringAttr>(tagAttr);
1193 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1194 return op.emitError(
"operand bundle tag must be a StringAttr");
1196 size_t numOpBundles = opBundleOperands.size();
1197 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1198 if (numOpBundles != numOpBundleTags)
1199 return op.emitError(
"expected ")
1200 << numOpBundles <<
" operand bundle tags, but actually got "
1216 bool isIndirect =
false;
1222 if (!getNumOperands())
1224 "must have either a `callee` attribute or at least an operand");
1225 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1227 return emitOpError(
"indirect call expects a pointer as callee: ")
1228 << getOperand(0).getType();
1235 return emitOpError()
1237 <<
"' does not reference a symbol in the current scope";
1238 auto fn = dyn_cast<LLVMFuncOp>(callee);
1240 return emitOpError() <<
"'" << calleeName.
getValue()
1241 <<
"' does not reference a valid LLVM function";
1245 fnType = fn.getFunctionType();
1248 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1250 return emitOpError(
"callee does not have a functional type: ") << fnType;
1252 if (funcType.isVarArg() && !getVarCalleeType())
1253 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1257 if (!funcType.isVarArg() &&
1258 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1259 return emitOpError() <<
"incorrect number of operands ("
1260 << (getCalleeOperands().size() - isIndirect)
1261 <<
") for callee (expecting: "
1262 << funcType.getNumParams() <<
")";
1264 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1265 return emitOpError() <<
"incorrect number of operands ("
1266 << (getCalleeOperands().size() - isIndirect)
1267 <<
") for varargs callee (expecting at least: "
1268 << funcType.getNumParams() <<
")";
1270 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1271 if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1272 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1273 << getOperand(i + isIndirect).getType()
1274 <<
" != " << funcType.getParamType(i);
1276 if (getNumResults() == 0 &&
1277 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1278 return emitOpError() <<
"expected function call to produce a value";
1280 if (getNumResults() != 0 &&
1281 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1282 return emitOpError()
1283 <<
"calling function with void result must not produce values";
1285 if (getNumResults() > 1)
1286 return emitOpError()
1287 <<
"expected LLVM function call to produce 0 or 1 result";
1289 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1290 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1291 <<
" != " << funcType.getReturnType();
1297 auto callee = getCallee();
1298 bool isDirect = callee.has_value();
1303 if (getCConv() != LLVM::CConv::C)
1304 p << stringifyCConv(getCConv()) <<
' ';
1307 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1316 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1317 p <<
'(' << args <<
')';
1320 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1321 p <<
" vararg(" << *varCalleeType <<
")";
1323 if (!getOpBundleOperands().empty()) {
1326 getOpBundleOperands().getTypes(), getOpBundleTags());
1330 {getCalleeAttrName(), getTailCallKindAttrName(),
1331 getVarCalleeTypeAttrName(), getCConvAttrName(),
1332 getOperandSegmentSizesAttrName(),
1333 getOpBundleSizesAttrName(),
1334 getOpBundleTagsAttrName()});
1338 p << getOperand(0).getType() <<
", ";
1354 if (isDirect && types.size() != 1)
1355 return parser.
emitError(trailingTypesLoc,
1356 "expected direct call to have 1 trailing type");
1357 if (!isDirect && types.size() != 2)
1358 return parser.
emitError(trailingTypesLoc,
1359 "expected indirect call to have 2 trailing types");
1361 auto funcType = llvm::dyn_cast<FunctionType>(types.pop_back_val());
1363 return parser.
emitError(trailingTypesLoc,
1364 "expected trailing function type");
1365 if (funcType.getNumResults() > 1)
1366 return parser.
emitError(trailingTypesLoc,
1367 "expected function with 0 or 1 result");
1368 if (funcType.getNumResults() == 1 &&
1369 llvm::isa<LLVM::LLVMVoidType>(funcType.getResult(0)))
1370 return parser.
emitError(trailingTypesLoc,
1371 "expected a non-void result type");
1377 llvm::append_range(types, funcType.getInputs());
1381 if (funcType.getNumResults() != 0)
1382 result.
addTypes(funcType.getResults());
1395 if (failed(*parseResult))
1396 return *parseResult;
1397 operands.push_back(funcPtrOperand);
1406 StringAttr opBundleSizesAttrName) {
1407 unsigned opBundleIndex = 0;
1408 for (
const auto &[operands, types] :
1409 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1410 if (operands.size() != types.size())
1411 return parser.
emitError(loc,
"expected ")
1413 <<
" types for operand bundle operands for operand bundle #"
1414 << opBundleIndex <<
", but actually got " << types.size();
1420 opBundleSizes.reserve(opBundleOperands.size());
1421 for (
const auto &operands : opBundleOperands)
1422 opBundleSizes.push_back(operands.size());
1425 opBundleSizesAttrName,
1437 SymbolRefAttr funcAttr;
1438 TypeAttr varCalleeType;
1442 ArrayAttr opBundleTags;
1446 getCConvAttrName(result.
name),
1448 parser, result, LLVM::CConv::C)));
1451 getTailCallKindAttrName(result.
name),
1453 parseOptionalLLVMKeyword<TailCallKind>(
1459 bool isDirect = operands.empty();
1472 StringAttr varCalleeTypeAttrName =
1473 CallOp::getVarCalleeTypeAttrName(result.
name);
1485 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1486 result && failed(*result))
1488 if (opBundleTags && !opBundleTags.empty())
1489 result.
addAttribute(CallOp::getOpBundleTagsAttrName(result.
name).getValue(),
1499 opBundleOperandTypes,
1500 getOpBundleSizesAttrName(result.
name)))
1503 int32_t numOpBundleOperands = 0;
1504 for (
const auto &operands : opBundleOperands)
1505 numOpBundleOperands += operands.size();
1508 CallOp::getOperandSegmentSizeAttr(),
1510 {
static_cast<int32_t
>(operands.size()), numOpBundleOperands}));
1514 LLVMFunctionType CallOp::getCalleeFunctionType() {
1515 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1516 return *varCalleeType;
1527 auto calleeType = func.getFunctionType();
1530 normalOps, unwindOps,
nullptr,
nullptr, {}, {}, normal, unwind);
1537 build(builder, state, tys,
1538 nullptr, callee, ops, normalOps, unwindOps,
nullptr,
1539 nullptr, {}, {}, normal, unwind);
1548 nullptr,
nullptr, {}, {}, normal, unwind);
1552 assert(index < getNumSuccessors() &&
"invalid successor index");
1554 : getUnwindDestOperandsMutable());
1562 return getOperand(0);
1568 auto symRef = cast<SymbolRefAttr>(callee);
1569 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1572 return setOperand(0, cast<Value>(callee));
1576 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1581 getCalleeOperands().size());
1588 Block *unwindDest = getUnwindDest();
1589 if (unwindDest->
empty())
1590 return emitError(
"must have at least one operation in unwind destination");
1593 if (!isa<LandingpadOp>(unwindDest->
front()))
1594 return emitError(
"first operation in unwind destination should be a "
1595 "llvm.landingpad operation");
1604 auto callee = getCallee();
1605 bool isDirect = callee.has_value();
1610 if (getCConv() != LLVM::CConv::C)
1611 p << stringifyCConv(getCConv()) <<
' ';
1619 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1626 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1627 p <<
" vararg(" << *varCalleeType <<
")";
1629 if (!getOpBundleOperands().empty()) {
1632 getOpBundleOperands().getTypes(), getOpBundleTags());
1636 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1637 getCConvAttrName(), getVarCalleeTypeAttrName(),
1638 getOpBundleSizesAttrName(),
1639 getOpBundleTagsAttrName()});
1643 p << getOperand(0).getType() <<
", ";
1645 llvm::drop_begin(getCalleeOperands().getTypes(), isDirect ? 0 : 1),
1658 SymbolRefAttr funcAttr;
1659 TypeAttr varCalleeType;
1662 ArrayAttr opBundleTags;
1663 Block *normalDest, *unwindDest;
1669 getCConvAttrName(result.
name),
1671 parser, result, LLVM::CConv::C)));
1676 bool isDirect = operands.empty();
1692 StringAttr varCalleeTypeAttrName =
1693 InvokeOp::getVarCalleeTypeAttrName(result.
name);
1705 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1706 result && failed(*result))
1708 if (opBundleTags && !opBundleTags.empty())
1710 InvokeOp::getOpBundleTagsAttrName(result.
name).getValue(),
1720 opBundleOperandTypes,
1721 getOpBundleSizesAttrName(result.
name)))
1728 int32_t numOpBundleOperands = 0;
1729 for (
const auto &operands : opBundleOperands)
1730 numOpBundleOperands += operands.size();
1733 InvokeOp::getOperandSegmentSizeAttr(),
1735 static_cast<int32_t
>(normalOperands.size()),
1736 static_cast<int32_t
>(unwindOperands.size()),
1737 numOpBundleOperands}));
1741 LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1742 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1743 return *varCalleeType;
1753 if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1754 if (!func.getPersonality())
1756 "llvm.landingpad needs to be in a function with a personality");
1762 if (!getCleanup() && getOperands().empty())
1763 return emitError(
"landingpad instruction expects at least one clause or "
1764 "cleanup attribute");
1766 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1767 value = getOperand(idx);
1768 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1775 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1778 <<
"global addresses expected as operand to "
1779 "bitcast used in clauses for landingpad";
1787 << idx <<
" is not a known constant - null, addressof, bitcast";
1794 p << (getCleanup() ?
" cleanup " :
" ");
1797 for (
auto value : getOperands()) {
1800 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1801 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1848 Type llvmType = containerType;
1850 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1858 for (int64_t idx : position) {
1859 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1860 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1861 emitError(
"position out of bounds: ") << idx;
1864 llvmType = arrayType.getElementType();
1865 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1867 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1868 emitError(
"position out of bounds: ") << idx;
1871 llvmType = structType.getBody()[idx];
1873 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1884 for (int64_t idx : position) {
1885 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1886 llvmType = structType.getBody()[idx];
1888 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1893 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1894 auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1896 while (insertValueOp) {
1897 if (getPosition() == insertValueOp.getPosition())
1898 return insertValueOp.getValue();
1900 std::min(getPosition().size(), insertValueOp.getPosition().size());
1911 if (getPosition().take_front(
min) ==
1912 insertValueOp.getPosition().take_front(
min))
1918 getContainerMutable().assign(insertValueOp.getContainer());
1919 result = getResult();
1920 insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1926 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1932 if (getRes().
getType() != valueType)
1933 return emitOpError() <<
"Type mismatch: extracting from "
1934 << getContainer().getType() <<
" should produce "
1935 << valueType <<
" but this op returns "
1936 << getRes().getType();
1942 build(builder, state,
1957 [&](StringRef msg) {
1961 return success(!!valueType);
1971 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1977 if (getValue().
getType() != valueType)
1978 return emitOpError() <<
"Type mismatch: cannot insert "
1979 << getValue().getType() <<
" into "
1980 << getContainer().getType();
1990 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
1994 Type expectedType = parent.getFunctionType().getReturnType();
1995 if (llvm::isa<LLVMVoidType>(expectedType)) {
1999 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2003 if (llvm::isa<LLVMVoidType>(expectedType))
2006 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2009 if (expectedType != getArg().
getType()) {
2011 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2025 assert(module &&
"unexpected operation outside of a module");
2030 return dyn_cast_or_null<GlobalOp>(
2035 return dyn_cast_or_null<LLVMFuncOp>(
2044 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2045 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2047 if (!global && !
function)
2049 "must reference a global defined by 'llvm.mlir.global' or 'llvm.func'");
2051 LLVMPointerType type =
getType();
2052 if (global && global.getAddrSpace() != type.getAddressSpace())
2053 return emitOpError(
"pointer address space must match address space of the "
2054 "referenced global");
2061 return getGlobalNameAttr();
2069 StringRef symName) {
2076 LogicalResult ComdatOp::verifyRegions() {
2077 Region &body = getBody();
2079 if (!isa<ComdatSelectorOp>(op))
2080 return op.emitError(
2081 "only comdat selector symbols can appear in a comdat region");
2091 bool isConstant, Linkage linkage, StringRef name,
2092 Attribute value, uint64_t alignment,
unsigned addrSpace,
2093 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2127 if (!dbgExprs.empty())
2135 p <<
' ' << stringifyLinkage(getLinkage()) <<
' ';
2136 StringRef visibility = stringifyVisibility(getVisibility_());
2137 if (!visibility.empty())
2138 p << visibility <<
' ';
2139 if (getThreadLocal_())
2140 p <<
"thread_local ";
2141 if (
auto unnamedAddr = getUnnamedAddr()) {
2142 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2150 if (
auto value = getValueOrNull())
2153 if (
auto comdat = getComdat())
2154 p <<
" comdat(" << *comdat <<
')';
2160 {SymbolTable::getSymbolAttrName(),
2161 getGlobalTypeAttrName(), getConstantAttrName(),
2162 getValueAttrName(), getLinkageAttrName(),
2163 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2164 getVisibility_AttrName(), getComdatAttrName(),
2165 getUnnamedAddrAttrName()});
2168 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2172 Region &initializer = getInitializerRegion();
2173 if (!initializer.
empty()) {
2180 std::optional<SymbolRefAttr> attr) {
2185 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2186 return op->
emitError() <<
"expected comdat symbol";
2204 ctx, parseOptionalLLVMKeyword<Linkage>(
2205 parser, result, LLVM::Linkage::External)));
2210 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2211 parser, result, LLVM::Visibility::Default)));
2216 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2242 SymbolRefAttr comdat;
2255 if (types.size() > 1)
2259 if (types.empty()) {
2260 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2263 strAttr.getValue().size());
2264 types.push_back(arrayType);
2267 "type can only be omitted for string globals");
2273 if (parseResult.
has_value() && failed(*parseResult))
2283 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2284 return intValue.getValue().isZero();
2285 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2286 return fpValue.getValue().isZero();
2287 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2289 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2291 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2298 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2299 LLVMMetadataType, LLVMLabelType>(
getType())
2300 : llvm::isa<PointerElementTypeInterface>(
getType());
2303 "expects type to be a valid element type for an LLVM global");
2305 return emitOpError(
"must appear at the module level");
2307 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2308 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2309 IntegerType elementType =
2310 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2311 if (!elementType || elementType.getWidth() != 8 ||
2312 type.getNumElements() != strAttr.getValue().size())
2314 "requires an i8 array type of the length equal to that of the string "
2318 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2319 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2320 return emitOpError()
2321 <<
"this target extension type cannot be used in a global";
2324 return emitOpError() <<
"global with target extension type can only be "
2325 "initialized with zero-initializer";
2328 if (getLinkage() == Linkage::Common) {
2329 if (
Attribute value = getValueOrNull()) {
2331 return emitOpError()
2332 <<
"expected zero value for '"
2333 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2338 if (getLinkage() == Linkage::Appending) {
2339 if (!llvm::isa<LLVMArrayType>(
getType())) {
2340 return emitOpError() <<
"expected array type for '"
2341 << stringifyLinkage(Linkage::Appending)
2349 std::optional<uint64_t> alignAttr = getAlignment();
2350 if (alignAttr.has_value()) {
2351 uint64_t value = alignAttr.value();
2352 if (!llvm::isPowerOf2_64(value))
2353 return emitError() <<
"alignment attribute is not a power of 2";
2359 LogicalResult GlobalOp::verifyRegions() {
2360 if (
Block *b = getInitializerBlock()) {
2361 ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2362 if (ret.operand_type_begin() == ret.operand_type_end())
2363 return emitOpError(
"initializer region cannot return void");
2364 if (*ret.operand_type_begin() !=
getType())
2365 return emitOpError(
"initializer region type ")
2366 << *ret.operand_type_begin() <<
" does not match global type "
2370 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2371 if (!iface || !iface.hasNoEffect())
2372 return op.emitError()
2373 <<
"ops with side effects not allowed in global initializers";
2376 if (getValueOrNull())
2377 return emitOpError(
"cannot have both initializer value and region");
2398 if (getCtors().size() != getPriorities().size())
2400 "mismatch between the number of ctors and the number of priorities");
2419 if (getDtors().size() != getPriorities().size())
2421 "mismatch between the number of dtors and the number of priorities");
2432 auto containerType = v1.
getType();
2436 build(builder, state, vType, v1, v2, mask);
2437 state.addAttributes(attrs);
2450 "expected an LLVM compatible vector type");
2462 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2463 return emitOpError(
"expected a splat operation for scalable vectors");
2473 assert(empty() &&
"function already has an entry block");
2478 LLVMFunctionType type = getFunctionType();
2479 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2480 entry->
addArgument(type.getParamType(i), getLoc());
2485 StringRef name,
Type type, LLVM::Linkage linkage,
2486 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2489 std::optional<uint64_t> functionEntryCount) {
2505 if (functionEntryCount)
2508 if (argAttrs.empty())
2511 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2512 "expected as many argument attribute lists as arguments");
2514 builder, result, argAttrs, std::nullopt,
2515 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2526 if (outputs.size() > 1) {
2527 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2528 "one function result");
2534 for (
auto t : inputs) {
2536 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2537 "type for function arguments");
2540 llvmInputs.push_back(t);
2547 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2548 "type for function results")
2566 getLinkageAttrName(result.
name),
2568 parseOptionalLLVMKeyword<Linkage>(
2569 parser, result, LLVM::Linkage::External)));
2574 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2575 parser, result, LLVM::Visibility::Default)));
2580 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2585 getCConvAttrName(result.
name),
2587 parser, result, LLVM::CConv::C)));
2589 StringAttr nameAttr;
2599 parser,
true, entryArgs, isVariadic, resultTypes,
2604 for (
auto &arg : entryArgs)
2605 argTypes.push_back(arg.type);
2615 int64_t minRange, maxRange;
2622 getVscaleRangeAttrName(result.
name),
2629 SymbolRefAttr comdat;
2640 parser.
getBuilder(), result, entryArgs, resultAttrs,
2641 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2646 return failure(parseResult.
has_value() && failed(*parseResult));
2654 if (getLinkage() != LLVM::Linkage::External)
2655 p << stringifyLinkage(getLinkage()) <<
' ';
2656 StringRef visibility = stringifyVisibility(getVisibility_());
2657 if (!visibility.empty())
2658 p << visibility <<
' ';
2659 if (
auto unnamedAddr = getUnnamedAddr()) {
2660 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2664 if (getCConv() != LLVM::CConv::C)
2665 p << stringifyCConv(getCConv()) <<
' ';
2669 LLVMFunctionType fnType = getFunctionType();
2672 argTypes.reserve(fnType.getNumParams());
2673 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
2674 argTypes.push_back(fnType.getParamType(i));
2676 Type returnType = fnType.getReturnType();
2677 if (!llvm::isa<LLVMVoidType>(returnType))
2678 resTypes.push_back(returnType);
2681 isVarArg(), resTypes);
2684 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
2685 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
2686 << vscale->getMaxRange().getInt() <<
')';
2689 if (
auto comdat = getComdat())
2690 p <<
" comdat(" << *comdat <<
')';
2694 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
2695 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
2696 getComdatAttrName(), getUnnamedAddrAttrName(),
2697 getVscaleRangeAttrName()});
2700 Region &body = getBody();
2701 if (!body.empty()) {
2713 if (getLinkage() == LLVM::Linkage::Common)
2714 return emitOpError() <<
"functions cannot have '"
2715 << stringifyLinkage(LLVM::Linkage::Common)
2722 if (getLinkage() != LLVM::Linkage::External &&
2723 getLinkage() != LLVM::Linkage::ExternWeak)
2724 return emitOpError() <<
"external functions must have '"
2725 << stringifyLinkage(LLVM::Linkage::External)
2727 << stringifyLinkage(LLVM::Linkage::ExternWeak)
2733 if (isNoInline() && isAlwaysInline())
2734 return emitError(
"no_inline and always_inline attributes are incompatible");
2736 if (isOptimizeNone() && !isNoInline())
2737 return emitOpError(
"with optimize_none must also be no_inline");
2739 Type landingpadResultTy;
2740 StringRef diagnosticMessage;
2741 bool isLandingpadTypeConsistent =
2743 const auto checkType = [&](
Type type, StringRef errorMessage) {
2744 if (!landingpadResultTy) {
2745 landingpadResultTy = type;
2748 if (landingpadResultTy != type) {
2749 diagnosticMessage = errorMessage;
2755 .Case<LandingpadOp>([&](
auto landingpad) {
2756 constexpr StringLiteral errorMessage =
2757 "'llvm.landingpad' should have a consistent result type "
2758 "inside a function";
2759 return checkType(landingpad.getType(), errorMessage);
2761 .Case<ResumeOp>([&](
auto resume) {
2762 constexpr StringLiteral errorMessage =
2763 "'llvm.resume' should have a consistent input type inside a "
2765 return checkType(resume.getValue().getType(), errorMessage);
2768 }).wasInterrupted();
2769 if (!isLandingpadTypeConsistent) {
2770 assert(!diagnosticMessage.empty() &&
2771 "Expecting a non-empty diagnostic message");
2780 LogicalResult LLVMFuncOp::verifyRegions() {
2784 unsigned numArguments = getFunctionType().getNumParams();
2785 Block &entryBlock = front();
2786 for (
unsigned i = 0; i < numArguments; ++i) {
2789 return emitOpError(
"entry block argument #")
2790 << i <<
" is not of LLVM type";
2796 Region *LLVMFuncOp::getCallableRegion() {
2825 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
2826 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
2827 return emitOpError()
2828 <<
"target extension type does not support zero-initializer";
2850 if (
auto vecType = dyn_cast<VectorType>(t))
2851 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
2852 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
2853 return arrayType.getNumElements() *
2855 if (
auto vecType = dyn_cast<LLVMFixedVectorType>(t))
2856 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
2857 assert(!isa<LLVM::LLVMScalableVectorType>(t) &&
2858 "number of elements of a scalable vector type is unknown");
2865 if (isa<LLVM::LLVMScalableVectorType>(t))
2867 if (
auto vecType = dyn_cast<VectorType>(t)) {
2868 if (vecType.isScalable())
2872 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
2874 if (
auto vecType = dyn_cast<LLVMFixedVectorType>(t))
2880 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
2881 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
2882 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
2883 !arrayType.getElementType().isInteger(8)) {
2884 return emitOpError() <<
"expected array type of "
2885 << sAttr.getValue().size()
2886 <<
" i8 elements for the string constant";
2890 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
2891 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
2893 return emitOpError() <<
"expected array attribute for a struct constant";
2897 if (arrayAttr.size() != elementTypes.size()) {
2898 return emitOpError() <<
"expected array attribute of size "
2899 << elementTypes.size();
2901 for (
auto elementTy : elementTypes) {
2902 if (!isa<IntegerType, FloatType, LLVMPPCFP128Type>(elementTy)) {
2903 return emitOpError() <<
"expected struct element types to be floating "
2904 "point type or integer type";
2908 for (
size_t i = 0; i < elementTypes.size(); ++i) {
2910 if (!isa<IntegerAttr, FloatAttr>(element)) {
2911 return emitOpError()
2912 <<
"expected struct element attribute types to be floating "
2913 "point type or integer type";
2915 auto elementType = cast<TypedAttr>(element).getType();
2916 if (elementType != elementTypes[i]) {
2917 return emitOpError()
2918 <<
"struct element at index " << i <<
" is of wrong type";
2924 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2925 return emitOpError() <<
"does not support target extension type.";
2929 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
2930 if (!llvm::isa<IntegerType>(
getType()))
2931 return emitOpError() <<
"expected integer type";
2932 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
2933 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
2934 unsigned floatWidth = APFloat::getSizeInBits(sem);
2935 if (
auto floatTy = dyn_cast<FloatType>(
getType())) {
2936 if (floatTy.getWidth() != floatWidth) {
2937 return emitOpError() <<
"expected float type of width " << floatWidth;
2942 if (isa<IntegerType>(
getType()) && !
getType().isInteger(floatWidth)) {
2943 return emitOpError() <<
"expected integer type of width " << floatWidth;
2945 }
else if (isa<ElementsAttr, ArrayAttr>(getValue())) {
2949 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
2950 if (!splatElementsAttr)
2951 return emitOpError()
2952 <<
"scalable vector type requires a splat attribute";
2955 if (!isa<VectorType, LLVM::LLVMArrayType, LLVM::LLVMFixedVectorType>(
2957 return emitOpError() <<
"expected vector or array type";
2959 int64_t attrNumElements;
2960 if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue()))
2961 attrNumElements = elementsAttr.getNumElements();
2963 attrNumElements = cast<ArrayAttr>(getValue()).size();
2965 return emitOpError()
2966 <<
"type and attribute have a different number of elements: "
2969 return emitOpError()
2970 <<
"only supports integer, float, string or elements attributes";
2976 bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
2978 auto typedAttr = dyn_cast<TypedAttr>(value);
2985 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
2990 if (isBuildableWith(value, type))
2991 return builder.
create<LLVM::ConstantOp>(loc, cast<TypedAttr>(value));
2996 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3004 AtomicOrdering ordering, StringRef syncscope,
3005 unsigned alignment,
bool isVolatile) {
3006 build(builder, state, val.
getType(), binOp, ptr, val, ordering,
3007 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3010 nullptr,
nullptr,
nullptr);
3014 auto valType = getVal().getType();
3015 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3016 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax) {
3019 return emitOpError(
"expected LLVM IR fixed vector type");
3023 "expected LLVM IR floating point type for vector element");
3025 return emitOpError(
"expected LLVM IR floating point type");
3027 }
else if (getBinOp() == AtomicBinOp::xchg) {
3030 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3032 auto intType = llvm::dyn_cast<IntegerType>(valType);
3033 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3034 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3036 return emitOpError(
"expected LLVM IR integer type");
3039 if (
static_cast<unsigned>(getOrdering()) <
3040 static_cast<unsigned>(AtomicOrdering::monotonic))
3041 return emitOpError() <<
"expected at least '"
3042 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3055 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3060 AtomicOrdering successOrdering,
3061 AtomicOrdering failureOrdering, StringRef syncscope,
3062 unsigned alignment,
bool isWeak,
bool isVolatile) {
3064 successOrdering, failureOrdering,
3065 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3067 isVolatile,
nullptr,
3068 nullptr,
nullptr,
nullptr);
3072 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3074 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3075 auto valType = getVal().getType();
3078 return emitOpError(
"unexpected LLVM IR type");
3079 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3080 getFailureOrdering() < AtomicOrdering::monotonic)
3081 return emitOpError(
"ordering must be at least 'monotonic'");
3082 if (getFailureOrdering() == AtomicOrdering::release ||
3083 getFailureOrdering() == AtomicOrdering::acq_rel)
3084 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3093 AtomicOrdering ordering, StringRef syncscope) {
3094 build(builder, state, ordering,
3095 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3099 if (getOrdering() == AtomicOrdering::not_atomic ||
3100 getOrdering() == AtomicOrdering::unordered ||
3101 getOrdering() == AtomicOrdering::monotonic)
3102 return emitOpError(
"can be given only acquire, release, acq_rel, "
3103 "and seq_cst orderings");
3113 template <
class ExtOp>
3115 IntegerType inputType, outputType;
3118 return op.emitError(
3119 "input type is a vector but output type is an integer");
3122 return op.emitError(
"input and output vectors are of incompatible shape");
3131 inputType = cast<IntegerType>(op.getArg().getType());
3132 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3134 return op.emitError(
3135 "input type is an integer but output type is a vector");
3138 if (outputType.getWidth() <= inputType.getWidth())
3139 return op.emitError(
"integer width of the output type is smaller or "
3140 "equal to the integer width of the input type");
3148 LogicalResult
ZExtOp::verify() {
return verifyExtOp<ZExtOp>(*
this); }
3151 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3155 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3163 LogicalResult
SExtOp::verify() {
return verifyExtOp<SExtOp>(*
this); }
3170 template <
typename T>
3172 typename T::FoldAdaptor adaptor) {
3174 if (castOp.getArg().getType() == castOp.getType())
3175 return castOp.getArg();
3176 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3178 if (prev.getArg().getType() == castOp.getType())
3179 return prev.getArg();
3181 castOp.getArgMutable().set(prev.getArg());
3182 return Value{castOp};
3187 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3192 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3194 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3199 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3200 return emitOpError(
"can only cast pointers from and to pointers");
3206 llvm::IsaPred<VectorType, LLVMScalableVectorType, LLVMFixedVectorType>;
3210 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3211 return emitOpError(
"cannot cast pointer to vector of pointers");
3213 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3214 return emitOpError(
"cannot cast vector of pointers to pointer");
3218 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3219 return emitOpError(
"cannot cast pointers of different address spaces, "
3220 "use 'llvm.addrspacecast' instead");
3229 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3233 Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3241 adaptor.getDynamicIndices());
3245 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
3246 if (integer.getValue().isZero())
3253 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3260 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3261 gepArgs.emplace_back(val);
3263 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
3269 gepArgs.emplace_back(integer.getInt());
3277 getDynamicIndicesMutable().assign(dynamicIndices);
3278 setRawConstantIndices(rawConstantIndices);
3279 return Value{*
this};
3285 Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3292 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3296 if (rhs.getValue().getZExtValue() >=
3297 getLhs().
getType().getIntOrFloatBitWidth())
3300 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3312 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3316 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3328 if (!getIntrin().starts_with(
"llvm."))
3329 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3337 build(builder, state,
TypeRange{}, intrin, args,
3338 FastmathFlagsAttr{},
3344 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3345 build(builder, state,
TypeRange{}, intrin, args,
3351 mlir::Type resultType, mlir::StringAttr intrin,
3353 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
3360 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3361 build(builder, state, resultTypes, intrin, args, fastMathFlags,
3375 .Case<AccessGroupAttr, AliasScopeAttr, AliasScopeDomainAttr,
3376 DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
3377 DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr,
3378 DIGlobalVariableAttr, DIGlobalVariableExpressionAttr,
3379 DIImportedEntityAttr, DILabelAttr, DILexicalBlockAttr,
3380 DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
3381 DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
3382 DISubprogramAttr, DISubroutineTypeAttr, LoopAnnotationAttr,
3383 LoopVectorizeAttr, LoopInterleaveAttr, LoopUnrollAttr,
3384 LoopUnrollAndJamAttr, LoopLICMAttr, LoopDistributeAttr,
3385 LoopPipelineAttr, LoopPeeledAttr, LoopUnswitchAttr, TBAARootAttr,
3386 TBAATagAttr, TBAATypeDescriptorAttr>([&](
auto attr) {
3387 os << decltype(attr)::getMnemonic();
3388 return AliasResult::OverridableAlias;
3402 return emitOpError(
"must appear at the module level");
3410 void InlineAsmOp::getEffects(
3413 if (getHasSideEffects()) {
3425 return build(builder, state, cond, {},
3431 ArrayRef<llvm::OperandBundleDefT<Value>> opBundles) {
3434 opBundleOperands.reserve(opBundles.size());
3435 opBundleTags.reserve(opBundles.size());
3437 for (
const llvm::OperandBundleDefT<Value> &bundle : opBundles) {
3438 opBundleOperands.emplace_back(bundle.inputs());
3439 opBundleTags.push_back(
3444 return build(builder, state, cond, opBundleOperands, opBundleTagsAttr);
3449 llvm::OperandBundleDefT<Value> opBundle(
3451 return build(builder, state, cond, opBundle);
3456 return build(builder, state, cond,
"align",
ValueRange{ptr, align});
3462 return build(builder, state, cond,
"separate_storage",
3473 auto ptrsVectorType = getPtrs().getType();
3474 Type expectedPtrsVectorType =
3479 if (ptrsVectorType != expectedPtrsVectorType)
3480 return emitOpError(
"expected operand #1 type to be ")
3481 << expectedPtrsVectorType;
3490 auto ptrsVectorType = getPtrs().getType();
3491 Type expectedPtrsVectorType =
3496 if (ptrsVectorType != expectedPtrsVectorType)
3497 return emitOpError(
"expected operand #2 type to be ")
3498 << expectedPtrsVectorType;
3506 void LLVMDialect::initialize() {
3507 registerAttributes();
3510 addTypes<LLVMVoidType,
3514 LLVMMetadataType>();
3520 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3523 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3527 allowUnknownOperations();
3529 addInterfaces<LLVMOpAsmDialectInterface>();
3531 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
3534 #define GET_OP_CLASSES
3535 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3537 #define GET_OP_CLASSES
3538 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3540 LogicalResult LLVMDialect::verifyDataLayoutString(
3544 if (maybeDataLayout)
3547 std::string message;
3548 llvm::raw_string_ostream messageStream(message);
3549 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
3550 reportError(
"invalid data layout descriptor: " + message);
3555 LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
3561 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
3563 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
3564 return verifyDataLayoutString(
3565 stringAttr.getValue(),
3566 [op](
const Twine &message) { op->emitOpError() << message.str(); });
3569 << LLVM::LLVMDialect::getDataLayoutAttrName()
3570 <<
"' to be a string attributes";
3573 LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
3581 StringAttr name = paramAttr.
getName();
3583 auto checkUnitAttrType = [&]() -> LogicalResult {
3584 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
3585 return op->
emitError() << name <<
" should be a unit attribute";
3588 auto checkTypeAttrType = [&]() -> LogicalResult {
3589 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
3590 return op->
emitError() << name <<
" should be a type attribute";
3593 auto checkIntegerAttrType = [&]() -> LogicalResult {
3594 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
3595 return op->
emitError() << name <<
" should be an integer attribute";
3598 auto checkPointerType = [&]() -> LogicalResult {
3599 if (!llvm::isa<LLVMPointerType>(paramType))
3601 << name <<
" attribute attached to non-pointer LLVM type";
3604 auto checkIntegerType = [&]() -> LogicalResult {
3605 if (!llvm::isa<IntegerType>(paramType))
3607 << name <<
" attribute attached to non-integer LLVM type";
3610 auto checkPointerTypeMatches = [&]() -> LogicalResult {
3611 if (failed(checkPointerType()))
3618 if (name == LLVMDialect::getNoAliasAttrName() ||
3619 name == LLVMDialect::getReadonlyAttrName() ||
3620 name == LLVMDialect::getReadnoneAttrName() ||
3621 name == LLVMDialect::getWriteOnlyAttrName() ||
3622 name == LLVMDialect::getNestAttrName() ||
3623 name == LLVMDialect::getNoCaptureAttrName() ||
3624 name == LLVMDialect::getNoFreeAttrName() ||
3625 name == LLVMDialect::getNonNullAttrName()) {
3626 if (failed(checkUnitAttrType()))
3628 if (verifyValueType && failed(checkPointerType()))
3634 if (name == LLVMDialect::getStructRetAttrName() ||
3635 name == LLVMDialect::getByValAttrName() ||
3636 name == LLVMDialect::getByRefAttrName() ||
3637 name == LLVMDialect::getInAllocaAttrName() ||
3638 name == LLVMDialect::getPreallocatedAttrName()) {
3639 if (failed(checkTypeAttrType()))
3641 if (verifyValueType && failed(checkPointerTypeMatches()))
3647 if (name == LLVMDialect::getSExtAttrName() ||
3648 name == LLVMDialect::getZExtAttrName()) {
3649 if (failed(checkUnitAttrType()))
3651 if (verifyValueType && failed(checkIntegerType()))
3657 if (name == LLVMDialect::getAlignAttrName() ||
3658 name == LLVMDialect::getDereferenceableAttrName() ||
3659 name == LLVMDialect::getDereferenceableOrNullAttrName() ||
3660 name == LLVMDialect::getStackAlignmentAttrName()) {
3661 if (failed(checkIntegerAttrType()))
3663 if (verifyValueType && failed(checkPointerType()))
3669 if (name == LLVMDialect::getNoUndefAttrName() ||
3670 name == LLVMDialect::getInRegAttrName() ||
3671 name == LLVMDialect::getReturnedAttrName())
3672 return checkUnitAttrType();
3678 LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
3682 auto funcOp = dyn_cast<FunctionOpInterface>(op);
3685 Type argType = funcOp.getArgumentTypes()[argIdx];
3687 return verifyParameterAttribute(op, argType, argAttr);
3690 LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
3694 auto funcOp = dyn_cast<FunctionOpInterface>(op);
3697 Type resType = funcOp.getResultTypes()[resIdx];
3701 if (llvm::isa<LLVMVoidType>(resType))
3702 return op->
emitError() <<
"cannot attach result attributes to functions "
3703 "with a void return";
3707 auto name = resAttr.
getName();
3708 if (name == LLVMDialect::getAllocAlignAttrName() ||
3709 name == LLVMDialect::getAllocatedPointerAttrName() ||
3710 name == LLVMDialect::getByValAttrName() ||
3711 name == LLVMDialect::getByRefAttrName() ||
3712 name == LLVMDialect::getInAllocaAttrName() ||
3713 name == LLVMDialect::getNestAttrName() ||
3714 name == LLVMDialect::getNoCaptureAttrName() ||
3715 name == LLVMDialect::getNoFreeAttrName() ||
3716 name == LLVMDialect::getPreallocatedAttrName() ||
3717 name == LLVMDialect::getReadnoneAttrName() ||
3718 name == LLVMDialect::getReadonlyAttrName() ||
3719 name == LLVMDialect::getReturnedAttrName() ||
3720 name == LLVMDialect::getStackAlignmentAttrName() ||
3721 name == LLVMDialect::getStructRetAttrName() ||
3722 name == LLVMDialect::getWriteOnlyAttrName())
3723 return op->
emitError() << name <<
" is not a valid result attribute";
3724 return verifyParameterAttribute(op, resType, resAttr);
3732 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
3733 if (isa<LLVM::LLVMPointerType>(type))
3734 return builder.
create<LLVM::AddressOfOp>(loc, type, symbol);
3735 if (isa<LLVM::UndefAttr>(value))
3736 return builder.
create<LLVM::UndefOp>(loc, type);
3737 if (isa<LLVM::PoisonAttr>(value))
3738 return builder.
create<LLVM::PoisonOp>(loc, type);
3739 if (isa<LLVM::ZeroAttr>(value))
3740 return builder.
create<LLVM::ZeroOp>(loc, type);
3742 return LLVM::ConstantOp::materialize(builder, value, type, loc);
3750 StringRef name, StringRef value,
3751 LLVM::Linkage linkage) {
3754 "expected builder to point to a block constrained in an op");
3757 assert(module &&
"builder points to an op outside of a module");
3763 auto global = moduleBuilder.
create<LLVM::GlobalOp>(
3764 loc, type,
true, linkage, name,
3770 builder.
create<LLVM::AddressOfOp>(loc, ptrType, global.getSymNameAttr());
3771 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 ...
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 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 void printOverflowFlags(AsmPrinter &p, Operation *op, IntegerOverflowFlags flags)
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 parseOverflowFlags(AsmParser &p, IntegerOverflowFlags &flags)
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 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 ParseResult parseCallTypeAndResolveOperands(OpAsmParser &parser, OperationState &result, bool isDirect, ArrayRef< OpAsmParser::UnresolvedOperand > operands)
Parses the type of a call operation and resolves the operands if the parsing succeeds.
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
static bool isTypeCompatibleWithAtomicOp(Type type, const DataLayout &dataLayout)
Returns true if the given type is supported by atomic operations.
static void printInsertExtractValueElementType(AsmPrinter &printer, Operation *op, Type valueType, Type containerType, DenseI64ArrayAttr position)
Nothing to print for an inferred type.
#define REGISTER_ENUM_TYPE(Ty)
static std::string diag(const llvm::Value &value)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
The possible results of an alias query.
@ NoAlias
The two locations do not alias at all.
This base class exposes generic asm parser hooks, usable across the various derived parsers.
ParseResult parseSymbolName(StringAttr &result)
Parse an -identifier and store it (without the '@' symbol) in a string attribute.
@ Paren
Parens surrounding zero or more operands.
@ None
Zero or more operands with no delimiters.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseColonTypeList(SmallVectorImpl< Type > &result)=0
Parse a colon followed by a type list, which must have at least one type.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseOptionalColonTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional colon followed by a type list, which if present must have at least one type.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
virtual ParseResult parseLess()=0
Parse a '<' token.
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 parseGreater()=0
Parse a '>' token.
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 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)
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)
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.
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.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
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 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.
void printFunctionalType(Operation *op)
Print the complete type of an operation in functional form.
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.
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class implements Optional functionality for ParseResult.
ParseResult value() const
Access the internal ParseResult value.
bool has_value() const
Returns true if we contain a valid ParseResult value.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
iterator_range< OpIterator > getOps()
This class represents a specific instance of an effect.
static DerivedEffect * get()
Returns a unique instance for the derived effect class.
This class models how operands are forwarded to block arguments in control flow.
This class implements the successor iterators for Block.
This class represents a collection of SymbolTables.
Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
This class provides an abstraction for a range of TypeRange.
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class provides an abstraction over the different types of ranges over Values.
type_range getTypes() const
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
static WalkResult advance()
static WalkResult interrupt()
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
Builder from ArrayRef<T>.
ArrayRef< T > asArrayRef() const
A named class for passing around the variadic flag.
Value createGlobalString(Location loc, OpBuilder &builder, StringRef name, StringRef value, Linkage linkage)
Create an LLVM global containing the string "value" at the module containing surrounding the insertio...
Type getVectorType(Type elementType, unsigned numElements, bool isScalable=false)
Creates an LLVM dialect-compatible vector type with the given element type and length.
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
bool isCompatibleOuterType(Type type)
Returns true if the given outer type is compatible with the LLVM dialect without checking its potenti...
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
constexpr int kGEPConstantBitWidth
Bit-width of a 'GEPConstantIndex' within GEPArg.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Type getVectorElementType(Type type)
Returns the element type of any vector type compatible with the LLVM dialect.
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)
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,...
ParseResult parseFunctionSignature(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...
Attribute convertToAttribute(MLIRContext *ctx, int64_t storage)
Convert the provided int64_t to an IntegerAttr attribute.
LogicalResult convertFromAttribute(int64_t &storage, Attribute attr, function_ref< InFlightDiagnostic()> emitError)
Convert an IntegerAttr attribute to an int64_t, or return an error if the attribute isn't an IntegerA...
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
A callable is either a symbol, or an SSA value, that is referenced by a call-like operation.
This is the representation of an operand reference.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
SmallVector< Value, 4 > operands
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addSuccessors(Block *successor)
Adds a successor to the operation sate. successor must not be null.
void addTypes(ArrayRef< Type > newTypes)
Region * addRegion()
Create a region that should be attached to the operation.