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;
141 DictionaryAttr attrs) {
143 if (
auto iface = dyn_cast<IntegerOverflowFlagsInterface>(op)) {
145 filteredAttrs, {iface.getOverflowFlagsAttrName()});
161 << name <<
"' does not reference a valid LLVM function";
162 if (func.isExternal())
163 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
189 template <
typename Ty>
190 struct EnumTraits {};
192 #define REGISTER_ENUM_TYPE(Ty) \
194 struct EnumTraits<Ty> { \
195 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
196 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
209 template <
typename EnumTy,
typename RetTy = EnumTy>
212 EnumTy defaultValue) {
214 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
219 return static_cast<RetTy
>(defaultValue);
220 return static_cast<RetTy
>(index);
228 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
229 <<
", " << getOperand(1);
231 p <<
" : " << getLhs().getType();
235 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
236 <<
", " << getOperand(1);
238 p <<
" : " << getLhs().getType();
245 template <
typename CmpPredicateType>
247 StringAttr predicateAttr;
250 SMLoc predicateLoc, trailingTypeLoc;
262 int64_t predicateValue = 0;
263 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
264 std::optional<ICmpPredicate> predicate =
265 symbolizeICmpPredicate(predicateAttr.getValue());
268 <<
"'" << predicateAttr.getValue()
269 <<
"' is an incorrect value of the 'predicate' attribute";
270 predicateValue =
static_cast<int64_t
>(*predicate);
272 std::optional<FCmpPredicate> predicate =
273 symbolizeFCmpPredicate(predicateAttr.getValue());
276 <<
"'" << predicateAttr.getValue()
277 <<
"' is an incorrect value of the 'predicate' attribute";
278 predicateValue =
static_cast<int64_t
>(*predicate);
288 "expected LLVM dialect-compatible type");
294 return parseCmpOp<ICmpPredicate>(parser, result);
298 return parseCmpOp<FCmpPredicate>(parser, result);
304 ShapedType shapedType = dyn_cast<ShapedType>(type);
311 if (getPredicate() != ICmpPredicate::eq &&
312 getPredicate() != ICmpPredicate::ne)
316 if (getLhs() == getRhs())
318 getPredicate() == ICmpPredicate::eq);
321 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
323 getPredicate() == ICmpPredicate::ne);
326 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
327 Value lhs = getLhs();
328 Value rhs = getRhs();
329 getLhsMutable().assign(rhs);
330 getRhsMutable().assign(lhs);
348 p <<
' ' << getArraySize() <<
" x " << getElemType();
349 if (getAlignment() && *getAlignment() != 0)
351 {kElemTypeAttrName, getInallocaAttrName()});
355 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
356 p <<
" : " << funcTy;
364 SMLoc trailingTypeLoc;
376 std::optional<NamedAttribute> alignmentAttr =
378 if (alignmentAttr.has_value()) {
379 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
382 "expected integer alignment");
383 if (alignmentInt.getValue().isZero())
388 auto funcType = llvm::dyn_cast<FunctionType>(type);
389 if (!funcType || funcType.getNumInputs() != 1 ||
390 funcType.getNumResults() != 1)
393 "expected trailing function type with one argument and one result");
398 Type resultType = funcType.getResult(0);
399 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
402 result.
addTypes({funcType.getResult(0)});
408 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
409 targetExtType && !targetExtType.supportsMemOps())
411 <<
"this target extension type cannot be used in alloca";
421 assert(index == 0 &&
"invalid successor index");
430 assert(index < getNumSuccessors() &&
"invalid successor index");
432 : getFalseDestOperandsMutable());
438 std::optional<std::pair<uint32_t, uint32_t>> weights) {
443 static_cast<int32_t
>(weights->second)});
445 build(builder, result, condition, trueOperands, falseOperands, weightsAttr,
446 {}, trueDest, falseDest);
460 if (!branchWeights.empty())
463 build(builder, result, value, defaultOperands, caseOperands, caseValues,
464 weightsAttr, defaultDestination, caseDestinations);
473 if (!caseValues.empty()) {
475 static_cast<int64_t
>(caseValues.size()), value.
getType());
479 build(builder, result, value, defaultDestination, defaultOperands,
480 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
489 if (!caseValues.empty()) {
491 static_cast<int64_t
>(caseValues.size()), value.
getType());
495 build(builder, result, value, defaultDestination, defaultOperands,
496 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
512 auto parseCase = [&]() {
516 values.push_back(APInt(bitWidth, value));
529 caseDestinations.push_back(destination);
530 caseOperands.emplace_back(operands);
531 caseOperandTypes.emplace_back(operandTypes);
537 ShapedType caseValueType =
557 llvm::zip(caseValues, caseDestinations),
560 p << std::get<0>(i).getLimitedValue();
573 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
575 getCaseValues()->size() !=
576 static_cast<int64_t
>(getCaseDestinations().size())))
577 return emitOpError(
"expects number of case values to match number of "
578 "case destinations");
579 if (getBranchWeights() && getBranchWeights()->size() != getNumSuccessors())
580 return emitError(
"expects number of branch weights to match number of "
582 << getBranchWeights()->size() <<
" vs " << getNumSuccessors();
583 if (getCaseValues() &&
585 return emitError(
"expects case value type to match condition value type");
590 assert(index < getNumSuccessors() &&
"invalid successor index");
592 : getCaseOperandsMutable(index - 1));
599 constexpr int32_t GEPOp::kDynamicIndex;
603 getDynamicIndices());
608 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
609 return vectorType.getElementType();
610 if (
auto scalableVectorType = llvm::dyn_cast<LLVMScalableVectorType>(type))
611 return scalableVectorType.getElementType();
612 if (
auto fixedVectorType = llvm::dyn_cast<LLVMFixedVectorType>(type))
613 return fixedVectorType.getElementType();
625 for (
const GEPArg &iter : indices) {
630 bool requiresConst = !rawConstantIndices.empty() &&
631 isa_and_nonnull<LLVMStructType>(currType);
632 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
636 rawConstantIndices.push_back(intC.getSExtValue());
638 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
639 dynamicIndices.push_back(val);
647 if (rawConstantIndices.size() == 1 || !currType)
652 .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
653 LLVMArrayType>([](
auto containerType) {
654 return containerType.getElementType();
657 int64_t memberIndex = rawConstantIndices.back();
658 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
660 return structType.
getBody()[memberIndex];
663 .Default(
Type(
nullptr));
690 build(builder, result, resultType, elementType, basePtr,
700 auto idxParser = [&]() -> ParseResult {
705 if (failed(parsedInteger.
value()))
711 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
725 llvm::interleaveComma(
728 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
731 printer << cst.get<IntegerAttr>().getInt();
741 if (indexPos >= indices.
size())
747 if (!indices[indexPos].is<IntegerAttr>())
748 return emitOpError() <<
"expected index " << indexPos
749 <<
" indexing a struct to be constant";
751 int32_t gepIndex = indices[indexPos].get<IntegerAttr>().getInt();
754 static_cast<size_t>(gepIndex) >= elementTypes.size())
755 return emitOpError() <<
"index " << indexPos
756 <<
" indexing a struct is out of bounds";
761 indices, emitOpError);
763 .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
764 LLVMArrayType>([&](
auto containerType) -> LogicalResult {
766 indices, emitOpError);
768 .Default([&](
auto otherType) -> LogicalResult {
770 <<
"type " << otherType <<
" cannot be indexed (index #"
783 if (
static_cast<size_t>(
784 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
785 getDynamicIndices().size())
786 return emitOpError(
"expected as many dynamic indices as specified in '")
787 << getRawConstantIndicesAttrName().getValue() <<
"'";
790 [&] {
return emitOpError(); });
797 void LoadOp::getEffects(
806 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
807 getOrdering() != AtomicOrdering::unordered)) {
818 if (!isa<IntegerType, LLVMPointerType>(type))
823 if (bitWidth.isScalable())
826 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
830 template <
typename OpTy>
833 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
836 return memOp.emitOpError(
"unsupported type ")
837 << valueType <<
" for atomic access";
838 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
839 return memOp.emitOpError(
"unsupported ordering '")
840 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
841 if (!memOp.getAlignment())
842 return memOp.emitOpError(
"expected alignment for atomic access");
845 if (memOp.getSyncscope())
846 return memOp.emitOpError(
847 "expected syncscope to be null for non-atomic access");
852 Type valueType = getResult().getType();
854 {AtomicOrdering::release, AtomicOrdering::acq_rel});
858 Value addr,
unsigned alignment,
bool isVolatile,
859 bool isNonTemporal,
bool isInvariant,
860 AtomicOrdering ordering, StringRef syncscope) {
861 build(builder, state, type, addr,
863 isNonTemporal, isInvariant, ordering,
864 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
874 void StoreOp::getEffects(
883 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
884 getOrdering() != AtomicOrdering::unordered)) {
891 Type valueType = getValue().getType();
893 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
897 Value addr,
unsigned alignment,
bool isVolatile,
898 bool isNonTemporal, AtomicOrdering ordering,
899 StringRef syncscope) {
900 build(builder, state, value, addr,
902 isNonTemporal, ordering,
903 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
905 nullptr,
nullptr,
nullptr);
915 Type resultType = calleeType.getReturnType();
916 if (!isa<LLVM::LLVMVoidType>(resultType))
917 results.push_back(resultType);
923 return calleeType.isVarArg() ?
TypeAttr::get(calleeType) :
nullptr;
933 resultType = results.front();
940 build(builder, state, results, builder.
getStringAttr(callee), args);
950 assert(callee &&
"expected non-null callee in direct call builder");
951 build(builder, state, results,
952 nullptr, callee, args,
nullptr,
956 nullptr,
nullptr,
nullptr,
962 LLVMFunctionType calleeType, StringRef callee,
964 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
968 LLVMFunctionType calleeType, StringAttr callee,
984 nullptr,
nullptr,
nullptr);
988 LLVMFunctionType calleeType,
ValueRange args) {
993 nullptr,
nullptr,
nullptr,
994 nullptr,
nullptr,
nullptr,
1001 auto calleeType = func.getFunctionType();
1005 nullptr,
nullptr,
nullptr,
1006 nullptr,
nullptr,
nullptr,
1016 return getOperand(0);
1022 auto symRef = callee.get<SymbolRefAttr>();
1023 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1026 return setOperand(0, callee.get<
Value>());
1030 return getOperands().drop_front(getCallee().has_value() ? 0 : 1);
1035 getCalleeOperands().size());
1042 if (callee.isExternal())
1044 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1048 auto hasSubprogram = [](
Operation *op) {
1053 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1055 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1057 return callOp.emitError()
1058 <<
"inlinable function call in a function with a DISubprogram "
1059 "location must have a debug location";
1065 template <
typename OpTy>
1067 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1072 if (!varCalleeType->isVarArg())
1073 return callOp.emitOpError(
1074 "expected var_callee_type to be a variadic function type");
1078 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1079 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1080 << callOp.getArgOperands().size() <<
" parameters";
1083 for (
auto [paramType, operand] :
1084 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1085 if (paramType != operand.getType())
1086 return callOp.emitOpError()
1087 <<
"var_callee_type parameter type mismatch: " << paramType
1088 <<
" != " << operand.getType();
1091 if (!callOp.getNumResults()) {
1092 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1093 return callOp.emitOpError(
"expected var_callee_type to return void");
1095 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1096 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1097 << varCalleeType->getReturnType()
1098 <<
" != " << callOp.getResult().getType();
1111 bool isIndirect =
false;
1117 if (!getNumOperands())
1119 "must have either a `callee` attribute or at least an operand");
1120 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1122 return emitOpError(
"indirect call expects a pointer as callee: ")
1123 << getOperand(0).getType();
1130 return emitOpError()
1132 <<
"' does not reference a symbol in the current scope";
1133 auto fn = dyn_cast<LLVMFuncOp>(callee);
1135 return emitOpError() <<
"'" << calleeName.
getValue()
1136 <<
"' does not reference a valid LLVM function";
1140 fnType = fn.getFunctionType();
1143 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1145 return emitOpError(
"callee does not have a functional type: ") << fnType;
1147 if (funcType.isVarArg() && !getVarCalleeType())
1148 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1152 if (!funcType.isVarArg() &&
1153 funcType.getNumParams() != (getNumOperands() - isIndirect))
1154 return emitOpError() <<
"incorrect number of operands ("
1155 << (getNumOperands() - isIndirect)
1156 <<
") for callee (expecting: "
1157 << funcType.getNumParams() <<
")";
1159 if (funcType.getNumParams() > (getNumOperands() - isIndirect))
1160 return emitOpError() <<
"incorrect number of operands ("
1161 << (getNumOperands() - isIndirect)
1162 <<
") for varargs callee (expecting at least: "
1163 << funcType.getNumParams() <<
")";
1165 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1166 if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1167 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1168 << getOperand(i + isIndirect).getType()
1169 <<
" != " << funcType.getParamType(i);
1171 if (getNumResults() == 0 &&
1172 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1173 return emitOpError() <<
"expected function call to produce a value";
1175 if (getNumResults() != 0 &&
1176 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1177 return emitOpError()
1178 <<
"calling function with void result must not produce values";
1180 if (getNumResults() > 1)
1181 return emitOpError()
1182 <<
"expected LLVM function call to produce 0 or 1 result";
1184 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1185 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1186 <<
" != " << funcType.getReturnType();
1192 auto callee = getCallee();
1193 bool isDirect = callee.has_value();
1198 if (getCConv() != LLVM::CConv::C)
1199 p << stringifyCConv(getCConv()) <<
' ';
1202 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1211 auto args = getOperands().drop_front(isDirect ? 0 : 1);
1212 p <<
'(' << args <<
')';
1215 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1216 p <<
" vararg(" << *varCalleeType <<
")";
1219 {getCalleeAttrName(), getTailCallKindAttrName(),
1220 getVarCalleeTypeAttrName(), getCConvAttrName()});
1224 p << getOperand(0).getType() <<
", ";
1240 if (isDirect && types.size() != 1)
1241 return parser.
emitError(trailingTypesLoc,
1242 "expected direct call to have 1 trailing type");
1243 if (!isDirect && types.size() != 2)
1244 return parser.
emitError(trailingTypesLoc,
1245 "expected indirect call to have 2 trailing types");
1247 auto funcType = llvm::dyn_cast<FunctionType>(types.pop_back_val());
1249 return parser.
emitError(trailingTypesLoc,
1250 "expected trailing function type");
1251 if (funcType.getNumResults() > 1)
1252 return parser.
emitError(trailingTypesLoc,
1253 "expected function with 0 or 1 result");
1254 if (funcType.getNumResults() == 1 &&
1255 llvm::isa<LLVM::LLVMVoidType>(funcType.getResult(0)))
1256 return parser.
emitError(trailingTypesLoc,
1257 "expected a non-void result type");
1263 llvm::append_range(types, funcType.getInputs());
1267 if (funcType.getNumResults() != 0)
1268 result.
addTypes(funcType.getResults());
1281 if (failed(*parseResult))
1282 return *parseResult;
1283 operands.push_back(funcPtrOperand);
1293 SymbolRefAttr funcAttr;
1294 TypeAttr varCalleeType;
1299 getCConvAttrName(result.
name),
1301 parser, result, LLVM::CConv::C)));
1304 getTailCallKindAttrName(result.
name),
1306 parseOptionalLLVMKeyword<TailCallKind>(
1312 bool isDirect = operands.empty();
1325 StringAttr varCalleeTypeAttrName =
1326 CallOp::getVarCalleeTypeAttrName(result.
name);
1343 LLVMFunctionType CallOp::getCalleeFunctionType() {
1344 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1345 return *varCalleeType;
1356 auto calleeType = func.getFunctionType();
1359 normalOps, unwindOps,
nullptr,
nullptr, normal, unwind);
1366 build(builder, state, tys,
1367 nullptr, callee, ops, normalOps, unwindOps,
nullptr,
1368 nullptr, normal, unwind);
1377 nullptr,
nullptr, normal, unwind);
1381 assert(index < getNumSuccessors() &&
"invalid successor index");
1383 : getUnwindDestOperandsMutable());
1391 return getOperand(0);
1397 auto symRef = callee.get<SymbolRefAttr>();
1398 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1401 return setOperand(0, callee.get<
Value>());
1405 return getOperands().drop_front(getCallee().has_value() ? 0 : 1);
1410 getCalleeOperands().size());
1417 Block *unwindDest = getUnwindDest();
1418 if (unwindDest->
empty())
1419 return emitError(
"must have at least one operation in unwind destination");
1422 if (!isa<LandingpadOp>(unwindDest->
front()))
1423 return emitError(
"first operation in unwind destination should be a "
1424 "llvm.landingpad operation");
1430 auto callee = getCallee();
1431 bool isDirect = callee.has_value();
1436 if (getCConv() != LLVM::CConv::C)
1437 p << stringifyCConv(getCConv()) <<
' ';
1445 p <<
'(' << getOperands().drop_front(isDirect ? 0 : 1) <<
')';
1452 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1453 p <<
" vararg(" << *varCalleeType <<
")";
1456 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1457 getCConvAttrName(), getVarCalleeTypeAttrName()});
1461 p << getOperand(0).getType() <<
", ";
1474 SymbolRefAttr funcAttr;
1475 TypeAttr varCalleeType;
1476 Block *normalDest, *unwindDest;
1482 getCConvAttrName(result.
name),
1484 parser, result, LLVM::CConv::C)));
1489 bool isDirect = operands.empty();
1505 StringAttr varCalleeTypeAttrName =
1506 InvokeOp::getVarCalleeTypeAttrName(result.
name);
1527 result.
addAttribute(InvokeOp::getOperandSegmentSizeAttr(),
1529 {static_cast<int32_t>(operands.size()),
1530 static_cast<int32_t>(normalOperands.size()),
1531 static_cast<int32_t>(unwindOperands.size())}));
1535 LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1536 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1537 return *varCalleeType;
1547 if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1548 if (!func.getPersonality())
1550 "llvm.landingpad needs to be in a function with a personality");
1556 if (!getCleanup() && getOperands().empty())
1557 return emitError(
"landingpad instruction expects at least one clause or "
1558 "cleanup attribute");
1560 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1561 value = getOperand(idx);
1562 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1569 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1572 <<
"global addresses expected as operand to "
1573 "bitcast used in clauses for landingpad";
1581 << idx <<
" is not a known constant - null, addressof, bitcast";
1588 p << (getCleanup() ?
" cleanup " :
" ");
1591 for (
auto value : getOperands()) {
1594 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1595 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1642 Type llvmType = containerType;
1644 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1652 for (int64_t idx : position) {
1653 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1654 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1655 emitError(
"position out of bounds: ") << idx;
1658 llvmType = arrayType.getElementType();
1659 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1661 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1662 emitError(
"position out of bounds: ") << idx;
1665 llvmType = structType.getBody()[idx];
1667 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1678 for (int64_t idx : position) {
1679 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1680 llvmType = structType.getBody()[idx];
1682 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1687 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1688 auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1690 while (insertValueOp) {
1691 if (getPosition() == insertValueOp.getPosition())
1692 return insertValueOp.getValue();
1694 std::min(getPosition().size(), insertValueOp.getPosition().size());
1705 if (getPosition().take_front(
min) ==
1706 insertValueOp.getPosition().take_front(
min))
1712 getContainerMutable().assign(insertValueOp.getContainer());
1713 result = getResult();
1714 insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1720 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1726 if (getRes().
getType() != valueType)
1727 return emitOpError() <<
"Type mismatch: extracting from "
1728 << getContainer().getType() <<
" should produce "
1729 << valueType <<
" but this op returns "
1730 << getRes().getType();
1736 build(builder, state,
1751 [&](StringRef msg) {
1755 return success(!!valueType);
1765 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1771 if (getValue().
getType() != valueType)
1772 return emitOpError() <<
"Type mismatch: cannot insert "
1773 << getValue().getType() <<
" into "
1774 << getContainer().getType();
1784 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
1788 Type expectedType = parent.getFunctionType().getReturnType();
1789 if (llvm::isa<LLVMVoidType>(expectedType)) {
1793 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1797 if (llvm::isa<LLVMVoidType>(expectedType))
1800 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1803 if (expectedType != getArg().
getType()) {
1805 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1819 assert(module &&
"unexpected operation outside of a module");
1824 return dyn_cast_or_null<GlobalOp>(
1829 return dyn_cast_or_null<LLVMFuncOp>(
1838 auto global = dyn_cast_or_null<GlobalOp>(symbol);
1839 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
1841 if (!global && !
function)
1843 "must reference a global defined by 'llvm.mlir.global' or 'llvm.func'");
1845 LLVMPointerType type =
getType();
1846 if (global && global.getAddrSpace() != type.getAddressSpace())
1847 return emitOpError(
"pointer address space must match address space of the "
1848 "referenced global");
1855 return getGlobalNameAttr();
1863 StringRef symName) {
1870 LogicalResult ComdatOp::verifyRegions() {
1871 Region &body = getBody();
1873 if (!isa<ComdatSelectorOp>(op))
1875 "only comdat selector symbols can appear in a comdat region");
1885 bool isConstant, Linkage linkage, StringRef name,
1886 Attribute value, uint64_t alignment,
unsigned addrSpace,
1887 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
1889 DIGlobalVariableExpressionAttr dbgExpr) {
1928 p <<
' ' << stringifyLinkage(getLinkage()) <<
' ';
1929 StringRef visibility = stringifyVisibility(getVisibility_());
1930 if (!visibility.empty())
1931 p << visibility <<
' ';
1932 if (getThreadLocal_())
1933 p <<
"thread_local ";
1934 if (
auto unnamedAddr = getUnnamedAddr()) {
1935 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
1943 if (
auto value = getValueOrNull())
1946 if (
auto comdat = getComdat())
1947 p <<
" comdat(" << *comdat <<
')';
1953 {SymbolTable::getSymbolAttrName(),
1954 getGlobalTypeAttrName(), getConstantAttrName(),
1955 getValueAttrName(), getLinkageAttrName(),
1956 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
1957 getVisibility_AttrName(), getComdatAttrName(),
1958 getUnnamedAddrAttrName()});
1961 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
1965 Region &initializer = getInitializerRegion();
1966 if (!initializer.
empty()) {
1973 std::optional<SymbolRefAttr> attr) {
1978 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
1979 return op->
emitError() <<
"expected comdat symbol";
1997 ctx, parseOptionalLLVMKeyword<Linkage>(
1998 parser, result, LLVM::Linkage::External)));
2003 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2004 parser, result, LLVM::Visibility::Default)));
2009 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2035 SymbolRefAttr comdat;
2048 if (types.size() > 1)
2052 if (types.empty()) {
2053 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2056 strAttr.getValue().size());
2057 types.push_back(arrayType);
2060 "type can only be omitted for string globals");
2066 if (parseResult.
has_value() && failed(*parseResult))
2076 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2077 return intValue.getValue().isZero();
2078 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2079 return fpValue.getValue().isZero();
2080 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2082 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2084 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2091 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2092 LLVMMetadataType, LLVMLabelType>(
getType())
2093 : llvm::isa<PointerElementTypeInterface>(
getType());
2096 "expects type to be a valid element type for an LLVM global");
2098 return emitOpError(
"must appear at the module level");
2100 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2101 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2102 IntegerType elementType =
2103 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2104 if (!elementType || elementType.getWidth() != 8 ||
2105 type.getNumElements() != strAttr.getValue().size())
2107 "requires an i8 array type of the length equal to that of the string "
2111 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2112 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2113 return emitOpError()
2114 <<
"this target extension type cannot be used in a global";
2117 return emitOpError() <<
"global with target extension type can only be "
2118 "initialized with zero-initializer";
2121 if (getLinkage() == Linkage::Common) {
2122 if (
Attribute value = getValueOrNull()) {
2124 return emitOpError()
2125 <<
"expected zero value for '"
2126 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2131 if (getLinkage() == Linkage::Appending) {
2132 if (!llvm::isa<LLVMArrayType>(
getType())) {
2133 return emitOpError() <<
"expected array type for '"
2134 << stringifyLinkage(Linkage::Appending)
2142 std::optional<uint64_t> alignAttr = getAlignment();
2143 if (alignAttr.has_value()) {
2144 uint64_t value = alignAttr.value();
2145 if (!llvm::isPowerOf2_64(value))
2146 return emitError() <<
"alignment attribute is not a power of 2";
2152 LogicalResult GlobalOp::verifyRegions() {
2153 if (
Block *b = getInitializerBlock()) {
2154 ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2155 if (ret.operand_type_begin() == ret.operand_type_end())
2156 return emitOpError(
"initializer region cannot return void");
2157 if (*ret.operand_type_begin() !=
getType())
2158 return emitOpError(
"initializer region type ")
2159 << *ret.operand_type_begin() <<
" does not match global type "
2163 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2164 if (!iface || !iface.hasNoEffect())
2166 <<
"ops with side effects not allowed in global initializers";
2169 if (getValueOrNull())
2170 return emitOpError(
"cannot have both initializer value and region");
2191 if (getCtors().size() != getPriorities().size())
2193 "mismatch between the number of ctors and the number of priorities");
2212 if (getDtors().size() != getPriorities().size())
2214 "mismatch between the number of dtors and the number of priorities");
2225 auto containerType = v1.
getType();
2229 build(builder, state, vType, v1, v2, mask);
2230 state.addAttributes(attrs);
2243 "expected an LLVM compatible vector type");
2255 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2256 return emitOpError(
"expected a splat operation for scalable vectors");
2266 assert(empty() &&
"function already has an entry block");
2271 LLVMFunctionType type = getFunctionType();
2272 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2273 entry->
addArgument(type.getParamType(i), getLoc());
2278 StringRef name,
Type type, LLVM::Linkage linkage,
2279 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2282 std::optional<uint64_t> functionEntryCount) {
2298 if (functionEntryCount)
2301 if (argAttrs.empty())
2304 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2305 "expected as many argument attribute lists as arguments");
2307 builder, result, argAttrs, std::nullopt,
2308 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2319 if (outputs.size() > 1) {
2320 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2321 "one function result");
2327 for (
auto t : inputs) {
2329 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2330 "type for function arguments");
2333 llvmInputs.push_back(t);
2340 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2341 "type for function results")
2359 getLinkageAttrName(result.
name),
2361 parseOptionalLLVMKeyword<Linkage>(
2362 parser, result, LLVM::Linkage::External)));
2367 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2368 parser, result, LLVM::Visibility::Default)));
2373 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2378 getCConvAttrName(result.
name),
2380 parser, result, LLVM::CConv::C)));
2382 StringAttr nameAttr;
2392 parser,
true, entryArgs, isVariadic, resultTypes,
2397 for (
auto &arg : entryArgs)
2398 argTypes.push_back(arg.type);
2408 int64_t minRange, maxRange;
2415 getVscaleRangeAttrName(result.
name),
2422 SymbolRefAttr comdat;
2433 parser.
getBuilder(), result, entryArgs, resultAttrs,
2434 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2439 return failure(parseResult.
has_value() && failed(*parseResult));
2447 if (getLinkage() != LLVM::Linkage::External)
2448 p << stringifyLinkage(getLinkage()) <<
' ';
2449 StringRef visibility = stringifyVisibility(getVisibility_());
2450 if (!visibility.empty())
2451 p << visibility <<
' ';
2452 if (
auto unnamedAddr = getUnnamedAddr()) {
2453 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2457 if (getCConv() != LLVM::CConv::C)
2458 p << stringifyCConv(getCConv()) <<
' ';
2462 LLVMFunctionType fnType = getFunctionType();
2465 argTypes.reserve(fnType.getNumParams());
2466 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
2467 argTypes.push_back(fnType.getParamType(i));
2469 Type returnType = fnType.getReturnType();
2470 if (!llvm::isa<LLVMVoidType>(returnType))
2471 resTypes.push_back(returnType);
2474 isVarArg(), resTypes);
2477 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
2478 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
2479 << vscale->getMaxRange().getInt() <<
')';
2482 if (
auto comdat = getComdat())
2483 p <<
" comdat(" << *comdat <<
')';
2487 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
2488 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
2489 getComdatAttrName(), getUnnamedAddrAttrName(),
2490 getVscaleRangeAttrName()});
2493 Region &body = getBody();
2494 if (!body.empty()) {
2506 if (getLinkage() == LLVM::Linkage::Common)
2507 return emitOpError() <<
"functions cannot have '"
2508 << stringifyLinkage(LLVM::Linkage::Common)
2515 if (getLinkage() != LLVM::Linkage::External &&
2516 getLinkage() != LLVM::Linkage::ExternWeak)
2517 return emitOpError() <<
"external functions must have '"
2518 << stringifyLinkage(LLVM::Linkage::External)
2520 << stringifyLinkage(LLVM::Linkage::ExternWeak)
2526 if (isNoInline() && isAlwaysInline())
2527 return emitError(
"no_inline and always_inline attributes are incompatible");
2529 if (isOptimizeNone() && !isNoInline())
2530 return emitOpError(
"with optimize_none must also be no_inline");
2532 Type landingpadResultTy;
2533 StringRef diagnosticMessage;
2534 bool isLandingpadTypeConsistent =
2536 const auto checkType = [&](
Type type, StringRef errorMessage) {
2537 if (!landingpadResultTy) {
2538 landingpadResultTy = type;
2541 if (landingpadResultTy != type) {
2542 diagnosticMessage = errorMessage;
2548 .Case<LandingpadOp>([&](
auto landingpad) {
2549 constexpr StringLiteral errorMessage =
2550 "'llvm.landingpad' should have a consistent result type "
2551 "inside a function";
2552 return checkType(landingpad.getType(), errorMessage);
2554 .Case<ResumeOp>([&](
auto resume) {
2555 constexpr StringLiteral errorMessage =
2556 "'llvm.resume' should have a consistent input type inside a "
2558 return checkType(resume.getValue().getType(), errorMessage);
2561 }).wasInterrupted();
2562 if (!isLandingpadTypeConsistent) {
2563 assert(!diagnosticMessage.empty() &&
2564 "Expecting a non-empty diagnostic message");
2573 LogicalResult LLVMFuncOp::verifyRegions() {
2577 unsigned numArguments = getFunctionType().getNumParams();
2578 Block &entryBlock = front();
2579 for (
unsigned i = 0; i < numArguments; ++i) {
2582 return emitOpError(
"entry block argument #")
2583 << i <<
" is not of LLVM type";
2589 Region *LLVMFuncOp::getCallableRegion() {
2618 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
2619 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
2620 return emitOpError()
2621 <<
"target extension type does not support zero-initializer";
2643 if (
auto vecType = dyn_cast<VectorType>(t))
2644 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
2645 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
2646 return arrayType.getNumElements() *
2648 if (
auto vecType = dyn_cast<LLVMFixedVectorType>(t))
2649 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
2650 assert(!isa<LLVM::LLVMScalableVectorType>(t) &&
2651 "number of elements of a scalable vector type is unknown");
2658 if (isa<LLVM::LLVMScalableVectorType>(t))
2660 if (
auto vecType = dyn_cast<VectorType>(t)) {
2661 if (vecType.isScalable())
2665 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
2667 if (
auto vecType = dyn_cast<LLVMFixedVectorType>(t))
2673 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
2674 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
2675 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
2676 !arrayType.getElementType().isInteger(8)) {
2677 return emitOpError() <<
"expected array type of "
2678 << sAttr.getValue().size()
2679 <<
" i8 elements for the string constant";
2683 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
2684 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
2686 return emitOpError() <<
"expected array attribute for a struct constant";
2690 if (arrayAttr.size() != elementTypes.size()) {
2691 return emitOpError() <<
"expected array attribute of size "
2692 << elementTypes.size();
2694 for (
auto elementTy : elementTypes) {
2695 if (!isa<IntegerType, FloatType, LLVMPPCFP128Type>(elementTy)) {
2696 return emitOpError() <<
"expected struct element types to be floating "
2697 "point type or integer type";
2701 for (
size_t i = 0; i < elementTypes.size(); ++i) {
2703 if (!isa<IntegerAttr, FloatAttr>(element)) {
2704 return emitOpError()
2705 <<
"expected struct element attribute types to be floating "
2706 "point type or integer type";
2708 auto elementType = cast<TypedAttr>(element).getType();
2709 if (elementType != elementTypes[i]) {
2710 return emitOpError()
2711 <<
"struct element at index " << i <<
" is of wrong type";
2717 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2718 return emitOpError() <<
"does not support target extension type.";
2722 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
2723 if (!llvm::isa<IntegerType>(
getType()))
2724 return emitOpError() <<
"expected integer type";
2725 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
2726 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
2727 unsigned floatWidth = APFloat::getSizeInBits(sem);
2728 if (
auto floatTy = dyn_cast<FloatType>(
getType())) {
2729 if (floatTy.getWidth() != floatWidth) {
2730 return emitOpError() <<
"expected float type of width " << floatWidth;
2735 if (isa<IntegerType>(
getType()) && !
getType().isInteger(floatWidth)) {
2736 return emitOpError() <<
"expected integer type of width " << floatWidth;
2738 }
else if (isa<ElementsAttr, ArrayAttr>(getValue())) {
2742 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
2743 if (!splatElementsAttr)
2744 return emitOpError()
2745 <<
"scalable vector type requires a splat attribute";
2748 if (!isa<VectorType, LLVM::LLVMArrayType, LLVM::LLVMFixedVectorType>(
2750 return emitOpError() <<
"expected vector or array type";
2752 int64_t attrNumElements;
2753 if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue()))
2754 attrNumElements = elementsAttr.getNumElements();
2756 attrNumElements = cast<ArrayAttr>(getValue()).size();
2758 return emitOpError()
2759 <<
"type and attribute have a different number of elements: "
2762 return emitOpError()
2763 <<
"only supports integer, float, string or elements attributes";
2769 bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
2771 auto typedAttr = dyn_cast<TypedAttr>(value);
2778 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
2783 if (isBuildableWith(value, type))
2784 return builder.
create<LLVM::ConstantOp>(loc, cast<TypedAttr>(value));
2789 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
2797 AtomicOrdering ordering, StringRef syncscope,
2798 unsigned alignment,
bool isVolatile) {
2799 build(builder, state, val.
getType(), binOp, ptr, val, ordering,
2800 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
2803 nullptr,
nullptr,
nullptr);
2807 auto valType = getVal().getType();
2808 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
2809 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax) {
2811 return emitOpError(
"expected LLVM IR floating point type");
2812 }
else if (getBinOp() == AtomicBinOp::xchg) {
2815 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
2817 auto intType = llvm::dyn_cast<IntegerType>(valType);
2818 unsigned intBitWidth = intType ? intType.getWidth() : 0;
2819 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
2821 return emitOpError(
"expected LLVM IR integer type");
2824 if (
static_cast<unsigned>(getOrdering()) <
2825 static_cast<unsigned>(AtomicOrdering::monotonic))
2826 return emitOpError() <<
"expected at least '"
2827 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
2840 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
2845 AtomicOrdering successOrdering,
2846 AtomicOrdering failureOrdering, StringRef syncscope,
2847 unsigned alignment,
bool isWeak,
bool isVolatile) {
2849 successOrdering, failureOrdering,
2850 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
2852 isVolatile,
nullptr,
2853 nullptr,
nullptr,
nullptr);
2857 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
2859 return emitOpError(
"expected LLVM IR pointer type for operand #0");
2860 auto valType = getVal().getType();
2863 return emitOpError(
"unexpected LLVM IR type");
2864 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
2865 getFailureOrdering() < AtomicOrdering::monotonic)
2866 return emitOpError(
"ordering must be at least 'monotonic'");
2867 if (getFailureOrdering() == AtomicOrdering::release ||
2868 getFailureOrdering() == AtomicOrdering::acq_rel)
2869 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
2878 AtomicOrdering ordering, StringRef syncscope) {
2879 build(builder, state, ordering,
2880 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
2884 if (getOrdering() == AtomicOrdering::not_atomic ||
2885 getOrdering() == AtomicOrdering::unordered ||
2886 getOrdering() == AtomicOrdering::monotonic)
2887 return emitOpError(
"can be given only acquire, release, acq_rel, "
2888 "and seq_cst orderings");
2898 template <
class ExtOp>
2900 IntegerType inputType, outputType;
2904 "input type is a vector but output type is an integer");
2907 return op.
emitError(
"input and output vectors are of incompatible shape");
2916 inputType = cast<IntegerType>(op.getArg().getType());
2920 "input type is an integer but output type is a vector");
2923 if (outputType.getWidth() <= inputType.getWidth())
2924 return op.
emitError(
"integer width of the output type is smaller or "
2925 "equal to the integer width of the input type");
2933 LogicalResult
ZExtOp::verify() {
return verifyExtOp<ZExtOp>(*
this); }
2936 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
2940 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
2948 LogicalResult
SExtOp::verify() {
return verifyExtOp<SExtOp>(*
this); }
2955 template <
typename T>
2957 typename T::FoldAdaptor adaptor) {
2959 if (castOp.getArg().getType() == castOp.getType())
2960 return castOp.getArg();
2961 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
2963 if (prev.getArg().getType() == castOp.getType())
2964 return prev.getArg();
2966 castOp.getArgMutable().set(prev.getArg());
2967 return Value{castOp};
2972 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
2977 auto resultType = llvm::dyn_cast<LLVMPointerType>(
2979 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
2984 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
2985 return emitOpError(
"can only cast pointers from and to pointers");
2991 llvm::IsaPred<VectorType, LLVMScalableVectorType, LLVMFixedVectorType>;
2995 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
2996 return emitOpError(
"cannot cast pointer to vector of pointers");
2998 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
2999 return emitOpError(
"cannot cast vector of pointers to pointer");
3003 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
3004 return emitOpError(
"cannot cast pointers of different address spaces, "
3005 "use 'llvm.addrspacecast' instead");
3014 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
3024 adaptor.getDynamicIndices());
3028 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
3029 if (integer.getValue().isZero())
3033 bool changed =
false;
3036 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3043 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3044 gepArgs.emplace_back(val);
3046 gepArgs.emplace_back(existing.get<IntegerAttr>().getInt());
3052 gepArgs.emplace_back(integer.getInt());
3060 getDynamicIndicesMutable().assign(dynamicIndices);
3061 setRawConstantIndices(rawConstantIndices);
3062 return Value{*
this};
3073 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3077 if (rhs.getValue().getZExtValue() >=
3078 getLhs().
getType().getIntOrFloatBitWidth())
3081 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3093 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3097 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3109 if (!getIntrin().starts_with(
"llvm."))
3110 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3124 .Case<AccessGroupAttr, AliasScopeAttr, AliasScopeDomainAttr,
3125 DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
3126 DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
3127 DIGlobalVariableExpressionAttr, DIImportedEntityAttr, DILabelAttr,
3128 DILexicalBlockAttr, DILexicalBlockFileAttr, DILocalVariableAttr,
3129 DIModuleAttr, DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
3130 DISubprogramAttr, DISubroutineTypeAttr, LoopAnnotationAttr,
3131 LoopVectorizeAttr, LoopInterleaveAttr, LoopUnrollAttr,
3132 LoopUnrollAndJamAttr, LoopLICMAttr, LoopDistributeAttr,
3133 LoopPipelineAttr, LoopPeeledAttr, LoopUnswitchAttr, TBAARootAttr,
3134 TBAATagAttr, TBAATypeDescriptorAttr>([&](
auto attr) {
3135 os << decltype(attr)::getMnemonic();
3136 return AliasResult::OverridableAlias;
3150 return emitOpError(
"must appear at the module level");
3158 void InlineAsmOp::getEffects(
3161 if (getHasSideEffects()) {
3172 auto ptrsVectorType = getPtrs().getType();
3173 Type expectedPtrsVectorType =
3178 if (ptrsVectorType != expectedPtrsVectorType)
3179 return emitOpError(
"expected operand #1 type to be ")
3180 << expectedPtrsVectorType;
3189 auto ptrsVectorType = getPtrs().getType();
3190 Type expectedPtrsVectorType =
3195 if (ptrsVectorType != expectedPtrsVectorType)
3196 return emitOpError(
"expected operand #2 type to be ")
3197 << expectedPtrsVectorType;
3205 void LLVMDialect::initialize() {
3206 registerAttributes();
3209 addTypes<LLVMVoidType,
3220 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3223 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3227 allowUnknownOperations();
3229 addInterfaces<LLVMOpAsmDialectInterface>();
3231 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
3234 #define GET_OP_CLASSES
3235 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3237 #define GET_OP_CLASSES
3238 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3240 LogicalResult LLVMDialect::verifyDataLayoutString(
3244 if (maybeDataLayout)
3247 std::string message;
3248 llvm::raw_string_ostream messageStream(message);
3249 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
3250 reportError(
"invalid data layout descriptor: " + messageStream.str());
3255 LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
3261 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
3263 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
3264 return verifyDataLayoutString(
3265 stringAttr.getValue(),
3266 [op](
const Twine &message) { op->emitOpError() << message.str(); });
3269 << LLVM::LLVMDialect::getDataLayoutAttrName()
3270 <<
"' to be a string attributes";
3273 LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
3281 StringAttr name = paramAttr.
getName();
3283 auto checkUnitAttrType = [&]() -> LogicalResult {
3284 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
3285 return op->
emitError() << name <<
" should be a unit attribute";
3288 auto checkTypeAttrType = [&]() -> LogicalResult {
3289 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
3290 return op->
emitError() << name <<
" should be a type attribute";
3293 auto checkIntegerAttrType = [&]() -> LogicalResult {
3294 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
3295 return op->
emitError() << name <<
" should be an integer attribute";
3298 auto checkPointerType = [&]() -> LogicalResult {
3299 if (!llvm::isa<LLVMPointerType>(paramType))
3301 << name <<
" attribute attached to non-pointer LLVM type";
3304 auto checkIntegerType = [&]() -> LogicalResult {
3305 if (!llvm::isa<IntegerType>(paramType))
3307 << name <<
" attribute attached to non-integer LLVM type";
3310 auto checkPointerTypeMatches = [&]() -> LogicalResult {
3311 if (failed(checkPointerType()))
3318 if (name == LLVMDialect::getNoAliasAttrName() ||
3319 name == LLVMDialect::getReadonlyAttrName() ||
3320 name == LLVMDialect::getReadnoneAttrName() ||
3321 name == LLVMDialect::getWriteOnlyAttrName() ||
3322 name == LLVMDialect::getNestAttrName() ||
3323 name == LLVMDialect::getNoCaptureAttrName() ||
3324 name == LLVMDialect::getNoFreeAttrName() ||
3325 name == LLVMDialect::getNonNullAttrName()) {
3326 if (failed(checkUnitAttrType()))
3328 if (verifyValueType && failed(checkPointerType()))
3334 if (name == LLVMDialect::getStructRetAttrName() ||
3335 name == LLVMDialect::getByValAttrName() ||
3336 name == LLVMDialect::getByRefAttrName() ||
3337 name == LLVMDialect::getInAllocaAttrName() ||
3338 name == LLVMDialect::getPreallocatedAttrName()) {
3339 if (failed(checkTypeAttrType()))
3341 if (verifyValueType && failed(checkPointerTypeMatches()))
3347 if (name == LLVMDialect::getSExtAttrName() ||
3348 name == LLVMDialect::getZExtAttrName()) {
3349 if (failed(checkUnitAttrType()))
3351 if (verifyValueType && failed(checkIntegerType()))
3357 if (name == LLVMDialect::getAlignAttrName() ||
3358 name == LLVMDialect::getDereferenceableAttrName() ||
3359 name == LLVMDialect::getDereferenceableOrNullAttrName() ||
3360 name == LLVMDialect::getStackAlignmentAttrName()) {
3361 if (failed(checkIntegerAttrType()))
3363 if (verifyValueType && failed(checkPointerType()))
3369 if (name == LLVMDialect::getNoUndefAttrName() ||
3370 name == LLVMDialect::getInRegAttrName() ||
3371 name == LLVMDialect::getReturnedAttrName())
3372 return checkUnitAttrType();
3378 LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
3382 auto funcOp = dyn_cast<FunctionOpInterface>(op);
3385 Type argType = funcOp.getArgumentTypes()[argIdx];
3387 return verifyParameterAttribute(op, argType, argAttr);
3390 LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
3394 auto funcOp = dyn_cast<FunctionOpInterface>(op);
3397 Type resType = funcOp.getResultTypes()[resIdx];
3401 if (llvm::isa<LLVMVoidType>(resType))
3402 return op->
emitError() <<
"cannot attach result attributes to functions "
3403 "with a void return";
3407 auto name = resAttr.
getName();
3408 if (name == LLVMDialect::getAllocAlignAttrName() ||
3409 name == LLVMDialect::getAllocatedPointerAttrName() ||
3410 name == LLVMDialect::getByValAttrName() ||
3411 name == LLVMDialect::getByRefAttrName() ||
3412 name == LLVMDialect::getInAllocaAttrName() ||
3413 name == LLVMDialect::getNestAttrName() ||
3414 name == LLVMDialect::getNoCaptureAttrName() ||
3415 name == LLVMDialect::getNoFreeAttrName() ||
3416 name == LLVMDialect::getPreallocatedAttrName() ||
3417 name == LLVMDialect::getReadnoneAttrName() ||
3418 name == LLVMDialect::getReadonlyAttrName() ||
3419 name == LLVMDialect::getReturnedAttrName() ||
3420 name == LLVMDialect::getStackAlignmentAttrName() ||
3421 name == LLVMDialect::getStructRetAttrName() ||
3422 name == LLVMDialect::getWriteOnlyAttrName())
3423 return op->
emitError() << name <<
" is not a valid result attribute";
3424 return verifyParameterAttribute(op, resType, resAttr);
3432 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
3433 if (isa<LLVM::LLVMPointerType>(type))
3434 return builder.
create<LLVM::AddressOfOp>(loc, type, symbol);
3435 if (isa<LLVM::UndefAttr>(value))
3436 return builder.
create<LLVM::UndefOp>(loc, type);
3437 if (isa<LLVM::PoisonAttr>(value))
3438 return builder.
create<LLVM::PoisonOp>(loc, type);
3439 if (isa<LLVM::ZeroAttr>(value))
3440 return builder.
create<LLVM::ZeroOp>(loc, type);
3442 return LLVM::ConstantOp::materialize(builder, value, type, loc);
3450 StringRef name, StringRef value,
3451 LLVM::Linkage linkage) {
3454 "expected builder to point to a block constrained in an op");
3457 assert(module &&
"builder points to an op outside of a module");
3463 auto global = moduleBuilder.
create<LLVM::GlobalOp>(
3464 loc, type,
true, linkage, name,
3470 builder.
create<LLVM::AddressOfOp>(loc, ptrType, global.getSymNameAttr());
3471 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 ParseResult parseCmpOp(OpAsmParser &parser, OperationState &result)
static ParseResult parseLLVMOpAttrs(OpAsmParser &parser, NamedAttrList &result)
LogicalResult verifyAtomicMemOp(OpTy memOp, Type valueType, ArrayRef< AtomicOrdering > unsupportedOrderings)
Verifies the attributes and the type of atomic memory access operations.
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 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 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 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 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 void printLLVMOpAttrs(OpAsmPrinter &printer, Operation *op, DictionaryAttr attrs)
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.
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 parseKeyword(StringRef keyword)
Parse a given keyword.
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 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.
LLVM dialect structure type representing a collection of different-typed elements manipulated togethe...
ArrayRef< Type > getBody() const
Returns the list of element types contained in a non-opaque struct.
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
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.
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
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.
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.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
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.