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);
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 << cst.get<IntegerAttr>().getInt();
818 if (indexPos >= indices.
size())
823 .Case<LLVMStructType>([&](LLVMStructType structType) -> LogicalResult {
824 if (!indices[indexPos].is<IntegerAttr>())
825 return emitOpError() <<
"expected index " << indexPos
826 <<
" indexing a struct to be constant";
828 int32_t gepIndex = indices[indexPos].get<IntegerAttr>().getInt();
831 static_cast<size_t>(gepIndex) >= elementTypes.size())
832 return emitOpError() <<
"index " << indexPos
833 <<
" indexing a struct is out of bounds";
838 indices, emitOpError);
840 .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
841 LLVMArrayType>([&](
auto containerType) -> LogicalResult {
843 indices, emitOpError);
845 .Default([&](
auto otherType) -> LogicalResult {
847 <<
"type " << otherType <<
" cannot be indexed (index #"
860 if (
static_cast<size_t>(
861 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
862 getDynamicIndices().size())
863 return emitOpError(
"expected as many dynamic indices as specified in '")
864 << getRawConstantIndicesAttrName().getValue() <<
"'";
867 [&] {
return emitOpError(); });
874 void LoadOp::getEffects(
883 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
884 getOrdering() != AtomicOrdering::unordered)) {
895 if (!isa<IntegerType, LLVMPointerType>(type))
900 if (bitWidth.isScalable())
903 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
907 template <
typename OpTy>
910 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
913 return memOp.emitOpError(
"unsupported type ")
914 << valueType <<
" for atomic access";
915 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
916 return memOp.emitOpError(
"unsupported ordering '")
917 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
918 if (!memOp.getAlignment())
919 return memOp.emitOpError(
"expected alignment for atomic access");
922 if (memOp.getSyncscope())
923 return memOp.emitOpError(
924 "expected syncscope to be null for non-atomic access");
929 Type valueType = getResult().getType();
931 {AtomicOrdering::release, AtomicOrdering::acq_rel});
935 Value addr,
unsigned alignment,
bool isVolatile,
936 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
937 AtomicOrdering ordering, StringRef syncscope) {
938 build(builder, state, type, addr,
940 isNonTemporal, isInvariant, isInvariantGroup, ordering,
941 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
951 void StoreOp::getEffects(
960 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
961 getOrdering() != AtomicOrdering::unordered)) {
968 Type valueType = getValue().getType();
970 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
974 Value addr,
unsigned alignment,
bool isVolatile,
975 bool isNonTemporal,
bool isInvariantGroup,
976 AtomicOrdering ordering, StringRef syncscope) {
977 build(builder, state, value, addr,
979 isNonTemporal, isInvariantGroup, ordering,
980 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
982 nullptr,
nullptr,
nullptr);
992 Type resultType = calleeType.getReturnType();
993 if (!isa<LLVM::LLVMVoidType>(resultType))
994 results.push_back(resultType);
1000 return calleeType.isVarArg() ?
TypeAttr::get(calleeType) :
nullptr;
1007 if (results.empty())
1010 resultType = results.front();
1017 build(builder, state, results, builder.
getStringAttr(callee), args);
1027 assert(callee &&
"expected non-null callee in direct call builder");
1028 build(builder, state, results,
1029 nullptr, callee, args,
nullptr,
1033 nullptr,
nullptr,
nullptr,
1040 LLVMFunctionType calleeType, StringRef callee,
1042 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1046 LLVMFunctionType calleeType, StringAttr callee,
1063 nullptr,
nullptr,
nullptr);
1067 LLVMFunctionType calleeType,
ValueRange args) {
1072 nullptr,
nullptr,
nullptr,
1073 nullptr,
nullptr,
nullptr,
1081 auto calleeType = func.getFunctionType();
1085 nullptr,
nullptr,
nullptr,
1086 nullptr,
nullptr,
nullptr,
1097 return getOperand(0);
1103 auto symRef = callee.get<SymbolRefAttr>();
1104 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1107 return setOperand(0, callee.get<
Value>());
1111 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1116 getCalleeOperands().size());
1123 if (callee.isExternal())
1125 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1129 auto hasSubprogram = [](
Operation *op) {
1134 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1136 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1138 return callOp.emitError()
1139 <<
"inlinable function call in a function with a DISubprogram "
1140 "location must have a debug location";
1146 template <
typename OpTy>
1148 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1153 if (!varCalleeType->isVarArg())
1154 return callOp.emitOpError(
1155 "expected var_callee_type to be a variadic function type");
1159 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1160 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1161 << callOp.getArgOperands().size() <<
" parameters";
1164 for (
auto [paramType, operand] :
1165 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1166 if (paramType != operand.getType())
1167 return callOp.emitOpError()
1168 <<
"var_callee_type parameter type mismatch: " << paramType
1169 <<
" != " << operand.getType();
1172 if (!callOp.getNumResults()) {
1173 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1174 return callOp.emitOpError(
"expected var_callee_type to return void");
1176 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1177 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1178 << varCalleeType->getReturnType()
1179 <<
" != " << callOp.getResult().getType();
1184 template <
typename OpType>
1187 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1189 auto isStringAttr = [](
Attribute tagAttr) {
1190 return isa<StringAttr>(tagAttr);
1192 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1193 return op.emitError(
"operand bundle tag must be a StringAttr");
1195 size_t numOpBundles = opBundleOperands.size();
1196 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1197 if (numOpBundles != numOpBundleTags)
1198 return op.emitError(
"expected ")
1199 << numOpBundles <<
" operand bundle tags, but actually got "
1215 bool isIndirect =
false;
1221 if (!getNumOperands())
1223 "must have either a `callee` attribute or at least an operand");
1224 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1226 return emitOpError(
"indirect call expects a pointer as callee: ")
1227 << getOperand(0).getType();
1234 return emitOpError()
1236 <<
"' does not reference a symbol in the current scope";
1237 auto fn = dyn_cast<LLVMFuncOp>(callee);
1239 return emitOpError() <<
"'" << calleeName.
getValue()
1240 <<
"' does not reference a valid LLVM function";
1244 fnType = fn.getFunctionType();
1247 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1249 return emitOpError(
"callee does not have a functional type: ") << fnType;
1251 if (funcType.isVarArg() && !getVarCalleeType())
1252 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1256 if (!funcType.isVarArg() &&
1257 funcType.getNumParams() != (getCalleeOperands().size() - isIndirect))
1258 return emitOpError() <<
"incorrect number of operands ("
1259 << (getCalleeOperands().size() - isIndirect)
1260 <<
") for callee (expecting: "
1261 << funcType.getNumParams() <<
")";
1263 if (funcType.getNumParams() > (getCalleeOperands().size() - isIndirect))
1264 return emitOpError() <<
"incorrect number of operands ("
1265 << (getCalleeOperands().size() - isIndirect)
1266 <<
") for varargs callee (expecting at least: "
1267 << funcType.getNumParams() <<
")";
1269 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1270 if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1271 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1272 << getOperand(i + isIndirect).getType()
1273 <<
" != " << funcType.getParamType(i);
1275 if (getNumResults() == 0 &&
1276 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1277 return emitOpError() <<
"expected function call to produce a value";
1279 if (getNumResults() != 0 &&
1280 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1281 return emitOpError()
1282 <<
"calling function with void result must not produce values";
1284 if (getNumResults() > 1)
1285 return emitOpError()
1286 <<
"expected LLVM function call to produce 0 or 1 result";
1288 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1289 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1290 <<
" != " << funcType.getReturnType();
1296 auto callee = getCallee();
1297 bool isDirect = callee.has_value();
1302 if (getCConv() != LLVM::CConv::C)
1303 p << stringifyCConv(getCConv()) <<
' ';
1306 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1315 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1316 p <<
'(' << args <<
')';
1319 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1320 p <<
" vararg(" << *varCalleeType <<
")";
1322 if (!getOpBundleOperands().empty()) {
1325 getOpBundleOperands().getTypes(), getOpBundleTags());
1329 {getCalleeAttrName(), getTailCallKindAttrName(),
1330 getVarCalleeTypeAttrName(), getCConvAttrName(),
1331 getOperandSegmentSizesAttrName(),
1332 getOpBundleSizesAttrName(),
1333 getOpBundleTagsAttrName()});
1337 p << getOperand(0).getType() <<
", ";
1353 if (isDirect && types.size() != 1)
1354 return parser.
emitError(trailingTypesLoc,
1355 "expected direct call to have 1 trailing type");
1356 if (!isDirect && types.size() != 2)
1357 return parser.
emitError(trailingTypesLoc,
1358 "expected indirect call to have 2 trailing types");
1360 auto funcType = llvm::dyn_cast<FunctionType>(types.pop_back_val());
1362 return parser.
emitError(trailingTypesLoc,
1363 "expected trailing function type");
1364 if (funcType.getNumResults() > 1)
1365 return parser.
emitError(trailingTypesLoc,
1366 "expected function with 0 or 1 result");
1367 if (funcType.getNumResults() == 1 &&
1368 llvm::isa<LLVM::LLVMVoidType>(funcType.getResult(0)))
1369 return parser.
emitError(trailingTypesLoc,
1370 "expected a non-void result type");
1376 llvm::append_range(types, funcType.getInputs());
1380 if (funcType.getNumResults() != 0)
1381 result.
addTypes(funcType.getResults());
1394 if (failed(*parseResult))
1395 return *parseResult;
1396 operands.push_back(funcPtrOperand);
1405 StringAttr opBundleSizesAttrName) {
1406 unsigned opBundleIndex = 0;
1407 for (
const auto &[operands, types] :
1408 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1409 if (operands.size() != types.size())
1410 return parser.
emitError(loc,
"expected ")
1412 <<
" types for operand bundle operands for operand bundle #"
1413 << opBundleIndex <<
", but actually got " << types.size();
1419 opBundleSizes.reserve(opBundleOperands.size());
1420 for (
const auto &operands : opBundleOperands)
1421 opBundleSizes.push_back(operands.size());
1424 opBundleSizesAttrName,
1436 SymbolRefAttr funcAttr;
1437 TypeAttr varCalleeType;
1441 ArrayAttr opBundleTags;
1445 getCConvAttrName(result.
name),
1447 parser, result, LLVM::CConv::C)));
1450 getTailCallKindAttrName(result.
name),
1452 parseOptionalLLVMKeyword<TailCallKind>(
1458 bool isDirect = operands.empty();
1471 StringAttr varCalleeTypeAttrName =
1472 CallOp::getVarCalleeTypeAttrName(result.
name);
1484 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1485 result && failed(*result))
1487 if (opBundleTags && !opBundleTags.empty())
1488 result.
addAttribute(CallOp::getOpBundleTagsAttrName(result.
name).getValue(),
1498 opBundleOperandTypes,
1499 getOpBundleSizesAttrName(result.
name)))
1502 int32_t numOpBundleOperands = 0;
1503 for (
const auto &operands : opBundleOperands)
1504 numOpBundleOperands += operands.size();
1507 CallOp::getOperandSegmentSizeAttr(),
1509 {
static_cast<int32_t
>(operands.size()), numOpBundleOperands}));
1513 LLVMFunctionType CallOp::getCalleeFunctionType() {
1514 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1515 return *varCalleeType;
1526 auto calleeType = func.getFunctionType();
1529 normalOps, unwindOps,
nullptr,
nullptr, {}, {}, normal, unwind);
1536 build(builder, state, tys,
1537 nullptr, callee, ops, normalOps, unwindOps,
nullptr,
1538 nullptr, {}, {}, normal, unwind);
1547 nullptr,
nullptr, {}, {}, normal, unwind);
1551 assert(index < getNumSuccessors() &&
"invalid successor index");
1553 : getUnwindDestOperandsMutable());
1561 return getOperand(0);
1567 auto symRef = callee.get<SymbolRefAttr>();
1568 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1571 return setOperand(0, callee.get<
Value>());
1575 return getCalleeOperands().drop_front(getCallee().has_value() ? 0 : 1);
1580 getCalleeOperands().size());
1587 Block *unwindDest = getUnwindDest();
1588 if (unwindDest->
empty())
1589 return emitError(
"must have at least one operation in unwind destination");
1592 if (!isa<LandingpadOp>(unwindDest->
front()))
1593 return emitError(
"first operation in unwind destination should be a "
1594 "llvm.landingpad operation");
1603 auto callee = getCallee();
1604 bool isDirect = callee.has_value();
1609 if (getCConv() != LLVM::CConv::C)
1610 p << stringifyCConv(getCConv()) <<
' ';
1618 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1625 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1626 p <<
" vararg(" << *varCalleeType <<
")";
1628 if (!getOpBundleOperands().empty()) {
1631 getOpBundleOperands().getTypes(), getOpBundleTags());
1635 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1636 getCConvAttrName(), getVarCalleeTypeAttrName(),
1637 getOpBundleSizesAttrName(),
1638 getOpBundleTagsAttrName()});
1642 p << getOperand(0).getType() <<
", ";
1644 llvm::drop_begin(getCalleeOperands().getTypes(), isDirect ? 0 : 1),
1657 SymbolRefAttr funcAttr;
1658 TypeAttr varCalleeType;
1661 ArrayAttr opBundleTags;
1662 Block *normalDest, *unwindDest;
1668 getCConvAttrName(result.
name),
1670 parser, result, LLVM::CConv::C)));
1675 bool isDirect = operands.empty();
1691 StringAttr varCalleeTypeAttrName =
1692 InvokeOp::getVarCalleeTypeAttrName(result.
name);
1704 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1705 result && failed(*result))
1707 if (opBundleTags && !opBundleTags.empty())
1709 InvokeOp::getOpBundleTagsAttrName(result.
name).getValue(),
1719 opBundleOperandTypes,
1720 getOpBundleSizesAttrName(result.
name)))
1727 int32_t numOpBundleOperands = 0;
1728 for (
const auto &operands : opBundleOperands)
1729 numOpBundleOperands += operands.size();
1732 InvokeOp::getOperandSegmentSizeAttr(),
1734 static_cast<int32_t
>(normalOperands.size()),
1735 static_cast<int32_t
>(unwindOperands.size()),
1736 numOpBundleOperands}));
1740 LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1741 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1742 return *varCalleeType;
1752 if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1753 if (!func.getPersonality())
1755 "llvm.landingpad needs to be in a function with a personality");
1761 if (!getCleanup() && getOperands().empty())
1762 return emitError(
"landingpad instruction expects at least one clause or "
1763 "cleanup attribute");
1765 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1766 value = getOperand(idx);
1767 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1774 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1777 <<
"global addresses expected as operand to "
1778 "bitcast used in clauses for landingpad";
1786 << idx <<
" is not a known constant - null, addressof, bitcast";
1793 p << (getCleanup() ?
" cleanup " :
" ");
1796 for (
auto value : getOperands()) {
1799 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1800 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1847 Type llvmType = containerType;
1849 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1857 for (int64_t idx : position) {
1858 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1859 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1860 emitError(
"position out of bounds: ") << idx;
1863 llvmType = arrayType.getElementType();
1864 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1866 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1867 emitError(
"position out of bounds: ") << idx;
1870 llvmType = structType.getBody()[idx];
1872 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1883 for (int64_t idx : position) {
1884 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1885 llvmType = structType.getBody()[idx];
1887 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1892 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1893 auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1895 while (insertValueOp) {
1896 if (getPosition() == insertValueOp.getPosition())
1897 return insertValueOp.getValue();
1899 std::min(getPosition().size(), insertValueOp.getPosition().size());
1910 if (getPosition().take_front(
min) ==
1911 insertValueOp.getPosition().take_front(
min))
1917 getContainerMutable().assign(insertValueOp.getContainer());
1918 result = getResult();
1919 insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1925 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1931 if (getRes().
getType() != valueType)
1932 return emitOpError() <<
"Type mismatch: extracting from "
1933 << getContainer().getType() <<
" should produce "
1934 << valueType <<
" but this op returns "
1935 << getRes().getType();
1941 build(builder, state,
1956 [&](StringRef msg) {
1960 return success(!!valueType);
1970 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1976 if (getValue().
getType() != valueType)
1977 return emitOpError() <<
"Type mismatch: cannot insert "
1978 << getValue().getType() <<
" into "
1979 << getContainer().getType();
1989 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
1993 Type expectedType = parent.getFunctionType().getReturnType();
1994 if (llvm::isa<LLVMVoidType>(expectedType)) {
1998 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2002 if (llvm::isa<LLVMVoidType>(expectedType))
2005 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2008 if (expectedType != getArg().
getType()) {
2010 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2024 assert(module &&
"unexpected operation outside of a module");
2029 return dyn_cast_or_null<GlobalOp>(
2034 return dyn_cast_or_null<LLVMFuncOp>(
2043 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2044 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2046 if (!global && !
function)
2048 "must reference a global defined by 'llvm.mlir.global' or 'llvm.func'");
2050 LLVMPointerType type =
getType();
2051 if (global && global.getAddrSpace() != type.getAddressSpace())
2052 return emitOpError(
"pointer address space must match address space of the "
2053 "referenced global");
2060 return getGlobalNameAttr();
2068 StringRef symName) {
2075 LogicalResult ComdatOp::verifyRegions() {
2076 Region &body = getBody();
2078 if (!isa<ComdatSelectorOp>(op))
2079 return op.emitError(
2080 "only comdat selector symbols can appear in a comdat region");
2090 bool isConstant, Linkage linkage, StringRef name,
2091 Attribute value, uint64_t alignment,
unsigned addrSpace,
2092 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
2126 if (!dbgExprs.empty())
2134 p <<
' ' << stringifyLinkage(getLinkage()) <<
' ';
2135 StringRef visibility = stringifyVisibility(getVisibility_());
2136 if (!visibility.empty())
2137 p << visibility <<
' ';
2138 if (getThreadLocal_())
2139 p <<
"thread_local ";
2140 if (
auto unnamedAddr = getUnnamedAddr()) {
2141 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2149 if (
auto value = getValueOrNull())
2152 if (
auto comdat = getComdat())
2153 p <<
" comdat(" << *comdat <<
')';
2159 {SymbolTable::getSymbolAttrName(),
2160 getGlobalTypeAttrName(), getConstantAttrName(),
2161 getValueAttrName(), getLinkageAttrName(),
2162 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
2163 getVisibility_AttrName(), getComdatAttrName(),
2164 getUnnamedAddrAttrName()});
2167 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2171 Region &initializer = getInitializerRegion();
2172 if (!initializer.
empty()) {
2179 std::optional<SymbolRefAttr> attr) {
2184 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2185 return op->
emitError() <<
"expected comdat symbol";
2203 ctx, parseOptionalLLVMKeyword<Linkage>(
2204 parser, result, LLVM::Linkage::External)));
2209 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2210 parser, result, LLVM::Visibility::Default)));
2215 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2241 SymbolRefAttr comdat;
2254 if (types.size() > 1)
2258 if (types.empty()) {
2259 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2262 strAttr.getValue().size());
2263 types.push_back(arrayType);
2266 "type can only be omitted for string globals");
2272 if (parseResult.
has_value() && failed(*parseResult))
2282 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2283 return intValue.getValue().isZero();
2284 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2285 return fpValue.getValue().isZero();
2286 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2288 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2290 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2297 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2298 LLVMMetadataType, LLVMLabelType>(
getType())
2299 : llvm::isa<PointerElementTypeInterface>(
getType());
2302 "expects type to be a valid element type for an LLVM global");
2304 return emitOpError(
"must appear at the module level");
2306 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2307 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2308 IntegerType elementType =
2309 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2310 if (!elementType || elementType.getWidth() != 8 ||
2311 type.getNumElements() != strAttr.getValue().size())
2313 "requires an i8 array type of the length equal to that of the string "
2317 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2318 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2319 return emitOpError()
2320 <<
"this target extension type cannot be used in a global";
2323 return emitOpError() <<
"global with target extension type can only be "
2324 "initialized with zero-initializer";
2327 if (getLinkage() == Linkage::Common) {
2328 if (
Attribute value = getValueOrNull()) {
2330 return emitOpError()
2331 <<
"expected zero value for '"
2332 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2337 if (getLinkage() == Linkage::Appending) {
2338 if (!llvm::isa<LLVMArrayType>(
getType())) {
2339 return emitOpError() <<
"expected array type for '"
2340 << stringifyLinkage(Linkage::Appending)
2348 std::optional<uint64_t> alignAttr = getAlignment();
2349 if (alignAttr.has_value()) {
2350 uint64_t value = alignAttr.value();
2351 if (!llvm::isPowerOf2_64(value))
2352 return emitError() <<
"alignment attribute is not a power of 2";
2358 LogicalResult GlobalOp::verifyRegions() {
2359 if (
Block *b = getInitializerBlock()) {
2360 ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2361 if (ret.operand_type_begin() == ret.operand_type_end())
2362 return emitOpError(
"initializer region cannot return void");
2363 if (*ret.operand_type_begin() !=
getType())
2364 return emitOpError(
"initializer region type ")
2365 << *ret.operand_type_begin() <<
" does not match global type "
2369 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2370 if (!iface || !iface.hasNoEffect())
2371 return op.emitError()
2372 <<
"ops with side effects not allowed in global initializers";
2375 if (getValueOrNull())
2376 return emitOpError(
"cannot have both initializer value and region");
2397 if (getCtors().size() != getPriorities().size())
2399 "mismatch between the number of ctors and the number of priorities");
2418 if (getDtors().size() != getPriorities().size())
2420 "mismatch between the number of dtors and the number of priorities");
2431 auto containerType = v1.
getType();
2435 build(builder, state, vType, v1, v2, mask);
2436 state.addAttributes(attrs);
2449 "expected an LLVM compatible vector type");
2461 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2462 return emitOpError(
"expected a splat operation for scalable vectors");
2472 assert(empty() &&
"function already has an entry block");
2477 LLVMFunctionType type = getFunctionType();
2478 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2479 entry->
addArgument(type.getParamType(i), getLoc());
2484 StringRef name,
Type type, LLVM::Linkage linkage,
2485 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2488 std::optional<uint64_t> functionEntryCount) {
2504 if (functionEntryCount)
2507 if (argAttrs.empty())
2510 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2511 "expected as many argument attribute lists as arguments");
2513 builder, result, argAttrs, std::nullopt,
2514 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2525 if (outputs.size() > 1) {
2526 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2527 "one function result");
2533 for (
auto t : inputs) {
2535 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2536 "type for function arguments");
2539 llvmInputs.push_back(t);
2546 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2547 "type for function results")
2565 getLinkageAttrName(result.
name),
2567 parseOptionalLLVMKeyword<Linkage>(
2568 parser, result, LLVM::Linkage::External)));
2573 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2574 parser, result, LLVM::Visibility::Default)));
2579 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2584 getCConvAttrName(result.
name),
2586 parser, result, LLVM::CConv::C)));
2588 StringAttr nameAttr;
2598 parser,
true, entryArgs, isVariadic, resultTypes,
2603 for (
auto &arg : entryArgs)
2604 argTypes.push_back(arg.type);
2614 int64_t minRange, maxRange;
2621 getVscaleRangeAttrName(result.
name),
2628 SymbolRefAttr comdat;
2639 parser.
getBuilder(), result, entryArgs, resultAttrs,
2640 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2645 return failure(parseResult.
has_value() && failed(*parseResult));
2653 if (getLinkage() != LLVM::Linkage::External)
2654 p << stringifyLinkage(getLinkage()) <<
' ';
2655 StringRef visibility = stringifyVisibility(getVisibility_());
2656 if (!visibility.empty())
2657 p << visibility <<
' ';
2658 if (
auto unnamedAddr = getUnnamedAddr()) {
2659 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2663 if (getCConv() != LLVM::CConv::C)
2664 p << stringifyCConv(getCConv()) <<
' ';
2668 LLVMFunctionType fnType = getFunctionType();
2671 argTypes.reserve(fnType.getNumParams());
2672 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
2673 argTypes.push_back(fnType.getParamType(i));
2675 Type returnType = fnType.getReturnType();
2676 if (!llvm::isa<LLVMVoidType>(returnType))
2677 resTypes.push_back(returnType);
2680 isVarArg(), resTypes);
2683 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
2684 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
2685 << vscale->getMaxRange().getInt() <<
')';
2688 if (
auto comdat = getComdat())
2689 p <<
" comdat(" << *comdat <<
')';
2693 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
2694 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
2695 getComdatAttrName(), getUnnamedAddrAttrName(),
2696 getVscaleRangeAttrName()});
2699 Region &body = getBody();
2700 if (!body.empty()) {
2712 if (getLinkage() == LLVM::Linkage::Common)
2713 return emitOpError() <<
"functions cannot have '"
2714 << stringifyLinkage(LLVM::Linkage::Common)
2721 if (getLinkage() != LLVM::Linkage::External &&
2722 getLinkage() != LLVM::Linkage::ExternWeak)
2723 return emitOpError() <<
"external functions must have '"
2724 << stringifyLinkage(LLVM::Linkage::External)
2726 << stringifyLinkage(LLVM::Linkage::ExternWeak)
2732 if (isNoInline() && isAlwaysInline())
2733 return emitError(
"no_inline and always_inline attributes are incompatible");
2735 if (isOptimizeNone() && !isNoInline())
2736 return emitOpError(
"with optimize_none must also be no_inline");
2738 Type landingpadResultTy;
2739 StringRef diagnosticMessage;
2740 bool isLandingpadTypeConsistent =
2742 const auto checkType = [&](
Type type, StringRef errorMessage) {
2743 if (!landingpadResultTy) {
2744 landingpadResultTy = type;
2747 if (landingpadResultTy != type) {
2748 diagnosticMessage = errorMessage;
2754 .Case<LandingpadOp>([&](
auto landingpad) {
2755 constexpr StringLiteral errorMessage =
2756 "'llvm.landingpad' should have a consistent result type "
2757 "inside a function";
2758 return checkType(landingpad.getType(), errorMessage);
2760 .Case<ResumeOp>([&](
auto resume) {
2761 constexpr StringLiteral errorMessage =
2762 "'llvm.resume' should have a consistent input type inside a "
2764 return checkType(resume.getValue().getType(), errorMessage);
2767 }).wasInterrupted();
2768 if (!isLandingpadTypeConsistent) {
2769 assert(!diagnosticMessage.empty() &&
2770 "Expecting a non-empty diagnostic message");
2779 LogicalResult LLVMFuncOp::verifyRegions() {
2783 unsigned numArguments = getFunctionType().getNumParams();
2784 Block &entryBlock = front();
2785 for (
unsigned i = 0; i < numArguments; ++i) {
2788 return emitOpError(
"entry block argument #")
2789 << i <<
" is not of LLVM type";
2795 Region *LLVMFuncOp::getCallableRegion() {
2824 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
2825 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
2826 return emitOpError()
2827 <<
"target extension type does not support zero-initializer";
2849 if (
auto vecType = dyn_cast<VectorType>(t))
2850 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
2851 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
2852 return arrayType.getNumElements() *
2854 if (
auto vecType = dyn_cast<LLVMFixedVectorType>(t))
2855 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
2856 assert(!isa<LLVM::LLVMScalableVectorType>(t) &&
2857 "number of elements of a scalable vector type is unknown");
2864 if (isa<LLVM::LLVMScalableVectorType>(t))
2866 if (
auto vecType = dyn_cast<VectorType>(t)) {
2867 if (vecType.isScalable())
2871 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
2873 if (
auto vecType = dyn_cast<LLVMFixedVectorType>(t))
2879 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
2880 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
2881 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
2882 !arrayType.getElementType().isInteger(8)) {
2883 return emitOpError() <<
"expected array type of "
2884 << sAttr.getValue().size()
2885 <<
" i8 elements for the string constant";
2889 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
2890 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
2892 return emitOpError() <<
"expected array attribute for a struct constant";
2896 if (arrayAttr.size() != elementTypes.size()) {
2897 return emitOpError() <<
"expected array attribute of size "
2898 << elementTypes.size();
2900 for (
auto elementTy : elementTypes) {
2901 if (!isa<IntegerType, FloatType, LLVMPPCFP128Type>(elementTy)) {
2902 return emitOpError() <<
"expected struct element types to be floating "
2903 "point type or integer type";
2907 for (
size_t i = 0; i < elementTypes.size(); ++i) {
2909 if (!isa<IntegerAttr, FloatAttr>(element)) {
2910 return emitOpError()
2911 <<
"expected struct element attribute types to be floating "
2912 "point type or integer type";
2914 auto elementType = cast<TypedAttr>(element).getType();
2915 if (elementType != elementTypes[i]) {
2916 return emitOpError()
2917 <<
"struct element at index " << i <<
" is of wrong type";
2923 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2924 return emitOpError() <<
"does not support target extension type.";
2928 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
2929 if (!llvm::isa<IntegerType>(
getType()))
2930 return emitOpError() <<
"expected integer type";
2931 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
2932 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
2933 unsigned floatWidth = APFloat::getSizeInBits(sem);
2934 if (
auto floatTy = dyn_cast<FloatType>(
getType())) {
2935 if (floatTy.getWidth() != floatWidth) {
2936 return emitOpError() <<
"expected float type of width " << floatWidth;
2941 if (isa<IntegerType>(
getType()) && !
getType().isInteger(floatWidth)) {
2942 return emitOpError() <<
"expected integer type of width " << floatWidth;
2944 }
else if (isa<ElementsAttr, ArrayAttr>(getValue())) {
2948 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
2949 if (!splatElementsAttr)
2950 return emitOpError()
2951 <<
"scalable vector type requires a splat attribute";
2954 if (!isa<VectorType, LLVM::LLVMArrayType, LLVM::LLVMFixedVectorType>(
2956 return emitOpError() <<
"expected vector or array type";
2958 int64_t attrNumElements;
2959 if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue()))
2960 attrNumElements = elementsAttr.getNumElements();
2962 attrNumElements = cast<ArrayAttr>(getValue()).size();
2964 return emitOpError()
2965 <<
"type and attribute have a different number of elements: "
2968 return emitOpError()
2969 <<
"only supports integer, float, string or elements attributes";
2975 bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
2977 auto typedAttr = dyn_cast<TypedAttr>(value);
2984 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
2989 if (isBuildableWith(value, type))
2990 return builder.
create<LLVM::ConstantOp>(loc, cast<TypedAttr>(value));
2995 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3003 AtomicOrdering ordering, StringRef syncscope,
3004 unsigned alignment,
bool isVolatile) {
3005 build(builder, state, val.
getType(), binOp, ptr, val, ordering,
3006 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3009 nullptr,
nullptr,
nullptr);
3013 auto valType = getVal().getType();
3014 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3015 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax) {
3018 return emitOpError(
"expected LLVM IR fixed vector type");
3022 "expected LLVM IR floating point type for vector element");
3024 return emitOpError(
"expected LLVM IR floating point type");
3026 }
else if (getBinOp() == AtomicBinOp::xchg) {
3029 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3031 auto intType = llvm::dyn_cast<IntegerType>(valType);
3032 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3033 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3035 return emitOpError(
"expected LLVM IR integer type");
3038 if (
static_cast<unsigned>(getOrdering()) <
3039 static_cast<unsigned>(AtomicOrdering::monotonic))
3040 return emitOpError() <<
"expected at least '"
3041 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3054 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3059 AtomicOrdering successOrdering,
3060 AtomicOrdering failureOrdering, StringRef syncscope,
3061 unsigned alignment,
bool isWeak,
bool isVolatile) {
3063 successOrdering, failureOrdering,
3064 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3066 isVolatile,
nullptr,
3067 nullptr,
nullptr,
nullptr);
3071 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3073 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3074 auto valType = getVal().getType();
3077 return emitOpError(
"unexpected LLVM IR type");
3078 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3079 getFailureOrdering() < AtomicOrdering::monotonic)
3080 return emitOpError(
"ordering must be at least 'monotonic'");
3081 if (getFailureOrdering() == AtomicOrdering::release ||
3082 getFailureOrdering() == AtomicOrdering::acq_rel)
3083 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3092 AtomicOrdering ordering, StringRef syncscope) {
3093 build(builder, state, ordering,
3094 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3098 if (getOrdering() == AtomicOrdering::not_atomic ||
3099 getOrdering() == AtomicOrdering::unordered ||
3100 getOrdering() == AtomicOrdering::monotonic)
3101 return emitOpError(
"can be given only acquire, release, acq_rel, "
3102 "and seq_cst orderings");
3112 template <
class ExtOp>
3114 IntegerType inputType, outputType;
3117 return op.emitError(
3118 "input type is a vector but output type is an integer");
3121 return op.emitError(
"input and output vectors are of incompatible shape");
3130 inputType = cast<IntegerType>(op.getArg().getType());
3131 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3133 return op.emitError(
3134 "input type is an integer but output type is a vector");
3137 if (outputType.getWidth() <= inputType.getWidth())
3138 return op.emitError(
"integer width of the output type is smaller or "
3139 "equal to the integer width of the input type");
3147 LogicalResult
ZExtOp::verify() {
return verifyExtOp<ZExtOp>(*
this); }
3150 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3154 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3162 LogicalResult
SExtOp::verify() {
return verifyExtOp<SExtOp>(*
this); }
3169 template <
typename T>
3171 typename T::FoldAdaptor adaptor) {
3173 if (castOp.getArg().getType() == castOp.getType())
3174 return castOp.getArg();
3175 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
3177 if (prev.getArg().getType() == castOp.getType())
3178 return prev.getArg();
3180 castOp.getArgMutable().set(prev.getArg());
3181 return Value{castOp};
3186 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
3191 auto resultType = llvm::dyn_cast<LLVMPointerType>(
3193 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
3198 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
3199 return emitOpError(
"can only cast pointers from and to pointers");
3205 llvm::IsaPred<VectorType, LLVMScalableVectorType, LLVMFixedVectorType>;
3209 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
3210 return emitOpError(
"cannot cast pointer to vector of pointers");
3212 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
3213 return emitOpError(
"cannot cast vector of pointers to pointer");
3217 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3218 return emitOpError(
"cannot cast pointers of different address spaces, "
3219 "use 'llvm.addrspacecast' instead");
3228 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3232 Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
3240 adaptor.getDynamicIndices());
3244 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
3245 if (integer.getValue().isZero())
3249 bool changed =
false;
3252 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3259 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3260 gepArgs.emplace_back(val);
3262 gepArgs.emplace_back(existing.get<IntegerAttr>().getInt());
3268 gepArgs.emplace_back(integer.getInt());
3276 getDynamicIndicesMutable().assign(dynamicIndices);
3277 setRawConstantIndices(rawConstantIndices);
3278 return Value{*
this};
3284 Value LLVM::GEPOp::getViewSource() {
return getBase(); }
3291 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3295 if (rhs.getValue().getZExtValue() >=
3296 getLhs().
getType().getIntOrFloatBitWidth())
3299 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3311 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3315 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3327 if (!getIntrin().starts_with(
"llvm."))
3328 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3336 build(builder, state,
TypeRange{}, intrin, args,
3337 FastmathFlagsAttr{},
3343 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3344 build(builder, state,
TypeRange{}, intrin, args,
3350 mlir::Type resultType, mlir::StringAttr intrin,
3352 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
3359 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
3360 build(builder, state, resultTypes, intrin, args, fastMathFlags,
3374 .Case<AccessGroupAttr, AliasScopeAttr, AliasScopeDomainAttr,
3375 DIBasicTypeAttr, DICommonBlockAttr, DICompileUnitAttr,
3376 DICompositeTypeAttr, DIDerivedTypeAttr, DIFileAttr,
3377 DIGlobalVariableAttr, DIGlobalVariableExpressionAttr,
3378 DIImportedEntityAttr, DILabelAttr, DILexicalBlockAttr,
3379 DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
3380 DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
3381 DISubprogramAttr, DISubroutineTypeAttr, LoopAnnotationAttr,
3382 LoopVectorizeAttr, LoopInterleaveAttr, LoopUnrollAttr,
3383 LoopUnrollAndJamAttr, LoopLICMAttr, LoopDistributeAttr,
3384 LoopPipelineAttr, LoopPeeledAttr, LoopUnswitchAttr, TBAARootAttr,
3385 TBAATagAttr, TBAATypeDescriptorAttr>([&](
auto attr) {
3386 os << decltype(attr)::getMnemonic();
3387 return AliasResult::OverridableAlias;
3401 return emitOpError(
"must appear at the module level");
3409 void InlineAsmOp::getEffects(
3412 if (getHasSideEffects()) {
3424 return build(builder, state, cond, {},
3430 ArrayRef<llvm::OperandBundleDefT<Value>> opBundles) {
3433 opBundleOperands.reserve(opBundles.size());
3434 opBundleTags.reserve(opBundles.size());
3436 for (
const llvm::OperandBundleDefT<Value> &bundle : opBundles) {
3437 opBundleOperands.emplace_back(bundle.inputs());
3438 opBundleTags.push_back(
3443 return build(builder, state, cond, opBundleOperands, opBundleTagsAttr);
3448 llvm::OperandBundleDefT<Value> opBundle(
3450 return build(builder, state, cond, opBundle);
3455 return build(builder, state, cond,
"align",
ValueRange{ptr, align});
3461 return build(builder, state, cond,
"separate_storage",
3472 auto ptrsVectorType = getPtrs().getType();
3473 Type expectedPtrsVectorType =
3478 if (ptrsVectorType != expectedPtrsVectorType)
3479 return emitOpError(
"expected operand #1 type to be ")
3480 << expectedPtrsVectorType;
3489 auto ptrsVectorType = getPtrs().getType();
3490 Type expectedPtrsVectorType =
3495 if (ptrsVectorType != expectedPtrsVectorType)
3496 return emitOpError(
"expected operand #2 type to be ")
3497 << expectedPtrsVectorType;
3505 void LLVMDialect::initialize() {
3506 registerAttributes();
3509 addTypes<LLVMVoidType,
3513 LLVMMetadataType>();
3519 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3522 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3526 allowUnknownOperations();
3528 addInterfaces<LLVMOpAsmDialectInterface>();
3530 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
3533 #define GET_OP_CLASSES
3534 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3536 #define GET_OP_CLASSES
3537 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3539 LogicalResult LLVMDialect::verifyDataLayoutString(
3543 if (maybeDataLayout)
3546 std::string message;
3547 llvm::raw_string_ostream messageStream(message);
3548 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
3549 reportError(
"invalid data layout descriptor: " + message);
3554 LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
3560 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
3562 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
3563 return verifyDataLayoutString(
3564 stringAttr.getValue(),
3565 [op](
const Twine &message) { op->emitOpError() << message.str(); });
3568 << LLVM::LLVMDialect::getDataLayoutAttrName()
3569 <<
"' to be a string attributes";
3572 LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
3580 StringAttr name = paramAttr.
getName();
3582 auto checkUnitAttrType = [&]() -> LogicalResult {
3583 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
3584 return op->
emitError() << name <<
" should be a unit attribute";
3587 auto checkTypeAttrType = [&]() -> LogicalResult {
3588 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
3589 return op->
emitError() << name <<
" should be a type attribute";
3592 auto checkIntegerAttrType = [&]() -> LogicalResult {
3593 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
3594 return op->
emitError() << name <<
" should be an integer attribute";
3597 auto checkPointerType = [&]() -> LogicalResult {
3598 if (!llvm::isa<LLVMPointerType>(paramType))
3600 << name <<
" attribute attached to non-pointer LLVM type";
3603 auto checkIntegerType = [&]() -> LogicalResult {
3604 if (!llvm::isa<IntegerType>(paramType))
3606 << name <<
" attribute attached to non-integer LLVM type";
3609 auto checkPointerTypeMatches = [&]() -> LogicalResult {
3610 if (failed(checkPointerType()))
3617 if (name == LLVMDialect::getNoAliasAttrName() ||
3618 name == LLVMDialect::getReadonlyAttrName() ||
3619 name == LLVMDialect::getReadnoneAttrName() ||
3620 name == LLVMDialect::getWriteOnlyAttrName() ||
3621 name == LLVMDialect::getNestAttrName() ||
3622 name == LLVMDialect::getNoCaptureAttrName() ||
3623 name == LLVMDialect::getNoFreeAttrName() ||
3624 name == LLVMDialect::getNonNullAttrName()) {
3625 if (failed(checkUnitAttrType()))
3627 if (verifyValueType && failed(checkPointerType()))
3633 if (name == LLVMDialect::getStructRetAttrName() ||
3634 name == LLVMDialect::getByValAttrName() ||
3635 name == LLVMDialect::getByRefAttrName() ||
3636 name == LLVMDialect::getInAllocaAttrName() ||
3637 name == LLVMDialect::getPreallocatedAttrName()) {
3638 if (failed(checkTypeAttrType()))
3640 if (verifyValueType && failed(checkPointerTypeMatches()))
3646 if (name == LLVMDialect::getSExtAttrName() ||
3647 name == LLVMDialect::getZExtAttrName()) {
3648 if (failed(checkUnitAttrType()))
3650 if (verifyValueType && failed(checkIntegerType()))
3656 if (name == LLVMDialect::getAlignAttrName() ||
3657 name == LLVMDialect::getDereferenceableAttrName() ||
3658 name == LLVMDialect::getDereferenceableOrNullAttrName() ||
3659 name == LLVMDialect::getStackAlignmentAttrName()) {
3660 if (failed(checkIntegerAttrType()))
3662 if (verifyValueType && failed(checkPointerType()))
3668 if (name == LLVMDialect::getNoUndefAttrName() ||
3669 name == LLVMDialect::getInRegAttrName() ||
3670 name == LLVMDialect::getReturnedAttrName())
3671 return checkUnitAttrType();
3677 LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
3681 auto funcOp = dyn_cast<FunctionOpInterface>(op);
3684 Type argType = funcOp.getArgumentTypes()[argIdx];
3686 return verifyParameterAttribute(op, argType, argAttr);
3689 LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
3693 auto funcOp = dyn_cast<FunctionOpInterface>(op);
3696 Type resType = funcOp.getResultTypes()[resIdx];
3700 if (llvm::isa<LLVMVoidType>(resType))
3701 return op->
emitError() <<
"cannot attach result attributes to functions "
3702 "with a void return";
3706 auto name = resAttr.
getName();
3707 if (name == LLVMDialect::getAllocAlignAttrName() ||
3708 name == LLVMDialect::getAllocatedPointerAttrName() ||
3709 name == LLVMDialect::getByValAttrName() ||
3710 name == LLVMDialect::getByRefAttrName() ||
3711 name == LLVMDialect::getInAllocaAttrName() ||
3712 name == LLVMDialect::getNestAttrName() ||
3713 name == LLVMDialect::getNoCaptureAttrName() ||
3714 name == LLVMDialect::getNoFreeAttrName() ||
3715 name == LLVMDialect::getPreallocatedAttrName() ||
3716 name == LLVMDialect::getReadnoneAttrName() ||
3717 name == LLVMDialect::getReadonlyAttrName() ||
3718 name == LLVMDialect::getReturnedAttrName() ||
3719 name == LLVMDialect::getStackAlignmentAttrName() ||
3720 name == LLVMDialect::getStructRetAttrName() ||
3721 name == LLVMDialect::getWriteOnlyAttrName())
3722 return op->
emitError() << name <<
" is not a valid result attribute";
3723 return verifyParameterAttribute(op, resType, resAttr);
3731 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
3732 if (isa<LLVM::LLVMPointerType>(type))
3733 return builder.
create<LLVM::AddressOfOp>(loc, type, symbol);
3734 if (isa<LLVM::UndefAttr>(value))
3735 return builder.
create<LLVM::UndefOp>(loc, type);
3736 if (isa<LLVM::PoisonAttr>(value))
3737 return builder.
create<LLVM::PoisonOp>(loc, type);
3738 if (isa<LLVM::ZeroAttr>(value))
3739 return builder.
create<LLVM::ZeroOp>(loc, type);
3741 return LLVM::ConstantOp::materialize(builder, value, type, loc);
3749 StringRef name, StringRef value,
3750 LLVM::Linkage linkage) {
3753 "expected builder to point to a block constrained in an op");
3756 assert(module &&
"builder points to an op outside of a module");
3762 auto global = moduleBuilder.
create<LLVM::GlobalOp>(
3763 loc, type,
true, linkage, name,
3769 builder.
create<LLVM::AddressOfOp>(loc, ptrType, global.getSymNameAttr());
3770 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.
llvm::PointerEmbeddedInt< int32_t, kGEPConstantBitWidth > GEPConstantIndex
Wrapper around a int32_t for use in a PointerUnion.
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...
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.