28 #include "llvm/ADT/SCCIterator.h"
29 #include "llvm/ADT/TypeSwitch.h"
30 #include "llvm/AsmParser/Parser.h"
31 #include "llvm/Bitcode/BitcodeReader.h"
32 #include "llvm/Bitcode/BitcodeWriter.h"
33 #include "llvm/IR/Attributes.h"
34 #include "llvm/IR/Function.h"
35 #include "llvm/IR/Type.h"
36 #include "llvm/Support/Error.h"
37 #include "llvm/Support/Mutex.h"
38 #include "llvm/Support/SourceMgr.h"
45 using mlir::LLVM::cconv::getMaxEnumValForCConv;
46 using mlir::LLVM::linkage::getMaxEnumValForLinkage;
47 using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
49 #include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
60 IntegerOverflowFlags flags) {
67 auto flagsAttr = dyn_cast<IntegerOverflowFlagsAttr>(attr);
69 return emitError() <<
"expected 'overflowFlags' attribute to be an "
70 "IntegerOverflowFlagsAttr, but got "
73 flags = flagsAttr.getValue();
79 IntegerOverflowFlags &flags) {
81 flags = IntegerOverflowFlags::none;
91 std::optional<IntegerOverflowFlags> flag =
92 symbolizeIntegerOverflowFlags(kw);
95 "invalid overflow flag: expected nsw, nuw, or none");
96 flags = flags | *flag;
102 IntegerOverflowFlags flags) {
103 if (flags == IntegerOverflowFlags::none)
107 if (bitEnumContainsAny(flags, IntegerOverflowFlags::nsw))
108 strs.push_back(
"nsw");
109 if (bitEnumContainsAny(flags, IntegerOverflowFlags::nuw))
110 strs.push_back(
"nuw");
111 llvm::interleaveComma(strs, p);
124 if (attr.
getName() ==
"fastmathFlags") {
126 FastmathFlagsAttr::get(attr.getValue().getContext(), {});
131 return filteredAttrs;
140 DictionaryAttr attrs) {
142 if (
auto iface = dyn_cast<IntegerOverflowFlagsInterface>(op)) {
144 filteredAttrs, {iface.getOverflowFlagsAttrName()});
160 << name <<
"' does not reference a valid LLVM function";
161 if (func.isExternal())
162 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
188 template <
typename Ty>
189 struct EnumTraits {};
191 #define REGISTER_ENUM_TYPE(Ty) \
193 struct EnumTraits<Ty> { \
194 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
195 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
208 template <
typename EnumTy,
typename RetTy = EnumTy>
211 EnumTy defaultValue) {
213 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
218 return static_cast<RetTy
>(defaultValue);
219 return static_cast<RetTy
>(index);
227 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
228 <<
", " << getOperand(1);
230 p <<
" : " << getLhs().getType();
234 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
235 <<
", " << getOperand(1);
237 p <<
" : " << getLhs().getType();
244 template <
typename CmpPredicateType>
246 StringAttr predicateAttr;
249 SMLoc predicateLoc, trailingTypeLoc;
261 int64_t predicateValue = 0;
262 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
263 std::optional<ICmpPredicate> predicate =
264 symbolizeICmpPredicate(predicateAttr.getValue());
267 <<
"'" << predicateAttr.getValue()
268 <<
"' is an incorrect value of the 'predicate' attribute";
269 predicateValue =
static_cast<int64_t
>(*predicate);
271 std::optional<FCmpPredicate> predicate =
272 symbolizeFCmpPredicate(predicateAttr.getValue());
275 <<
"'" << predicateAttr.getValue()
276 <<
"' is an incorrect value of the 'predicate' attribute";
277 predicateValue =
static_cast<int64_t
>(*predicate);
287 "expected LLVM dialect-compatible type");
293 return parseCmpOp<ICmpPredicate>(parser, result);
297 return parseCmpOp<FCmpPredicate>(parser, result);
303 ShapedType shapedType = dyn_cast<ShapedType>(type);
310 if (getPredicate() != ICmpPredicate::eq &&
311 getPredicate() != ICmpPredicate::ne)
315 if (getLhs() == getRhs())
317 getPredicate() == ICmpPredicate::eq);
320 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
322 getPredicate() == ICmpPredicate::ne);
325 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
326 Value lhs = getLhs();
327 Value rhs = getRhs();
328 getLhsMutable().assign(rhs);
329 getRhsMutable().assign(lhs);
347 p <<
' ' << getArraySize() <<
" x " << getElemType();
348 if (getAlignment() && *getAlignment() != 0)
350 {kElemTypeAttrName, getInallocaAttrName()});
354 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
355 p <<
" : " << funcTy;
363 SMLoc trailingTypeLoc;
375 std::optional<NamedAttribute> alignmentAttr =
377 if (alignmentAttr.has_value()) {
378 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
381 "expected integer alignment");
382 if (alignmentInt.getValue().isZero())
387 auto funcType = llvm::dyn_cast<FunctionType>(type);
388 if (!funcType || funcType.getNumInputs() != 1 ||
389 funcType.getNumResults() != 1)
392 "expected trailing function type with one argument and one result");
397 Type resultType = funcType.getResult(0);
398 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
401 result.
addTypes({funcType.getResult(0)});
407 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
408 targetExtType && !targetExtType.supportsMemOps())
410 <<
"this target extension type cannot be used in alloca";
415 Type AllocaOp::getResultPtrElementType() {
return getElemType(); }
422 assert(index == 0 &&
"invalid successor index");
431 assert(index < getNumSuccessors() &&
"invalid successor index");
433 : getFalseDestOperandsMutable());
439 std::optional<std::pair<uint32_t, uint32_t>> weights) {
444 static_cast<int32_t
>(weights->second)});
446 build(builder, result, condition, trueOperands, falseOperands, weightsAttr,
447 {}, trueDest, falseDest);
461 if (!branchWeights.empty())
464 build(builder, result, value, defaultOperands, caseOperands, caseValues,
465 weightsAttr, defaultDestination, caseDestinations);
474 if (!caseValues.empty()) {
476 static_cast<int64_t
>(caseValues.size()), value.
getType());
480 build(builder, result, value, defaultDestination, defaultOperands,
481 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
490 if (!caseValues.empty()) {
492 static_cast<int64_t
>(caseValues.size()), value.
getType());
496 build(builder, result, value, defaultDestination, defaultOperands,
497 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
513 auto parseCase = [&]() {
517 values.push_back(APInt(bitWidth, value));
530 caseDestinations.push_back(destination);
531 caseOperands.emplace_back(operands);
532 caseOperandTypes.emplace_back(operandTypes);
538 ShapedType caseValueType =
558 llvm::zip(caseValues, caseDestinations),
561 p << std::get<0>(i).getLimitedValue();
574 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
576 getCaseValues()->size() !=
577 static_cast<int64_t
>(getCaseDestinations().size())))
578 return emitOpError(
"expects number of case values to match number of "
579 "case destinations");
580 if (getBranchWeights() && getBranchWeights()->size() != getNumSuccessors())
581 return emitError(
"expects number of branch weights to match number of "
583 << getBranchWeights()->size() <<
" vs " << getNumSuccessors();
584 if (getCaseValues() &&
586 return emitError(
"expects case value type to match condition value type");
591 assert(index < getNumSuccessors() &&
"invalid successor index");
593 : getCaseOperandsMutable(index - 1));
600 constexpr int32_t GEPOp::kDynamicIndex;
604 getDynamicIndices());
609 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
610 return vectorType.getElementType();
611 if (
auto scalableVectorType = llvm::dyn_cast<LLVMScalableVectorType>(type))
612 return scalableVectorType.getElementType();
613 if (
auto fixedVectorType = llvm::dyn_cast<LLVMFixedVectorType>(type))
614 return fixedVectorType.getElementType();
626 for (
const GEPArg &iter : indices) {
631 bool requiresConst = !rawConstantIndices.empty() &&
632 isa_and_nonnull<LLVMStructType>(currType);
633 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
637 rawConstantIndices.push_back(intC.getSExtValue());
639 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
640 dynamicIndices.push_back(val);
648 if (rawConstantIndices.size() == 1 || !currType)
653 .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
654 LLVMArrayType>([](
auto containerType) {
655 return containerType.getElementType();
658 int64_t memberIndex = rawConstantIndices.back();
659 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
661 return structType.
getBody()[memberIndex];
664 .Default(
Type(
nullptr));
691 build(builder, result, resultType, elementType, basePtr,
701 auto idxParser = [&]() -> ParseResult {
706 if (failed(parsedInteger.
value()))
712 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
726 llvm::interleaveComma(
729 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
732 printer << cst.get<IntegerAttr>().getInt();
742 if (indexPos >= indices.
size())
748 if (!indices[indexPos].is<IntegerAttr>())
749 return emitOpError() <<
"expected index " << indexPos
750 <<
" indexing a struct to be constant";
752 int32_t gepIndex = indices[indexPos].get<IntegerAttr>().getInt();
755 static_cast<size_t>(gepIndex) >= elementTypes.size())
756 return emitOpError() <<
"index " << indexPos
757 <<
" indexing a struct is out of bounds";
762 indices, emitOpError);
764 .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
765 LLVMArrayType>([&](
auto containerType) -> LogicalResult {
767 indices, emitOpError);
769 .Default([&](
auto otherType) -> LogicalResult {
771 <<
"type " << otherType <<
" cannot be indexed (index #"
784 if (
static_cast<size_t>(
785 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
786 getDynamicIndices().size())
787 return emitOpError(
"expected as many dynamic indices as specified in '")
788 << getRawConstantIndicesAttrName().getValue() <<
"'";
791 [&] {
return emitOpError(); });
794 Type GEPOp::getResultPtrElementType() {
797 Type selectedType = getElemType();
802 llvm::drop_begin(indices)) {
807 if (
auto arrayType = dyn_cast<LLVMArrayType>(selectedType)) {
808 selectedType = arrayType.getElementType();
814 selectedType = cast<DestructurableTypeInterface>(selectedType)
815 .getTypeAtIndex(cast<IntegerAttr>(index));
827 void LoadOp::getEffects(
836 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
837 getOrdering() != AtomicOrdering::unordered)) {
848 if (!isa<IntegerType, LLVMPointerType>(type))
853 if (bitWidth.isScalable())
856 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
860 template <
typename OpTy>
863 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
866 return memOp.emitOpError(
"unsupported type ")
867 << valueType <<
" for atomic access";
868 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
869 return memOp.emitOpError(
"unsupported ordering '")
870 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
871 if (!memOp.getAlignment())
872 return memOp.emitOpError(
"expected alignment for atomic access");
875 if (memOp.getSyncscope())
876 return memOp.emitOpError(
877 "expected syncscope to be null for non-atomic access");
882 Type valueType = getResult().getType();
884 {AtomicOrdering::release, AtomicOrdering::acq_rel});
888 Value addr,
unsigned alignment,
bool isVolatile,
889 bool isNonTemporal,
bool isInvariant,
890 AtomicOrdering ordering, StringRef syncscope) {
891 build(builder, state, type, addr,
893 isNonTemporal, isInvariant, ordering,
894 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
904 void StoreOp::getEffects(
913 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
914 getOrdering() != AtomicOrdering::unordered)) {
921 Type valueType = getValue().getType();
923 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
927 Value addr,
unsigned alignment,
bool isVolatile,
928 bool isNonTemporal, AtomicOrdering ordering,
929 StringRef syncscope) {
930 build(builder, state, value, addr,
932 isNonTemporal, ordering,
933 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
935 nullptr,
nullptr,
nullptr);
945 Type resultType = calleeType.getReturnType();
946 if (!isa<LLVM::LLVMVoidType>(resultType))
947 results.push_back(resultType);
953 return calleeType.isVarArg() ?
TypeAttr::get(calleeType) :
nullptr;
963 resultType = results.front();
970 build(builder, state, results, builder.
getStringAttr(callee), args);
980 assert(callee &&
"expected non-null callee in direct call builder");
981 build(builder, state, results,
982 nullptr, callee, args,
nullptr,
986 nullptr,
nullptr,
nullptr,
992 LLVMFunctionType calleeType, StringRef callee,
994 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
998 LLVMFunctionType calleeType, StringAttr callee,
1014 nullptr,
nullptr,
nullptr);
1018 LLVMFunctionType calleeType,
ValueRange args) {
1023 nullptr,
nullptr,
nullptr,
1024 nullptr,
nullptr,
nullptr,
1031 auto calleeType = func.getFunctionType();
1035 nullptr,
nullptr,
nullptr,
1036 nullptr,
nullptr,
nullptr,
1046 return getOperand(0);
1052 auto symRef = callee.get<SymbolRefAttr>();
1053 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1056 return setOperand(0, callee.get<
Value>());
1060 return getOperands().drop_front(getCallee().has_value() ? 0 : 1);
1065 getCalleeOperands().size());
1072 if (callee.isExternal())
1074 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1078 auto hasSubprogram = [](
Operation *op) {
1083 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1085 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1087 return callOp.emitError()
1088 <<
"inlinable function call in a function with a DISubprogram "
1089 "location must have a debug location";
1095 template <
typename OpTy>
1097 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1102 if (!varCalleeType->isVarArg())
1103 return callOp.emitOpError(
1104 "expected var_callee_type to be a variadic function type");
1108 if (varCalleeType->getNumParams() > callOp.getArgOperands().size())
1109 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1110 << callOp.getArgOperands().size() <<
" parameters";
1113 for (
auto [paramType, operand] :
1114 llvm::zip(varCalleeType->getParams(), callOp.getArgOperands()))
1115 if (paramType != operand.getType())
1116 return callOp.emitOpError()
1117 <<
"var_callee_type parameter type mismatch: " << paramType
1118 <<
" != " << operand.getType();
1121 if (!callOp.getNumResults()) {
1122 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1123 return callOp.emitOpError(
"expected var_callee_type to return void");
1125 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1126 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1127 << varCalleeType->getReturnType()
1128 <<
" != " << callOp.getResult().getType();
1141 bool isIndirect =
false;
1147 if (!getNumOperands())
1149 "must have either a `callee` attribute or at least an operand");
1150 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1152 return emitOpError(
"indirect call expects a pointer as callee: ")
1153 << getOperand(0).getType();
1160 return emitOpError()
1162 <<
"' does not reference a symbol in the current scope";
1163 auto fn = dyn_cast<LLVMFuncOp>(callee);
1165 return emitOpError() <<
"'" << calleeName.
getValue()
1166 <<
"' does not reference a valid LLVM function";
1170 fnType = fn.getFunctionType();
1173 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1175 return emitOpError(
"callee does not have a functional type: ") << fnType;
1177 if (funcType.isVarArg() && !getVarCalleeType())
1178 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1182 if (!funcType.isVarArg() &&
1183 funcType.getNumParams() != (getNumOperands() - isIndirect))
1184 return emitOpError() <<
"incorrect number of operands ("
1185 << (getNumOperands() - isIndirect)
1186 <<
") for callee (expecting: "
1187 << funcType.getNumParams() <<
")";
1189 if (funcType.getNumParams() > (getNumOperands() - isIndirect))
1190 return emitOpError() <<
"incorrect number of operands ("
1191 << (getNumOperands() - isIndirect)
1192 <<
") for varargs callee (expecting at least: "
1193 << funcType.getNumParams() <<
")";
1195 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1196 if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1197 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1198 << getOperand(i + isIndirect).getType()
1199 <<
" != " << funcType.getParamType(i);
1201 if (getNumResults() == 0 &&
1202 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1203 return emitOpError() <<
"expected function call to produce a value";
1205 if (getNumResults() != 0 &&
1206 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1207 return emitOpError()
1208 <<
"calling function with void result must not produce values";
1210 if (getNumResults() > 1)
1211 return emitOpError()
1212 <<
"expected LLVM function call to produce 0 or 1 result";
1214 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1215 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1216 <<
" != " << funcType.getReturnType();
1222 auto callee = getCallee();
1223 bool isDirect = callee.has_value();
1228 if (getCConv() != LLVM::CConv::C)
1229 p << stringifyCConv(getCConv()) <<
' ';
1232 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1241 auto args = getOperands().drop_front(isDirect ? 0 : 1);
1242 p <<
'(' << args <<
')';
1245 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1246 p <<
" vararg(" << *varCalleeType <<
")";
1249 {getCalleeAttrName(), getTailCallKindAttrName(),
1250 getVarCalleeTypeAttrName(), getCConvAttrName()});
1254 p << getOperand(0).getType() <<
", ";
1270 if (isDirect && types.size() != 1)
1271 return parser.
emitError(trailingTypesLoc,
1272 "expected direct call to have 1 trailing type");
1273 if (!isDirect && types.size() != 2)
1274 return parser.
emitError(trailingTypesLoc,
1275 "expected indirect call to have 2 trailing types");
1277 auto funcType = llvm::dyn_cast<FunctionType>(types.pop_back_val());
1279 return parser.
emitError(trailingTypesLoc,
1280 "expected trailing function type");
1281 if (funcType.getNumResults() > 1)
1282 return parser.
emitError(trailingTypesLoc,
1283 "expected function with 0 or 1 result");
1284 if (funcType.getNumResults() == 1 &&
1285 llvm::isa<LLVM::LLVMVoidType>(funcType.getResult(0)))
1286 return parser.
emitError(trailingTypesLoc,
1287 "expected a non-void result type");
1293 llvm::append_range(types, funcType.getInputs());
1297 if (funcType.getNumResults() != 0)
1298 result.
addTypes(funcType.getResults());
1311 if (failed(*parseResult))
1312 return *parseResult;
1313 operands.push_back(funcPtrOperand);
1323 SymbolRefAttr funcAttr;
1324 TypeAttr varCalleeType;
1329 getCConvAttrName(result.
name),
1331 parser, result, LLVM::CConv::C)));
1334 getTailCallKindAttrName(result.
name),
1336 parseOptionalLLVMKeyword<TailCallKind>(
1342 bool isDirect = operands.empty();
1355 StringAttr varCalleeTypeAttrName =
1356 CallOp::getVarCalleeTypeAttrName(result.
name);
1373 LLVMFunctionType CallOp::getCalleeFunctionType() {
1374 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1375 return *varCalleeType;
1386 auto calleeType = func.getFunctionType();
1389 normalOps, unwindOps,
nullptr,
nullptr, normal, unwind);
1396 build(builder, state, tys,
1397 nullptr, callee, ops, normalOps, unwindOps,
nullptr,
1398 nullptr, normal, unwind);
1407 nullptr,
nullptr, normal, unwind);
1411 assert(index < getNumSuccessors() &&
"invalid successor index");
1413 : getUnwindDestOperandsMutable());
1421 return getOperand(0);
1427 auto symRef = callee.get<SymbolRefAttr>();
1428 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1431 return setOperand(0, callee.get<
Value>());
1435 return getOperands().drop_front(getCallee().has_value() ? 0 : 1);
1440 getCalleeOperands().size());
1447 Block *unwindDest = getUnwindDest();
1448 if (unwindDest->
empty())
1449 return emitError(
"must have at least one operation in unwind destination");
1452 if (!isa<LandingpadOp>(unwindDest->
front()))
1453 return emitError(
"first operation in unwind destination should be a "
1454 "llvm.landingpad operation");
1460 auto callee = getCallee();
1461 bool isDirect = callee.has_value();
1466 if (getCConv() != LLVM::CConv::C)
1467 p << stringifyCConv(getCConv()) <<
' ';
1475 p <<
'(' << getOperands().drop_front(isDirect ? 0 : 1) <<
')';
1482 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1483 p <<
" vararg(" << *varCalleeType <<
")";
1486 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1487 getCConvAttrName(), getVarCalleeTypeAttrName()});
1491 p << getOperand(0).getType() <<
", ";
1504 SymbolRefAttr funcAttr;
1505 TypeAttr varCalleeType;
1506 Block *normalDest, *unwindDest;
1512 getCConvAttrName(result.
name),
1514 parser, result, LLVM::CConv::C)));
1519 bool isDirect = operands.empty();
1535 StringAttr varCalleeTypeAttrName =
1536 InvokeOp::getVarCalleeTypeAttrName(result.
name);
1557 result.
addAttribute(InvokeOp::getOperandSegmentSizeAttr(),
1559 {static_cast<int32_t>(operands.size()),
1560 static_cast<int32_t>(normalOperands.size()),
1561 static_cast<int32_t>(unwindOperands.size())}));
1565 LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1566 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1567 return *varCalleeType;
1577 if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1578 if (!func.getPersonality())
1580 "llvm.landingpad needs to be in a function with a personality");
1586 if (!getCleanup() && getOperands().empty())
1587 return emitError(
"landingpad instruction expects at least one clause or "
1588 "cleanup attribute");
1590 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1591 value = getOperand(idx);
1592 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1599 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1602 <<
"global addresses expected as operand to "
1603 "bitcast used in clauses for landingpad";
1611 << idx <<
" is not a known constant - null, addressof, bitcast";
1618 p << (getCleanup() ?
" cleanup " :
" ");
1621 for (
auto value : getOperands()) {
1624 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1625 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1672 Type llvmType = containerType;
1674 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1682 for (int64_t idx : position) {
1683 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1684 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1685 emitError(
"position out of bounds: ") << idx;
1688 llvmType = arrayType.getElementType();
1689 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1691 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1692 emitError(
"position out of bounds: ") << idx;
1695 llvmType = structType.getBody()[idx];
1697 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1708 for (int64_t idx : position) {
1709 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1710 llvmType = structType.getBody()[idx];
1712 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1717 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1718 auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1720 while (insertValueOp) {
1721 if (getPosition() == insertValueOp.getPosition())
1722 return insertValueOp.getValue();
1724 std::min(getPosition().size(), insertValueOp.getPosition().size());
1735 if (getPosition().take_front(
min) ==
1736 insertValueOp.getPosition().take_front(
min))
1742 getContainerMutable().assign(insertValueOp.getContainer());
1743 result = getResult();
1744 insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1750 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1756 if (getRes().
getType() != valueType)
1757 return emitOpError() <<
"Type mismatch: extracting from "
1758 << getContainer().getType() <<
" should produce "
1759 << valueType <<
" but this op returns "
1760 << getRes().getType();
1766 build(builder, state,
1781 [&](StringRef msg) {
1785 return success(!!valueType);
1795 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1801 if (getValue().
getType() != valueType)
1802 return emitOpError() <<
"Type mismatch: cannot insert "
1803 << getValue().getType() <<
" into "
1804 << getContainer().getType();
1814 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
1818 Type expectedType = parent.getFunctionType().getReturnType();
1819 if (llvm::isa<LLVMVoidType>(expectedType)) {
1823 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1827 if (llvm::isa<LLVMVoidType>(expectedType))
1830 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1833 if (expectedType != getArg().
getType()) {
1835 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1849 assert(module &&
"unexpected operation outside of a module");
1854 return dyn_cast_or_null<GlobalOp>(
1859 return dyn_cast_or_null<LLVMFuncOp>(
1868 auto global = dyn_cast_or_null<GlobalOp>(symbol);
1869 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
1871 if (!global && !
function)
1873 "must reference a global defined by 'llvm.mlir.global' or 'llvm.func'");
1875 LLVMPointerType type =
getType();
1876 if (global && global.getAddrSpace() != type.getAddressSpace())
1877 return emitOpError(
"pointer address space must match address space of the "
1878 "referenced global");
1885 return getGlobalNameAttr();
1893 StringRef symName) {
1900 LogicalResult ComdatOp::verifyRegions() {
1901 Region &body = getBody();
1903 if (!isa<ComdatSelectorOp>(op))
1905 "only comdat selector symbols can appear in a comdat region");
1915 bool isConstant, Linkage linkage, StringRef name,
1916 Attribute value, uint64_t alignment,
unsigned addrSpace,
1917 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
1919 DIGlobalVariableExpressionAttr dbgExpr) {
1958 p <<
' ' << stringifyLinkage(getLinkage()) <<
' ';
1959 StringRef visibility = stringifyVisibility(getVisibility_());
1960 if (!visibility.empty())
1961 p << visibility <<
' ';
1962 if (getThreadLocal_())
1963 p <<
"thread_local ";
1964 if (
auto unnamedAddr = getUnnamedAddr()) {
1965 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
1973 if (
auto value = getValueOrNull())
1976 if (
auto comdat = getComdat())
1977 p <<
" comdat(" << *comdat <<
')';
1983 {SymbolTable::getSymbolAttrName(),
1984 getGlobalTypeAttrName(), getConstantAttrName(),
1985 getValueAttrName(), getLinkageAttrName(),
1986 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
1987 getVisibility_AttrName(), getComdatAttrName(),
1988 getUnnamedAddrAttrName()});
1991 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
1995 Region &initializer = getInitializerRegion();
1996 if (!initializer.
empty()) {
2003 std::optional<SymbolRefAttr> attr) {
2008 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2009 return op->
emitError() <<
"expected comdat symbol";
2027 ctx, parseOptionalLLVMKeyword<Linkage>(
2028 parser, result, LLVM::Linkage::External)));
2033 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2034 parser, result, LLVM::Visibility::Default)));
2039 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2065 SymbolRefAttr comdat;
2078 if (types.size() > 1)
2082 if (types.empty()) {
2083 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2086 strAttr.getValue().size());
2087 types.push_back(arrayType);
2090 "type can only be omitted for string globals");
2096 if (parseResult.
has_value() && failed(*parseResult))
2106 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2107 return intValue.getValue().isZero();
2108 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2109 return fpValue.getValue().isZero();
2110 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2112 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2114 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2121 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
2122 LLVMMetadataType, LLVMLabelType>(
getType())
2123 : llvm::isa<PointerElementTypeInterface>(
getType());
2126 "expects type to be a valid element type for an LLVM global");
2128 return emitOpError(
"must appear at the module level");
2130 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2131 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2132 IntegerType elementType =
2133 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2134 if (!elementType || elementType.getWidth() != 8 ||
2135 type.getNumElements() != strAttr.getValue().size())
2137 "requires an i8 array type of the length equal to that of the string "
2141 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2142 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2143 return emitOpError()
2144 <<
"this target extension type cannot be used in a global";
2147 return emitOpError() <<
"global with target extension type can only be "
2148 "initialized with zero-initializer";
2151 if (getLinkage() == Linkage::Common) {
2152 if (
Attribute value = getValueOrNull()) {
2154 return emitOpError()
2155 <<
"expected zero value for '"
2156 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2161 if (getLinkage() == Linkage::Appending) {
2162 if (!llvm::isa<LLVMArrayType>(
getType())) {
2163 return emitOpError() <<
"expected array type for '"
2164 << stringifyLinkage(Linkage::Appending)
2172 std::optional<uint64_t> alignAttr = getAlignment();
2173 if (alignAttr.has_value()) {
2174 uint64_t value = alignAttr.value();
2175 if (!llvm::isPowerOf2_64(value))
2176 return emitError() <<
"alignment attribute is not a power of 2";
2182 LogicalResult GlobalOp::verifyRegions() {
2183 if (
Block *b = getInitializerBlock()) {
2184 ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2185 if (ret.operand_type_begin() == ret.operand_type_end())
2186 return emitOpError(
"initializer region cannot return void");
2187 if (*ret.operand_type_begin() !=
getType())
2188 return emitOpError(
"initializer region type ")
2189 << *ret.operand_type_begin() <<
" does not match global type "
2193 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2194 if (!iface || !iface.hasNoEffect())
2196 <<
"ops with side effects not allowed in global initializers";
2199 if (getValueOrNull())
2200 return emitOpError(
"cannot have both initializer value and region");
2221 if (getCtors().size() != getPriorities().size())
2223 "mismatch between the number of ctors and the number of priorities");
2242 if (getDtors().size() != getPriorities().size())
2244 "mismatch between the number of dtors and the number of priorities");
2255 auto containerType = v1.
getType();
2259 build(builder, state, vType, v1, v2, mask);
2260 state.addAttributes(attrs);
2273 "expected an LLVM compatible vector type");
2285 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2286 return emitOpError(
"expected a splat operation for scalable vectors");
2296 assert(empty() &&
"function already has an entry block");
2301 LLVMFunctionType type = getFunctionType();
2302 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2303 entry->
addArgument(type.getParamType(i), getLoc());
2308 StringRef name,
Type type, LLVM::Linkage linkage,
2309 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2312 std::optional<uint64_t> functionEntryCount) {
2328 if (functionEntryCount)
2331 if (argAttrs.empty())
2334 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2335 "expected as many argument attribute lists as arguments");
2337 builder, result, argAttrs, std::nullopt,
2338 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2349 if (outputs.size() > 1) {
2350 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2351 "one function result");
2357 for (
auto t : inputs) {
2359 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2360 "type for function arguments");
2363 llvmInputs.push_back(t);
2370 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2371 "type for function results")
2389 getLinkageAttrName(result.
name),
2391 parseOptionalLLVMKeyword<Linkage>(
2392 parser, result, LLVM::Linkage::External)));
2397 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2398 parser, result, LLVM::Visibility::Default)));
2403 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2408 getCConvAttrName(result.
name),
2410 parser, result, LLVM::CConv::C)));
2412 StringAttr nameAttr;
2422 parser,
true, entryArgs, isVariadic, resultTypes,
2427 for (
auto &arg : entryArgs)
2428 argTypes.push_back(arg.type);
2438 int64_t minRange, maxRange;
2445 getVscaleRangeAttrName(result.
name),
2452 SymbolRefAttr comdat;
2463 parser.
getBuilder(), result, entryArgs, resultAttrs,
2464 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2469 return failure(parseResult.
has_value() && failed(*parseResult));
2477 if (getLinkage() != LLVM::Linkage::External)
2478 p << stringifyLinkage(getLinkage()) <<
' ';
2479 StringRef visibility = stringifyVisibility(getVisibility_());
2480 if (!visibility.empty())
2481 p << visibility <<
' ';
2482 if (
auto unnamedAddr = getUnnamedAddr()) {
2483 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2487 if (getCConv() != LLVM::CConv::C)
2488 p << stringifyCConv(getCConv()) <<
' ';
2492 LLVMFunctionType fnType = getFunctionType();
2495 argTypes.reserve(fnType.getNumParams());
2496 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
2497 argTypes.push_back(fnType.getParamType(i));
2499 Type returnType = fnType.getReturnType();
2500 if (!llvm::isa<LLVMVoidType>(returnType))
2501 resTypes.push_back(returnType);
2504 isVarArg(), resTypes);
2507 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
2508 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
2509 << vscale->getMaxRange().getInt() <<
')';
2512 if (
auto comdat = getComdat())
2513 p <<
" comdat(" << *comdat <<
')';
2517 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
2518 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
2519 getComdatAttrName(), getUnnamedAddrAttrName(),
2520 getVscaleRangeAttrName()});
2523 Region &body = getBody();
2524 if (!body.empty()) {
2536 if (getLinkage() == LLVM::Linkage::Common)
2537 return emitOpError() <<
"functions cannot have '"
2538 << stringifyLinkage(LLVM::Linkage::Common)
2545 if (getLinkage() != LLVM::Linkage::External &&
2546 getLinkage() != LLVM::Linkage::ExternWeak)
2547 return emitOpError() <<
"external functions must have '"
2548 << stringifyLinkage(LLVM::Linkage::External)
2550 << stringifyLinkage(LLVM::Linkage::ExternWeak)
2556 if (isNoInline() && isAlwaysInline())
2557 return emitError(
"no_inline and always_inline attributes are incompatible");
2559 if (isOptimizeNone() && !isNoInline())
2560 return emitOpError(
"with optimize_none must also be no_inline");
2562 Type landingpadResultTy;
2563 StringRef diagnosticMessage;
2564 bool isLandingpadTypeConsistent =
2566 const auto checkType = [&](
Type type, StringRef errorMessage) {
2567 if (!landingpadResultTy) {
2568 landingpadResultTy = type;
2571 if (landingpadResultTy != type) {
2572 diagnosticMessage = errorMessage;
2578 .Case<LandingpadOp>([&](
auto landingpad) {
2579 constexpr StringLiteral errorMessage =
2580 "'llvm.landingpad' should have a consistent result type "
2581 "inside a function";
2582 return checkType(landingpad.getType(), errorMessage);
2584 .Case<ResumeOp>([&](
auto resume) {
2585 constexpr StringLiteral errorMessage =
2586 "'llvm.resume' should have a consistent input type inside a "
2588 return checkType(resume.getValue().getType(), errorMessage);
2591 }).wasInterrupted();
2592 if (!isLandingpadTypeConsistent) {
2593 assert(!diagnosticMessage.empty() &&
2594 "Expecting a non-empty diagnostic message");
2603 LogicalResult LLVMFuncOp::verifyRegions() {
2607 unsigned numArguments = getFunctionType().getNumParams();
2608 Block &entryBlock = front();
2609 for (
unsigned i = 0; i < numArguments; ++i) {
2612 return emitOpError(
"entry block argument #")
2613 << i <<
" is not of LLVM type";
2619 Region *LLVMFuncOp::getCallableRegion() {
2648 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
2649 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
2650 return emitOpError()
2651 <<
"target extension type does not support zero-initializer";
2670 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
2671 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
2672 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
2673 !arrayType.getElementType().isInteger(8)) {
2674 return emitOpError() <<
"expected array type of "
2675 << sAttr.getValue().size()
2676 <<
" i8 elements for the string constant";
2680 if (
auto structType = llvm::dyn_cast<LLVMStructType>(
getType())) {
2681 if (structType.getBody().size() != 2 ||
2682 structType.getBody()[0] != structType.getBody()[1]) {
2683 return emitError() <<
"expected struct type with two elements of the "
2684 "same type, the type of a complex constant";
2687 auto arrayAttr = llvm::dyn_cast<ArrayAttr>(getValue());
2688 if (!arrayAttr || arrayAttr.size() != 2) {
2689 return emitOpError() <<
"expected array attribute with two elements, "
2690 "representing a complex constant";
2692 auto re = llvm::dyn_cast<TypedAttr>(arrayAttr[0]);
2693 auto im = llvm::dyn_cast<TypedAttr>(arrayAttr[1]);
2694 if (!re || !im || re.getType() != im.getType()) {
2695 return emitOpError()
2696 <<
"expected array attribute with two elements of the same type";
2699 Type elementType = structType.getBody()[0];
2700 if (!llvm::isa<IntegerType, Float16Type, Float32Type, Float64Type>(
2703 <<
"expected struct element types to be floating point type or "
2708 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2709 return emitOpError() <<
"does not support target extension type.";
2711 if (!llvm::isa<IntegerAttr, ArrayAttr, FloatAttr, ElementsAttr>(getValue()))
2712 return emitOpError()
2713 <<
"only supports integer, float, string or elements attributes";
2714 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
2715 if (!llvm::isa<IntegerType>(
getType()))
2716 return emitOpError() <<
"expected integer type";
2718 if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
2719 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
2720 unsigned floatWidth = APFloat::getSizeInBits(sem);
2721 if (
auto floatTy = dyn_cast<FloatType>(
getType())) {
2722 if (floatTy.getWidth() != floatWidth) {
2723 return emitOpError() <<
"expected float type of width " << floatWidth;
2728 if (isa<IntegerType>(
getType()) && !
getType().isInteger(floatWidth)) {
2729 return emitOpError() <<
"expected integer type of width " << floatWidth;
2732 if (
auto splatAttr = dyn_cast<SplatElementsAttr>(getValue())) {
2733 if (!isa<VectorType>(
getType()) && !isa<LLVM::LLVMArrayType>(
getType()) &&
2734 !isa<LLVM::LLVMFixedVectorType>(
getType()) &&
2735 !isa<LLVM::LLVMScalableVectorType>(
getType()))
2736 return emitOpError() <<
"expected vector or array type";
2741 bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
2743 auto typedAttr = dyn_cast<TypedAttr>(value);
2750 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
2755 if (isBuildableWith(value, type))
2756 return builder.
create<LLVM::ConstantOp>(loc, cast<TypedAttr>(value));
2761 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
2769 AtomicOrdering ordering, StringRef syncscope,
2770 unsigned alignment,
bool isVolatile) {
2771 build(builder, state, val.
getType(), binOp, ptr, val, ordering,
2772 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
2775 nullptr,
nullptr,
nullptr);
2779 auto valType = getVal().getType();
2780 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
2781 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax) {
2783 return emitOpError(
"expected LLVM IR floating point type");
2784 }
else if (getBinOp() == AtomicBinOp::xchg) {
2787 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
2789 auto intType = llvm::dyn_cast<IntegerType>(valType);
2790 unsigned intBitWidth = intType ? intType.getWidth() : 0;
2791 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
2793 return emitOpError(
"expected LLVM IR integer type");
2796 if (
static_cast<unsigned>(getOrdering()) <
2797 static_cast<unsigned>(AtomicOrdering::monotonic))
2798 return emitOpError() <<
"expected at least '"
2799 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
2812 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
2817 AtomicOrdering successOrdering,
2818 AtomicOrdering failureOrdering, StringRef syncscope,
2819 unsigned alignment,
bool isWeak,
bool isVolatile) {
2821 successOrdering, failureOrdering,
2822 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
2824 isVolatile,
nullptr,
2825 nullptr,
nullptr,
nullptr);
2829 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
2831 return emitOpError(
"expected LLVM IR pointer type for operand #0");
2832 auto valType = getVal().getType();
2835 return emitOpError(
"unexpected LLVM IR type");
2836 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
2837 getFailureOrdering() < AtomicOrdering::monotonic)
2838 return emitOpError(
"ordering must be at least 'monotonic'");
2839 if (getFailureOrdering() == AtomicOrdering::release ||
2840 getFailureOrdering() == AtomicOrdering::acq_rel)
2841 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
2850 AtomicOrdering ordering, StringRef syncscope) {
2851 build(builder, state, ordering,
2852 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
2856 if (getOrdering() == AtomicOrdering::not_atomic ||
2857 getOrdering() == AtomicOrdering::unordered ||
2858 getOrdering() == AtomicOrdering::monotonic)
2859 return emitOpError(
"can be given only acquire, release, acq_rel, "
2860 "and seq_cst orderings");
2870 template <
class ExtOp>
2872 IntegerType inputType, outputType;
2876 "input type is a vector but output type is an integer");
2879 return op.
emitError(
"input and output vectors are of incompatible shape");
2888 inputType = cast<IntegerType>(op.getArg().getType());
2892 "input type is an integer but output type is a vector");
2895 if (outputType.getWidth() <= inputType.getWidth())
2896 return op.
emitError(
"integer width of the output type is smaller or "
2897 "equal to the integer width of the input type");
2905 LogicalResult
ZExtOp::verify() {
return verifyExtOp<ZExtOp>(*
this); }
2908 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
2912 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
2920 LogicalResult
SExtOp::verify() {
return verifyExtOp<SExtOp>(*
this); }
2927 template <
typename T>
2929 typename T::FoldAdaptor adaptor) {
2931 if (castOp.getArg().getType() == castOp.getType())
2932 return castOp.getArg();
2933 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
2935 if (prev.getArg().getType() == castOp.getType())
2936 return prev.getArg();
2938 castOp.getArgMutable().set(prev.getArg());
2939 return Value{castOp};
2944 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
2949 auto resultType = llvm::dyn_cast<LLVMPointerType>(
2951 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
2956 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
2957 return emitOpError(
"can only cast pointers from and to pointers");
2963 llvm::IsaPred<VectorType, LLVMScalableVectorType, LLVMFixedVectorType>;
2967 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
2968 return emitOpError(
"cannot cast pointer to vector of pointers");
2970 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
2971 return emitOpError(
"cannot cast vector of pointers to pointer");
2975 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
2976 return emitOpError(
"cannot cast pointers of different address spaces, "
2977 "use 'llvm.addrspacecast' instead");
2986 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
2996 adaptor.getDynamicIndices());
3000 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
3001 if (integer.getValue().isZero())
3005 bool changed =
false;
3008 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
3015 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
3016 gepArgs.emplace_back(val);
3018 gepArgs.emplace_back(existing.get<IntegerAttr>().getInt());
3024 gepArgs.emplace_back(integer.getInt());
3032 getDynamicIndicesMutable().assign(dynamicIndices);
3033 setRawConstantIndices(rawConstantIndices);
3034 return Value{*
this};
3045 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3049 if (rhs.getValue().getZExtValue() >=
3050 getLhs().
getType().getIntOrFloatBitWidth())
3053 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3065 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
3069 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
3081 if (!getIntrin().starts_with(
"llvm."))
3082 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
3096 .Case<AccessGroupAttr, AliasScopeAttr, AliasScopeDomainAttr,
3097 DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
3098 DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
3099 DIGlobalVariableExpressionAttr, DILabelAttr, DILexicalBlockAttr,
3100 DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
3101 DINamespaceAttr, DINullTypeAttr, DIStringTypeAttr,
3102 DISubprogramAttr, DISubroutineTypeAttr, LoopAnnotationAttr,
3103 LoopVectorizeAttr, LoopInterleaveAttr, LoopUnrollAttr,
3104 LoopUnrollAndJamAttr, LoopLICMAttr, LoopDistributeAttr,
3105 LoopPipelineAttr, LoopPeeledAttr, LoopUnswitchAttr, TBAARootAttr,
3106 TBAATagAttr, TBAATypeDescriptorAttr>([&](
auto attr) {
3107 os << decltype(attr)::getMnemonic();
3108 return AliasResult::OverridableAlias;
3122 return emitOpError(
"must appear at the module level");
3130 void InlineAsmOp::getEffects(
3133 if (getHasSideEffects()) {
3144 auto ptrsVectorType = getPtrs().getType();
3145 Type expectedPtrsVectorType =
3150 if (ptrsVectorType != expectedPtrsVectorType)
3151 return emitOpError(
"expected operand #1 type to be ")
3152 << expectedPtrsVectorType;
3161 auto ptrsVectorType = getPtrs().getType();
3162 Type expectedPtrsVectorType =
3167 if (ptrsVectorType != expectedPtrsVectorType)
3168 return emitOpError(
"expected operand #2 type to be ")
3169 << expectedPtrsVectorType;
3177 void LLVMDialect::initialize() {
3178 registerAttributes();
3181 addTypes<LLVMVoidType,
3192 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3195 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3199 allowUnknownOperations();
3201 addInterfaces<LLVMOpAsmDialectInterface>();
3206 #define GET_OP_CLASSES
3207 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3209 #define GET_OP_CLASSES
3210 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3212 LogicalResult LLVMDialect::verifyDataLayoutString(
3216 if (maybeDataLayout)
3219 std::string message;
3220 llvm::raw_string_ostream messageStream(message);
3221 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
3222 reportError(
"invalid data layout descriptor: " + messageStream.str());
3227 LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
3233 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
3235 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
3236 return verifyDataLayoutString(
3237 stringAttr.getValue(),
3238 [op](
const Twine &message) { op->emitOpError() << message.str(); });
3241 << LLVM::LLVMDialect::getDataLayoutAttrName()
3242 <<
"' to be a string attributes";
3245 LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
3253 StringAttr name = paramAttr.
getName();
3255 auto checkUnitAttrType = [&]() -> LogicalResult {
3256 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
3257 return op->
emitError() << name <<
" should be a unit attribute";
3260 auto checkTypeAttrType = [&]() -> LogicalResult {
3261 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
3262 return op->
emitError() << name <<
" should be a type attribute";
3265 auto checkIntegerAttrType = [&]() -> LogicalResult {
3266 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
3267 return op->
emitError() << name <<
" should be an integer attribute";
3270 auto checkPointerType = [&]() -> LogicalResult {
3271 if (!llvm::isa<LLVMPointerType>(paramType))
3273 << name <<
" attribute attached to non-pointer LLVM type";
3276 auto checkIntegerType = [&]() -> LogicalResult {
3277 if (!llvm::isa<IntegerType>(paramType))
3279 << name <<
" attribute attached to non-integer LLVM type";
3282 auto checkPointerTypeMatches = [&]() -> LogicalResult {
3283 if (failed(checkPointerType()))
3290 if (name == LLVMDialect::getNoAliasAttrName() ||
3291 name == LLVMDialect::getReadonlyAttrName() ||
3292 name == LLVMDialect::getReadnoneAttrName() ||
3293 name == LLVMDialect::getWriteOnlyAttrName() ||
3294 name == LLVMDialect::getNestAttrName() ||
3295 name == LLVMDialect::getNoCaptureAttrName() ||
3296 name == LLVMDialect::getNoFreeAttrName() ||
3297 name == LLVMDialect::getNonNullAttrName()) {
3298 if (failed(checkUnitAttrType()))
3300 if (verifyValueType && failed(checkPointerType()))
3306 if (name == LLVMDialect::getStructRetAttrName() ||
3307 name == LLVMDialect::getByValAttrName() ||
3308 name == LLVMDialect::getByRefAttrName() ||
3309 name == LLVMDialect::getInAllocaAttrName() ||
3310 name == LLVMDialect::getPreallocatedAttrName()) {
3311 if (failed(checkTypeAttrType()))
3313 if (verifyValueType && failed(checkPointerTypeMatches()))
3319 if (name == LLVMDialect::getSExtAttrName() ||
3320 name == LLVMDialect::getZExtAttrName()) {
3321 if (failed(checkUnitAttrType()))
3323 if (verifyValueType && failed(checkIntegerType()))
3329 if (name == LLVMDialect::getAlignAttrName() ||
3330 name == LLVMDialect::getDereferenceableAttrName() ||
3331 name == LLVMDialect::getDereferenceableOrNullAttrName() ||
3332 name == LLVMDialect::getStackAlignmentAttrName()) {
3333 if (failed(checkIntegerAttrType()))
3335 if (verifyValueType && failed(checkPointerType()))
3341 if (name == LLVMDialect::getNoUndefAttrName() ||
3342 name == LLVMDialect::getInRegAttrName() ||
3343 name == LLVMDialect::getReturnedAttrName())
3344 return checkUnitAttrType();
3350 LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
3354 auto funcOp = dyn_cast<FunctionOpInterface>(op);
3357 Type argType = funcOp.getArgumentTypes()[argIdx];
3359 return verifyParameterAttribute(op, argType, argAttr);
3362 LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
3366 auto funcOp = dyn_cast<FunctionOpInterface>(op);
3369 Type resType = funcOp.getResultTypes()[resIdx];
3373 if (llvm::isa<LLVMVoidType>(resType))
3374 return op->
emitError() <<
"cannot attach result attributes to functions "
3375 "with a void return";
3379 auto name = resAttr.
getName();
3380 if (name == LLVMDialect::getAllocAlignAttrName() ||
3381 name == LLVMDialect::getAllocatedPointerAttrName() ||
3382 name == LLVMDialect::getByValAttrName() ||
3383 name == LLVMDialect::getByRefAttrName() ||
3384 name == LLVMDialect::getInAllocaAttrName() ||
3385 name == LLVMDialect::getNestAttrName() ||
3386 name == LLVMDialect::getNoCaptureAttrName() ||
3387 name == LLVMDialect::getNoFreeAttrName() ||
3388 name == LLVMDialect::getPreallocatedAttrName() ||
3389 name == LLVMDialect::getReadnoneAttrName() ||
3390 name == LLVMDialect::getReadonlyAttrName() ||
3391 name == LLVMDialect::getReturnedAttrName() ||
3392 name == LLVMDialect::getStackAlignmentAttrName() ||
3393 name == LLVMDialect::getStructRetAttrName() ||
3394 name == LLVMDialect::getWriteOnlyAttrName())
3395 return op->
emitError() << name <<
" is not a valid result attribute";
3396 return verifyParameterAttribute(op, resType, resAttr);
3404 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
3405 if (isa<LLVM::LLVMPointerType>(type))
3406 return builder.
create<LLVM::AddressOfOp>(loc, type, symbol);
3407 if (isa<LLVM::UndefAttr>(value))
3408 return builder.
create<LLVM::UndefOp>(loc, type);
3409 if (isa<LLVM::PoisonAttr>(value))
3410 return builder.
create<LLVM::PoisonOp>(loc, type);
3411 if (isa<LLVM::ZeroAttr>(value))
3412 return builder.
create<LLVM::ZeroOp>(loc, type);
3414 return LLVM::ConstantOp::materialize(builder, value, type, loc);
3422 StringRef name, StringRef value,
3423 LLVM::Linkage linkage) {
3426 "expected builder to point to a block constrained in an op");
3429 assert(module &&
"builder points to an op outside of a module");
3435 auto global = moduleBuilder.
create<LLVM::GlobalOp>(
3436 loc, type,
true, linkage, name,
3442 builder.
create<LLVM::AddressOfOp>(loc, ptrType, global.getSymNameAttr());
3443 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 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 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.
std::conditional_t< std::is_base_of< Attribute, llvm::detail::ValueOfRange< DynamicRange > >::value, Attribute, PointerUnion< IntegerAttr, llvm::detail::ValueOfRange< DynamicRange > >> value_type
Return type of 'operator[]' and the iterators 'operator*'.
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.
void addLLVMInlinerInterface(LLVMDialect *dialect)
Register the LLVMInlinerInterface implementation of DialectInlinerInterface with the LLVM dialect.
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.