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;
48 #include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
55 if (attr.
getName() ==
"fastmathFlags") {
57 FastmathFlagsAttr::get(attr.getValue().getContext(), {});
71 DictionaryAttr attrs) {
73 if (
auto iface = dyn_cast<IntegerOverflowFlagsInterface>(op))
76 {iface.getIntegerOverflowAttrName()});
91 << name <<
"' does not reference a valid LLVM function";
92 if (func.isExternal())
93 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
119 template <
typename Ty>
120 struct EnumTraits {};
122 #define REGISTER_ENUM_TYPE(Ty) \
124 struct EnumTraits<Ty> { \
125 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
126 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
138 template <
typename EnumTy,
typename RetTy = EnumTy>
141 EnumTy defaultValue) {
143 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
148 return static_cast<RetTy
>(defaultValue);
149 return static_cast<RetTy
>(index);
157 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
158 <<
", " << getOperand(1);
160 p <<
" : " << getLhs().getType();
164 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
165 <<
", " << getOperand(1);
167 p <<
" : " << getLhs().getType();
174 template <
typename CmpPredicateType>
176 StringAttr predicateAttr;
179 SMLoc predicateLoc, trailingTypeLoc;
191 int64_t predicateValue = 0;
192 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
193 std::optional<ICmpPredicate> predicate =
194 symbolizeICmpPredicate(predicateAttr.getValue());
197 <<
"'" << predicateAttr.getValue()
198 <<
"' is an incorrect value of the 'predicate' attribute";
199 predicateValue =
static_cast<int64_t
>(*predicate);
201 std::optional<FCmpPredicate> predicate =
202 symbolizeFCmpPredicate(predicateAttr.getValue());
205 <<
"'" << predicateAttr.getValue()
206 <<
"' is an incorrect value of the 'predicate' attribute";
207 predicateValue =
static_cast<int64_t
>(*predicate);
217 "expected LLVM dialect-compatible type");
223 return parseCmpOp<ICmpPredicate>(parser, result);
227 return parseCmpOp<FCmpPredicate>(parser, result);
233 ShapedType shapedType = dyn_cast<ShapedType>(type);
240 if (getPredicate() != ICmpPredicate::eq &&
241 getPredicate() != ICmpPredicate::ne)
245 if (getLhs() == getRhs())
247 getPredicate() == ICmpPredicate::eq);
250 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
252 getPredicate() == ICmpPredicate::ne);
255 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
256 Value lhs = getLhs();
257 Value rhs = getRhs();
258 getLhsMutable().assign(rhs);
259 getRhsMutable().assign(lhs);
277 p <<
' ' << getArraySize() <<
" x " << getElemType();
278 if (getAlignment() && *getAlignment() != 0)
280 {kElemTypeAttrName, getInallocaAttrName()});
284 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
285 p <<
" : " << funcTy;
293 SMLoc trailingTypeLoc;
305 std::optional<NamedAttribute> alignmentAttr =
307 if (alignmentAttr.has_value()) {
308 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
311 "expected integer alignment");
312 if (alignmentInt.getValue().isZero())
317 auto funcType = llvm::dyn_cast<FunctionType>(type);
318 if (!funcType || funcType.getNumInputs() != 1 ||
319 funcType.getNumResults() != 1)
322 "expected trailing function type with one argument and one result");
327 Type resultType = funcType.getResult(0);
328 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
331 result.
addTypes({funcType.getResult(0)});
337 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
338 targetExtType && !targetExtType.supportsMemOps())
340 <<
"this target extension type cannot be used in alloca";
345 Type AllocaOp::getResultPtrElementType() {
return getElemType(); }
352 assert(index == 0 &&
"invalid successor index");
361 assert(index < getNumSuccessors() &&
"invalid successor index");
363 : getFalseDestOperandsMutable());
369 std::optional<std::pair<uint32_t, uint32_t>> weights) {
374 static_cast<int32_t
>(weights->second)});
376 build(builder, result, condition, trueOperands, falseOperands, weightsAttr,
377 {}, trueDest, falseDest);
391 if (!branchWeights.empty())
394 build(builder, result, value, defaultOperands, caseOperands, caseValues,
395 weightsAttr, defaultDestination, caseDestinations);
404 if (!caseValues.empty()) {
406 static_cast<int64_t
>(caseValues.size()), value.
getType());
410 build(builder, result, value, defaultDestination, defaultOperands,
411 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
420 if (!caseValues.empty()) {
422 static_cast<int64_t
>(caseValues.size()), value.
getType());
426 build(builder, result, value, defaultDestination, defaultOperands,
427 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
443 auto parseCase = [&]() {
447 values.push_back(APInt(bitWidth, value));
460 caseDestinations.push_back(destination);
461 caseOperands.emplace_back(operands);
462 caseOperandTypes.emplace_back(operandTypes);
468 ShapedType caseValueType =
488 llvm::zip(caseValues, caseDestinations),
491 p << std::get<0>(i).getLimitedValue();
504 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
506 getCaseValues()->size() !=
507 static_cast<int64_t
>(getCaseDestinations().size())))
508 return emitOpError(
"expects number of case values to match number of "
509 "case destinations");
510 if (getBranchWeights() && getBranchWeights()->size() != getNumSuccessors())
511 return emitError(
"expects number of branch weights to match number of "
513 << getBranchWeights()->size() <<
" vs " << getNumSuccessors();
514 if (getCaseValues() &&
516 return emitError(
"expects case value type to match condition value type");
521 assert(index < getNumSuccessors() &&
"invalid successor index");
523 : getCaseOperandsMutable(index - 1));
530 constexpr int32_t GEPOp::kDynamicIndex;
534 getDynamicIndices());
539 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
540 return vectorType.getElementType();
541 if (
auto scalableVectorType = llvm::dyn_cast<LLVMScalableVectorType>(type))
542 return scalableVectorType.getElementType();
543 if (
auto fixedVectorType = llvm::dyn_cast<LLVMFixedVectorType>(type))
544 return fixedVectorType.getElementType();
556 for (
const GEPArg &iter : indices) {
561 bool requiresConst = !rawConstantIndices.empty() &&
563 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
567 rawConstantIndices.push_back(intC.getSExtValue());
569 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
570 dynamicIndices.push_back(val);
578 if (rawConstantIndices.size() == 1 || !currType)
583 .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
584 LLVMArrayType>([](
auto containerType) {
585 return containerType.getElementType();
588 int64_t memberIndex = rawConstantIndices.back();
589 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
591 return structType.
getBody()[memberIndex];
594 .Default(
Type(
nullptr));
621 build(builder, result, resultType, elementType, basePtr,
642 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
656 llvm::interleaveComma(
659 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
662 printer << cst.get<IntegerAttr>().getInt();
672 if (indexPos >= indices.
size())
678 if (!indices[indexPos].is<IntegerAttr>())
679 return emitOpError() <<
"expected index " << indexPos
680 <<
" indexing a struct to be constant";
682 int32_t gepIndex = indices[indexPos].get<IntegerAttr>().getInt();
685 static_cast<size_t>(gepIndex) >= elementTypes.size())
686 return emitOpError() <<
"index " << indexPos
687 <<
" indexing a struct is out of bounds";
692 indices, emitOpError);
694 .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
697 indices, emitOpError);
701 <<
"type " << otherType <<
" cannot be indexed (index #"
714 if (
static_cast<size_t>(
715 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
716 getDynamicIndices().size())
717 return emitOpError(
"expected as many dynamic indices as specified in '")
718 << getRawConstantIndicesAttrName().getValue() <<
"'";
721 [&] {
return emitOpError(); });
724 Type GEPOp::getResultPtrElementType() {
727 Type selectedType = getElemType();
732 llvm::drop_begin(indices)) {
737 if (
auto arrayType = dyn_cast<LLVMArrayType>(selectedType)) {
738 selectedType = arrayType.getElementType();
744 selectedType = cast<DestructurableTypeInterface>(selectedType)
745 .getTypeAtIndex(cast<IntegerAttr>(index));
757 void LoadOp::getEffects(
766 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
767 getOrdering() != AtomicOrdering::unordered)) {
777 if (llvm::isa<LLVMPointerType>(type))
778 return isPointerTypeAllowed;
780 std::optional<unsigned> bitWidth;
781 if (
auto floatType = llvm::dyn_cast<FloatType>(type)) {
784 bitWidth = floatType.getWidth();
786 if (
auto integerType = llvm::dyn_cast<IntegerType>(type))
787 bitWidth = integerType.getWidth();
791 return *bitWidth == 8 || *bitWidth == 16 || *bitWidth == 32 ||
796 template <
typename OpTy>
799 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
802 return memOp.emitOpError(
"unsupported type ")
803 << valueType <<
" for atomic access";
804 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
805 return memOp.emitOpError(
"unsupported ordering '")
806 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
807 if (!memOp.getAlignment())
808 return memOp.emitOpError(
"expected alignment for atomic access");
811 if (memOp.getSyncscope())
812 return memOp.emitOpError(
813 "expected syncscope to be null for non-atomic access");
818 Type valueType = getResult().getType();
820 {AtomicOrdering::release, AtomicOrdering::acq_rel});
824 Value addr,
unsigned alignment,
bool isVolatile,
825 bool isNonTemporal,
bool isInvariant,
826 AtomicOrdering ordering, StringRef syncscope) {
827 build(builder, state, type, addr,
829 isNonTemporal, isInvariant, ordering,
830 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
840 void StoreOp::getEffects(
849 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
850 getOrdering() != AtomicOrdering::unordered)) {
857 Type valueType = getValue().getType();
859 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
863 Value addr,
unsigned alignment,
bool isVolatile,
864 bool isNonTemporal, AtomicOrdering ordering,
865 StringRef syncscope) {
866 build(builder, state, value, addr,
868 isNonTemporal, ordering,
869 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
871 nullptr,
nullptr,
nullptr);
881 Type resultType = calleeType.getReturnType();
882 if (!isa<LLVM::LLVMVoidType>(resultType))
883 results.push_back(resultType);
894 resultType = results.front();
901 build(builder, state, results, builder.
getStringAttr(callee), args);
911 assert(callee &&
"expected non-null callee in direct call builder");
912 build(builder, state, results,
914 callee, args,
nullptr,
nullptr,
921 LLVMFunctionType calleeType, StringRef callee,
923 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
927 LLVMFunctionType calleeType, StringAttr callee,
939 nullptr,
nullptr,
nullptr);
943 LLVMFunctionType calleeType,
ValueRange args) {
954 auto calleeType = func.getFunctionType();
968 return getOperand(0);
974 auto symRef = callee.get<SymbolRefAttr>();
975 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
978 return setOperand(0, callee.get<
Value>());
982 return getOperands().drop_front(getCallee().has_value() ? 0 : 1);
987 getCalleeOperands().size());
994 if (callee.isExternal())
996 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1000 auto hasSubprogram = [](
Operation *op) {
1005 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1007 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1009 return callOp.emitError()
1010 <<
"inlinable function call in a function with a DISubprogram "
1011 "location must have a debug location";
1016 if (getNumResults() > 1)
1017 return emitOpError(
"must have 0 or 1 result");
1023 bool isIndirect =
false;
1029 if (!getNumOperands())
1031 "must have either a `callee` attribute or at least an operand");
1032 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).getType());
1034 return emitOpError(
"indirect call expects a pointer as callee: ")
1035 << getOperand(0).getType();
1042 return emitOpError()
1044 <<
"' does not reference a symbol in the current scope";
1045 auto fn = dyn_cast<LLVMFuncOp>(callee);
1047 return emitOpError() <<
"'" << calleeName.
getValue()
1048 <<
"' does not reference a valid LLVM function";
1052 fnType = fn.getFunctionType();
1055 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1057 return emitOpError(
"callee does not have a functional type: ") << fnType;
1059 if (funcType.isVarArg() && !getCalleeType())
1060 return emitOpError() <<
"missing callee type attribute for vararg call";
1064 if (!funcType.isVarArg() &&
1065 funcType.getNumParams() != (getNumOperands() - isIndirect))
1066 return emitOpError() <<
"incorrect number of operands ("
1067 << (getNumOperands() - isIndirect)
1068 <<
") for callee (expecting: "
1069 << funcType.getNumParams() <<
")";
1071 if (funcType.getNumParams() > (getNumOperands() - isIndirect))
1072 return emitOpError() <<
"incorrect number of operands ("
1073 << (getNumOperands() - isIndirect)
1074 <<
") for varargs callee (expecting at least: "
1075 << funcType.getNumParams() <<
")";
1077 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1078 if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1079 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1080 << getOperand(i + isIndirect).getType()
1081 <<
" != " << funcType.getParamType(i);
1083 if (getNumResults() == 0 &&
1084 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1085 return emitOpError() <<
"expected function call to produce a value";
1087 if (getNumResults() != 0 &&
1088 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1089 return emitOpError()
1090 <<
"calling function with void result must not produce values";
1092 if (getNumResults() > 1)
1093 return emitOpError()
1094 <<
"expected LLVM function call to produce 0 or 1 result";
1096 if (getNumResults() && getResult().getType() != funcType.getReturnType())
1097 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1098 <<
" != " << funcType.getReturnType();
1104 auto callee = getCallee();
1105 bool isDirect = callee.has_value();
1107 LLVMFunctionType calleeType;
1108 bool isVarArg =
false;
1110 if (std::optional<LLVMFunctionType> optionalCalleeType = getCalleeType()) {
1111 calleeType = *optionalCalleeType;
1112 isVarArg = calleeType.isVarArg();
1118 if (getCConv() != LLVM::CConv::C)
1119 p << stringifyCConv(getCConv()) <<
' ';
1128 auto args = getOperands().drop_front(isDirect ? 0 : 1);
1129 p <<
'(' << args <<
')';
1132 p <<
" vararg(" << calleeType <<
")";
1135 {getCConvAttrName(),
"callee",
"callee_type"});
1139 p << getOperand(0).getType() <<
", ";
1155 if (isDirect && types.size() != 1)
1156 return parser.
emitError(trailingTypesLoc,
1157 "expected direct call to have 1 trailing type");
1158 if (!isDirect && types.size() != 2)
1159 return parser.
emitError(trailingTypesLoc,
1160 "expected indirect call to have 2 trailing types");
1162 auto funcType = llvm::dyn_cast<FunctionType>(types.pop_back_val());
1164 return parser.
emitError(trailingTypesLoc,
1165 "expected trailing function type");
1166 if (funcType.getNumResults() > 1)
1167 return parser.
emitError(trailingTypesLoc,
1168 "expected function with 0 or 1 result");
1169 if (funcType.getNumResults() == 1 &&
1170 llvm::isa<LLVM::LLVMVoidType>(funcType.getResult(0)))
1171 return parser.
emitError(trailingTypesLoc,
1172 "expected a non-void result type");
1178 llvm::append_range(types, funcType.getInputs());
1182 if (funcType.getNumResults() != 0)
1183 result.
addTypes(funcType.getResults());
1196 if (
failed(*parseResult))
1197 return *parseResult;
1198 operands.push_back(funcPtrOperand);
1208 SymbolRefAttr funcAttr;
1209 TypeAttr calleeType;
1214 getCConvAttrName(result.
name),
1216 parser, result, LLVM::CConv::C)));
1221 bool isDirect = operands.empty();
1248 LLVMFunctionType CallOp::getCalleeFunctionType() {
1249 if (getCalleeType())
1250 return *getCalleeType();
1261 auto calleeType = func.getFunctionType();
1264 unwindOps,
nullptr,
nullptr, normal, unwind);
1271 build(builder, state, tys,
1273 ops, normalOps, unwindOps,
nullptr,
nullptr, normal, unwind);
1281 TypeAttr::get(calleeType), callee, ops, normalOps, unwindOps,
nullptr,
1282 nullptr, normal, unwind);
1286 assert(index < getNumSuccessors() &&
"invalid successor index");
1288 : getUnwindDestOperandsMutable());
1296 return getOperand(0);
1302 auto symRef = callee.get<SymbolRefAttr>();
1303 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1306 return setOperand(0, callee.get<
Value>());
1310 return getOperands().drop_front(getCallee().has_value() ? 0 : 1);
1315 getCalleeOperands().size());
1319 if (getNumResults() > 1)
1320 return emitOpError(
"must have 0 or 1 result");
1322 Block *unwindDest = getUnwindDest();
1323 if (unwindDest->
empty())
1324 return emitError(
"must have at least one operation in unwind destination");
1327 if (!isa<LandingpadOp>(unwindDest->
front()))
1328 return emitError(
"first operation in unwind destination should be a "
1329 "llvm.landingpad operation");
1335 auto callee = getCallee();
1336 bool isDirect = callee.has_value();
1338 LLVMFunctionType calleeType;
1339 bool isVarArg =
false;
1341 if (std::optional<LLVMFunctionType> optionalCalleeType = getCalleeType()) {
1342 calleeType = *optionalCalleeType;
1343 isVarArg = calleeType.isVarArg();
1349 if (getCConv() != LLVM::CConv::C)
1350 p << stringifyCConv(getCConv()) <<
' ';
1358 p <<
'(' << getOperands().drop_front(isDirect ? 0 : 1) <<
')';
1365 p <<
" vararg(" << calleeType <<
")";
1368 {InvokeOp::getOperandSegmentSizeAttr(),
"callee",
1369 "callee_type", InvokeOp::getCConvAttrName()});
1373 p << getOperand(0).getType() <<
", ";
1386 SymbolRefAttr funcAttr;
1387 TypeAttr calleeType;
1388 Block *normalDest, *unwindDest;
1394 getCConvAttrName(result.
name),
1396 parser, result, LLVM::CConv::C)));
1401 bool isDirect = operands.empty();
1435 result.
addAttribute(InvokeOp::getOperandSegmentSizeAttr(),
1437 {static_cast<int32_t>(operands.size()),
1438 static_cast<int32_t>(normalOperands.size()),
1439 static_cast<int32_t>(unwindOperands.size())}));
1443 LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1444 if (getCalleeType())
1445 return *getCalleeType();
1455 if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1456 if (!func.getPersonality())
1458 "llvm.landingpad needs to be in a function with a personality");
1464 if (!getCleanup() && getOperands().empty())
1465 return emitError(
"landingpad instruction expects at least one clause or "
1466 "cleanup attribute");
1468 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1469 value = getOperand(idx);
1470 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1477 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1480 <<
"global addresses expected as operand to "
1481 "bitcast used in clauses for landingpad";
1489 << idx <<
" is not a known constant - null, addressof, bitcast";
1496 p << (getCleanup() ?
" cleanup " :
" ");
1499 for (
auto value : getOperands()) {
1502 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1503 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1509 p <<
": " << getType();
1550 Type llvmType = containerType;
1552 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1560 for (int64_t idx : position) {
1561 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1562 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1563 emitError(
"position out of bounds: ") << idx;
1566 llvmType = arrayType.getElementType();
1567 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1569 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1570 emitError(
"position out of bounds: ") << idx;
1573 llvmType = structType.getBody()[idx];
1575 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1586 for (int64_t idx : position) {
1587 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1588 llvmType = structType.getBody()[idx];
1590 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1595 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1596 auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1598 while (insertValueOp) {
1599 if (getPosition() == insertValueOp.getPosition())
1600 return insertValueOp.getValue();
1602 std::min(getPosition().size(), insertValueOp.getPosition().size());
1613 if (getPosition().take_front(
min) ==
1614 insertValueOp.getPosition().take_front(
min))
1620 getContainerMutable().assign(insertValueOp.getContainer());
1621 result = getResult();
1622 insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1628 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1630 emitError, getContainer().getType(), getPosition());
1634 if (getRes().getType() != valueType)
1635 return emitOpError() <<
"Type mismatch: extracting from "
1636 << getContainer().getType() <<
" should produce "
1637 << valueType <<
" but this op returns "
1638 << getRes().getType();
1644 build(builder, state,
1659 [&](StringRef msg) {
1673 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1675 emitError, getContainer().getType(), getPosition());
1679 if (getValue().getType() != valueType)
1680 return emitOpError() <<
"Type mismatch: cannot insert "
1681 << getValue().getType() <<
" into "
1682 << getContainer().getType();
1692 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
1696 Type expectedType = parent.getFunctionType().getReturnType();
1697 if (llvm::isa<LLVMVoidType>(expectedType)) {
1701 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1705 if (llvm::isa<LLVMVoidType>(expectedType))
1708 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1711 if (expectedType != getArg().getType()) {
1713 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1727 assert(module &&
"unexpected operation outside of a module");
1732 return dyn_cast_or_null<GlobalOp>(
1737 return dyn_cast_or_null<LLVMFuncOp>(
1746 auto global = dyn_cast_or_null<GlobalOp>(symbol);
1747 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
1749 if (!global && !
function)
1751 "must reference a global defined by 'llvm.mlir.global' or 'llvm.func'");
1753 LLVMPointerType type = getType();
1754 if (global && global.getAddrSpace() != type.getAddressSpace())
1755 return emitOpError(
"pointer address space must match address space of the "
1756 "referenced global");
1766 StringRef symName) {
1774 Region &body = getBody();
1776 if (!isa<ComdatSelectorOp>(op))
1778 "only comdat selector symbols can appear in a comdat region");
1788 bool isConstant, Linkage linkage, StringRef name,
1789 Attribute value, uint64_t alignment,
unsigned addrSpace,
1790 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
1792 DIGlobalVariableExpressionAttr dbgExpr) {
1831 p <<
' ' << stringifyLinkage(getLinkage()) <<
' ';
1832 StringRef visibility = stringifyVisibility(getVisibility_());
1833 if (!visibility.empty())
1834 p << visibility <<
' ';
1835 if (getThreadLocal_())
1836 p <<
"thread_local ";
1837 if (
auto unnamedAddr = getUnnamedAddr()) {
1838 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
1846 if (
auto value = getValueOrNull())
1849 if (
auto comdat = getComdat())
1850 p <<
" comdat(" << *comdat <<
')';
1856 {SymbolTable::getSymbolAttrName(),
1857 getGlobalTypeAttrName(), getConstantAttrName(),
1858 getValueAttrName(), getLinkageAttrName(),
1859 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
1860 getVisibility_AttrName(), getComdatAttrName(),
1861 getUnnamedAddrAttrName()});
1864 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
1866 p <<
" : " << getType();
1868 Region &initializer = getInitializerRegion();
1869 if (!initializer.
empty()) {
1876 std::optional<SymbolRefAttr> attr) {
1881 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
1882 return op->
emitError() <<
"expected comdat symbol";
1900 ctx, parseOptionalLLVMKeyword<Linkage>(
1901 parser, result, LLVM::Linkage::External)));
1906 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
1907 parser, result, LLVM::Visibility::Default)));
1912 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
1938 SymbolRefAttr comdat;
1951 if (types.size() > 1)
1955 if (types.empty()) {
1956 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
1959 strAttr.getValue().size());
1960 types.push_back(arrayType);
1963 "type can only be omitted for string globals");
1979 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
1980 return intValue.getValue().isZero();
1981 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
1982 return fpValue.getValue().isZero();
1983 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
1985 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
1987 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
1994 ? !llvm::isa<LLVMVoidType, LLVMTokenType,
1995 LLVMMetadataType, LLVMLabelType>(getType())
1996 : llvm::isa<PointerElementTypeInterface>(getType());
1999 "expects type to be a valid element type for an LLVM global");
2001 return emitOpError(
"must appear at the module level");
2003 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2004 auto type = llvm::dyn_cast<LLVMArrayType>(getType());
2005 IntegerType elementType =
2006 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2007 if (!elementType || elementType.getWidth() != 8 ||
2008 type.getNumElements() != strAttr.getValue().size())
2010 "requires an i8 array type of the length equal to that of the string "
2014 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getType())) {
2015 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2016 return emitOpError()
2017 <<
"this target extension type cannot be used in a global";
2020 return emitOpError() <<
"global with target extension type can only be "
2021 "initialized with zero-initializer";
2024 if (getLinkage() == Linkage::Common) {
2025 if (
Attribute value = getValueOrNull()) {
2027 return emitOpError()
2028 <<
"expected zero value for '"
2029 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2034 if (getLinkage() == Linkage::Appending) {
2035 if (!llvm::isa<LLVMArrayType>(getType())) {
2036 return emitOpError() <<
"expected array type for '"
2037 << stringifyLinkage(Linkage::Appending)
2045 std::optional<uint64_t> alignAttr = getAlignment();
2046 if (alignAttr.has_value()) {
2047 uint64_t value = alignAttr.value();
2048 if (!llvm::isPowerOf2_64(value))
2049 return emitError() <<
"alignment attribute is not a power of 2";
2056 if (
Block *b = getInitializerBlock()) {
2057 ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2058 if (ret.operand_type_begin() == ret.operand_type_end())
2059 return emitOpError(
"initializer region cannot return void");
2060 if (*ret.operand_type_begin() != getType())
2061 return emitOpError(
"initializer region type ")
2062 << *ret.operand_type_begin() <<
" does not match global type "
2066 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2067 if (!iface || !iface.hasNoEffect())
2069 <<
"ops with side effects not allowed in global initializers";
2072 if (getValueOrNull())
2073 return emitOpError(
"cannot have both initializer value and region");
2094 if (getCtors().size() != getPriorities().size())
2096 "mismatch between the number of ctors and the number of priorities");
2115 if (getDtors().size() != getPriorities().size())
2117 "mismatch between the number of dtors and the number of priorities");
2128 auto containerType = v1.
getType();
2132 build(builder, state, vType, v1, v2, mask);
2133 state.addAttributes(attrs);
2146 "expected an LLVM compatible vector type");
2158 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2159 return emitOpError(
"expected a splat operation for scalable vectors");
2169 assert(empty() &&
"function already has an entry block");
2174 LLVMFunctionType type = getFunctionType();
2175 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2176 entry->
addArgument(type.getParamType(i), getLoc());
2181 StringRef name,
Type type, LLVM::Linkage linkage,
2182 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2185 std::optional<uint64_t> functionEntryCount) {
2201 if (functionEntryCount)
2204 if (argAttrs.empty())
2207 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2208 "expected as many argument attribute lists as arguments");
2210 builder, result, argAttrs, std::nullopt,
2211 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2222 if (outputs.size() > 1) {
2223 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2224 "one function result");
2230 for (
auto t : inputs) {
2232 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2233 "type for function arguments");
2236 llvmInputs.push_back(t);
2243 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2244 "type for function results")
2262 getLinkageAttrName(result.
name),
2264 parseOptionalLLVMKeyword<Linkage>(
2265 parser, result, LLVM::Linkage::External)));
2270 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2271 parser, result, LLVM::Visibility::Default)));
2276 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2281 getCConvAttrName(result.
name),
2283 parser, result, LLVM::CConv::C)));
2285 StringAttr nameAttr;
2295 parser,
true, entryArgs, isVariadic, resultTypes,
2300 for (
auto &arg : entryArgs)
2301 argTypes.push_back(arg.type);
2311 int64_t minRange, maxRange;
2318 getVscaleRangeAttrName(result.
name),
2325 SymbolRefAttr comdat;
2336 parser.
getBuilder(), result, entryArgs, resultAttrs,
2337 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2350 if (getLinkage() != LLVM::Linkage::External)
2351 p << stringifyLinkage(getLinkage()) <<
' ';
2352 StringRef visibility = stringifyVisibility(getVisibility_());
2353 if (!visibility.empty())
2354 p << visibility <<
' ';
2355 if (
auto unnamedAddr = getUnnamedAddr()) {
2356 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2360 if (getCConv() != LLVM::CConv::C)
2361 p << stringifyCConv(getCConv()) <<
' ';
2365 LLVMFunctionType fnType = getFunctionType();
2368 argTypes.reserve(fnType.getNumParams());
2369 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
2370 argTypes.push_back(fnType.getParamType(i));
2372 Type returnType = fnType.getReturnType();
2373 if (!llvm::isa<LLVMVoidType>(returnType))
2374 resTypes.push_back(returnType);
2377 isVarArg(), resTypes);
2380 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
2381 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
2382 << vscale->getMaxRange().getInt() <<
')';
2385 if (
auto comdat = getComdat())
2386 p <<
" comdat(" << *comdat <<
')';
2390 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
2391 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
2392 getComdatAttrName(), getUnnamedAddrAttrName(),
2393 getVscaleRangeAttrName()});
2396 Region &body = getBody();
2397 if (!body.empty()) {
2409 if (getLinkage() == LLVM::Linkage::Common)
2410 return emitOpError() <<
"functions cannot have '"
2411 << stringifyLinkage(LLVM::Linkage::Common)
2418 if (getLinkage() != LLVM::Linkage::External &&
2419 getLinkage() != LLVM::Linkage::ExternWeak)
2420 return emitOpError() <<
"external functions must have '"
2421 << stringifyLinkage(LLVM::Linkage::External)
2423 << stringifyLinkage(LLVM::Linkage::ExternWeak)
2428 Type landingpadResultTy;
2429 StringRef diagnosticMessage;
2430 bool isLandingpadTypeConsistent =
2432 const auto checkType = [&](
Type type, StringRef errorMessage) {
2433 if (!landingpadResultTy) {
2434 landingpadResultTy = type;
2437 if (landingpadResultTy != type) {
2438 diagnosticMessage = errorMessage;
2444 .Case<LandingpadOp>([&](
auto landingpad) {
2445 constexpr StringLiteral errorMessage =
2446 "'llvm.landingpad' should have a consistent result type "
2447 "inside a function";
2448 return checkType(landingpad.getType(), errorMessage);
2450 .Case<ResumeOp>([&](
auto resume) {
2451 constexpr StringLiteral errorMessage =
2452 "'llvm.resume' should have a consistent input type inside a "
2454 return checkType(resume.getValue().getType(), errorMessage);
2457 }).wasInterrupted();
2458 if (!isLandingpadTypeConsistent) {
2459 assert(!diagnosticMessage.empty() &&
2460 "Expecting a non-empty diagnostic message");
2473 unsigned numArguments = getFunctionType().getNumParams();
2474 Block &entryBlock = front();
2475 for (
unsigned i = 0; i < numArguments; ++i) {
2478 return emitOpError(
"entry block argument #")
2479 << i <<
" is not of LLVM type";
2485 Region *LLVMFuncOp::getCallableRegion() {
2496 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getType()))
2497 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
2498 return emitOpError()
2499 <<
"target extension type does not support zero-initializer";
2509 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
2510 auto arrayType = llvm::dyn_cast<LLVMArrayType>(getType());
2511 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
2512 !arrayType.getElementType().isInteger(8)) {
2513 return emitOpError() <<
"expected array type of "
2514 << sAttr.getValue().size()
2515 <<
" i8 elements for the string constant";
2519 if (
auto structType = llvm::dyn_cast<LLVMStructType>(getType())) {
2520 if (structType.getBody().size() != 2 ||
2521 structType.getBody()[0] != structType.getBody()[1]) {
2522 return emitError() <<
"expected struct type with two elements of the "
2523 "same type, the type of a complex constant";
2526 auto arrayAttr = llvm::dyn_cast<ArrayAttr>(getValue());
2527 if (!arrayAttr || arrayAttr.size() != 2) {
2528 return emitOpError() <<
"expected array attribute with two elements, "
2529 "representing a complex constant";
2531 auto re = llvm::dyn_cast<TypedAttr>(arrayAttr[0]);
2532 auto im = llvm::dyn_cast<TypedAttr>(arrayAttr[1]);
2533 if (!re || !im || re.getType() != im.getType()) {
2534 return emitOpError()
2535 <<
"expected array attribute with two elements of the same type";
2538 Type elementType = structType.getBody()[0];
2539 if (!llvm::isa<IntegerType, Float16Type, Float32Type, Float64Type>(
2542 <<
"expected struct element types to be floating point type or "
2547 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getType())) {
2548 return emitOpError() <<
"does not support target extension type.";
2550 if (!llvm::isa<IntegerAttr, ArrayAttr, FloatAttr, ElementsAttr>(getValue()))
2551 return emitOpError()
2552 <<
"only supports integer, float, string or elements attributes";
2553 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
2554 if (!llvm::isa<IntegerType>(getType()))
2555 return emitOpError() <<
"expected integer type";
2557 if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
2558 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
2559 unsigned floatWidth = APFloat::getSizeInBits(sem);
2560 if (
auto floatTy = dyn_cast<FloatType>(getType())) {
2561 if (floatTy.getWidth() != floatWidth) {
2562 return emitOpError() <<
"expected float type of width " << floatWidth;
2567 if (getType().isa<IntegerType>() && !getType().isInteger(floatWidth)) {
2568 return emitOpError() <<
"expected integer type of width " << floatWidth;
2571 if (
auto splatAttr = dyn_cast<SplatElementsAttr>(getValue())) {
2572 if (!getType().isa<VectorType>() && !getType().isa<LLVM::LLVMArrayType>() &&
2573 !getType().isa<LLVM::LLVMFixedVectorType>() &&
2574 !getType().isa<LLVM::LLVMScalableVectorType>())
2575 return emitOpError() <<
"expected vector or array type";
2580 bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
2582 auto typedAttr = dyn_cast<TypedAttr>(value);
2589 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
2594 if (isBuildableWith(value, type))
2595 return builder.
create<LLVM::ConstantOp>(loc, cast<TypedAttr>(value));
2600 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
2608 AtomicOrdering ordering, StringRef syncscope,
2609 unsigned alignment,
bool isVolatile) {
2610 build(builder, state, val.
getType(), binOp, ptr, val, ordering,
2611 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
2614 nullptr,
nullptr,
nullptr);
2618 auto valType = getVal().getType();
2619 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
2620 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax) {
2622 return emitOpError(
"expected LLVM IR floating point type");
2623 }
else if (getBinOp() == AtomicBinOp::xchg) {
2625 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
2627 auto intType = llvm::dyn_cast<IntegerType>(valType);
2628 unsigned intBitWidth = intType ? intType.getWidth() : 0;
2629 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
2631 return emitOpError(
"expected LLVM IR integer type");
2634 if (
static_cast<unsigned>(getOrdering()) <
2635 static_cast<unsigned>(AtomicOrdering::monotonic))
2636 return emitOpError() <<
"expected at least '"
2637 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
2650 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
2655 AtomicOrdering successOrdering,
2656 AtomicOrdering failureOrdering, StringRef syncscope,
2657 unsigned alignment,
bool isWeak,
bool isVolatile) {
2659 successOrdering, failureOrdering,
2660 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
2662 isVolatile,
nullptr,
2663 nullptr,
nullptr,
nullptr);
2667 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().getType());
2669 return emitOpError(
"expected LLVM IR pointer type for operand #0");
2670 auto valType = getVal().getType();
2673 return emitOpError(
"unexpected LLVM IR type");
2674 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
2675 getFailureOrdering() < AtomicOrdering::monotonic)
2676 return emitOpError(
"ordering must be at least 'monotonic'");
2677 if (getFailureOrdering() == AtomicOrdering::release ||
2678 getFailureOrdering() == AtomicOrdering::acq_rel)
2679 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
2688 AtomicOrdering ordering, StringRef syncscope) {
2689 build(builder, state, ordering,
2690 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
2694 if (getOrdering() == AtomicOrdering::not_atomic ||
2695 getOrdering() == AtomicOrdering::unordered ||
2696 getOrdering() == AtomicOrdering::monotonic)
2697 return emitOpError(
"can be given only acquire, release, acq_rel, "
2698 "and seq_cst orderings");
2708 template <
class ExtOp>
2710 IntegerType inputType, outputType;
2714 "input type is a vector but output type is an integer");
2717 return op.
emitError(
"input and output vectors are of incompatible shape");
2726 inputType = cast<IntegerType>(op.getArg().getType());
2730 "input type is an integer but output type is a vector");
2733 if (outputType.getWidth() <= inputType.getWidth())
2734 return op.
emitError(
"integer width of the output type is smaller or "
2735 "equal to the integer width of the input type");
2746 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
2750 size_t targetSize = cast<IntegerType>(getType()).getWidth();
2764 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
2766 if (getArg().getType() == getType())
2769 if (
auto prev = getArg().getDefiningOp<BitcastOp>())
2770 if (prev.getArg().getType() == getType())
2771 return prev.getArg();
2776 auto resultType = llvm::dyn_cast<LLVMPointerType>(
2778 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
2783 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
2784 return emitOpError(
"can only cast pointers from and to pointers");
2789 auto isVector = [](
Type type) {
2790 return llvm::isa<VectorType, LLVMScalableVectorType, LLVMFixedVectorType>(
2796 if (isVector(getResult().getType()) && !isVector(getArg().getType()))
2797 return emitOpError(
"cannot cast pointer to vector of pointers");
2799 if (!isVector(getResult().getType()) && isVector(getArg().getType()))
2800 return emitOpError(
"cannot cast vector of pointers to pointer");
2804 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
2805 return emitOpError(
"cannot cast pointers of different address spaces, "
2806 "use 'llvm.addrspacecast' instead");
2815 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
2817 if (getArg().getType() == getType())
2820 if (
auto prev = getArg().getDefiningOp<AddrSpaceCastOp>())
2821 if (prev.getArg().getType() == getType())
2822 return prev.getArg();
2832 adaptor.getDynamicIndices());
2835 if (
getBase().getType() == getType() && indices.
size() == 1)
2836 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
2837 if (integer.getValue().isZero())
2841 bool changed =
false;
2844 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
2851 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
2852 gepArgs.emplace_back(val);
2854 gepArgs.emplace_back(existing.get<IntegerAttr>().getInt());
2860 gepArgs.emplace_back(integer.getInt());
2868 getDynamicIndicesMutable().assign(dynamicIndices);
2869 setRawConstantIndices(rawConstantIndices);
2870 return Value{*
this};
2881 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
2885 if (rhs.getValue().getZExtValue() >=
2886 getLhs().getType().getIntOrFloatBitWidth())
2889 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
2901 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
2905 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
2917 if (!getIntrin().starts_with(
"llvm."))
2918 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
2932 .Case<AccessGroupAttr, AliasScopeAttr, AliasScopeDomainAttr,
2933 DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
2934 DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr,
2935 DIGlobalVariableExpressionAttr, DILabelAttr, DILexicalBlockAttr,
2936 DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
2937 DINamespaceAttr, DINullTypeAttr, DISubprogramAttr,
2938 DISubroutineTypeAttr, LoopAnnotationAttr, LoopVectorizeAttr,
2939 LoopInterleaveAttr, LoopUnrollAttr, LoopUnrollAndJamAttr,
2940 LoopLICMAttr, LoopDistributeAttr, LoopPipelineAttr,
2941 LoopPeeledAttr, LoopUnswitchAttr, TBAARootAttr, TBAATagAttr,
2942 TBAATypeDescriptorAttr>([&](
auto attr) {
2943 os << decltype(attr)::getMnemonic();
2944 return AliasResult::OverridableAlias;
2958 return emitOpError(
"must appear at the module level");
2966 void LLVMDialect::initialize() {
2967 registerAttributes();
2970 addTypes<LLVMVoidType,
2982 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
2985 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
2989 allowUnknownOperations();
2991 addInterfaces<LLVMOpAsmDialectInterface>();
2996 #define GET_OP_CLASSES
2997 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
2999 #define GET_OP_CLASSES
3000 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3006 if (maybeDataLayout)
3009 std::string message;
3010 llvm::raw_string_ostream messageStream(message);
3011 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
3012 reportError(
"invalid data layout descriptor: " + messageStream.str());
3023 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
3025 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
3026 return verifyDataLayoutString(
3027 stringAttr.getValue(),
3028 [op](
const Twine &message) { op->emitOpError() << message.str(); });
3031 << LLVM::LLVMDialect::getDataLayoutAttrName()
3032 <<
"' to be a string attributes";
3043 StringAttr name = paramAttr.
getName();
3046 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
3047 return op->
emitError() << name <<
" should be a unit attribute";
3051 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
3052 return op->
emitError() << name <<
" should be a type attribute";
3056 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
3057 return op->
emitError() << name <<
" should be an integer attribute";
3061 if (!llvm::isa<LLVMPointerType>(paramType))
3063 << name <<
" attribute attached to non-pointer LLVM type";
3067 if (!llvm::isa<IntegerType>(paramType))
3069 << name <<
" attribute attached to non-integer LLVM type";
3073 if (
failed(checkPointerType()))
3080 if (name == LLVMDialect::getNoAliasAttrName() ||
3081 name == LLVMDialect::getReadonlyAttrName() ||
3082 name == LLVMDialect::getReadnoneAttrName() ||
3083 name == LLVMDialect::getWriteOnlyAttrName() ||
3084 name == LLVMDialect::getNestAttrName() ||
3085 name == LLVMDialect::getNoCaptureAttrName() ||
3086 name == LLVMDialect::getNoFreeAttrName() ||
3087 name == LLVMDialect::getNonNullAttrName()) {
3088 if (
failed(checkUnitAttrType()))
3090 if (verifyValueType &&
failed(checkPointerType()))
3096 if (name == LLVMDialect::getStructRetAttrName() ||
3097 name == LLVMDialect::getByValAttrName() ||
3098 name == LLVMDialect::getByRefAttrName() ||
3099 name == LLVMDialect::getInAllocaAttrName() ||
3100 name == LLVMDialect::getPreallocatedAttrName()) {
3101 if (
failed(checkTypeAttrType()))
3103 if (verifyValueType &&
failed(checkPointerTypeMatches()))
3109 if (name == LLVMDialect::getSExtAttrName() ||
3110 name == LLVMDialect::getZExtAttrName()) {
3111 if (
failed(checkUnitAttrType()))
3113 if (verifyValueType &&
failed(checkIntegerType()))
3119 if (name == LLVMDialect::getAlignAttrName() ||
3120 name == LLVMDialect::getDereferenceableAttrName() ||
3121 name == LLVMDialect::getDereferenceableOrNullAttrName() ||
3122 name == LLVMDialect::getStackAlignmentAttrName()) {
3123 if (
failed(checkIntegerAttrType()))
3125 if (verifyValueType &&
failed(checkPointerType()))
3131 if (name == LLVMDialect::getNoUndefAttrName() ||
3132 name == LLVMDialect::getInRegAttrName() ||
3133 name == LLVMDialect::getReturnedAttrName())
3134 return checkUnitAttrType();
3144 auto funcOp = dyn_cast<FunctionOpInterface>(op);
3147 Type argType = funcOp.getArgumentTypes()[argIdx];
3149 return verifyParameterAttribute(op, argType, argAttr);
3156 auto funcOp = dyn_cast<FunctionOpInterface>(op);
3159 Type resType = funcOp.getResultTypes()[resIdx];
3163 if (llvm::isa<LLVMVoidType>(resType))
3164 return op->
emitError() <<
"cannot attach result attributes to functions "
3165 "with a void return";
3169 auto name = resAttr.
getName();
3170 if (name == LLVMDialect::getAllocAlignAttrName() ||
3171 name == LLVMDialect::getAllocatedPointerAttrName() ||
3172 name == LLVMDialect::getByValAttrName() ||
3173 name == LLVMDialect::getByRefAttrName() ||
3174 name == LLVMDialect::getInAllocaAttrName() ||
3175 name == LLVMDialect::getNestAttrName() ||
3176 name == LLVMDialect::getNoCaptureAttrName() ||
3177 name == LLVMDialect::getNoFreeAttrName() ||
3178 name == LLVMDialect::getPreallocatedAttrName() ||
3179 name == LLVMDialect::getReadnoneAttrName() ||
3180 name == LLVMDialect::getReadonlyAttrName() ||
3181 name == LLVMDialect::getReturnedAttrName() ||
3182 name == LLVMDialect::getStackAlignmentAttrName() ||
3183 name == LLVMDialect::getStructRetAttrName() ||
3184 name == LLVMDialect::getWriteOnlyAttrName())
3185 return op->
emitError() << name <<
" is not a valid result attribute";
3186 return verifyParameterAttribute(op, resType, resAttr);
3191 return LLVM::ConstantOp::materialize(builder, value, type, loc);
3199 StringRef name, StringRef value,
3200 LLVM::Linkage linkage) {
3203 "expected builder to point to a block constrained in an op");
3206 assert(module &&
"builder points to an op outside of a module");
3212 auto global = moduleBuilder.
create<LLVM::GlobalOp>(
3213 loc, type,
true, linkage, name,
3219 builder.
create<LLVM::AddressOfOp>(loc, ptrType, global.getSymNameAttr());
3220 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)
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 bool isTypeCompatibleWithAtomicOp(Type type, bool isPointerTypeAllowed)
Returns true if the given type is supported by atomic operations.
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 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 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 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 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 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 parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
ParseResult 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)
MLIRContext * getContext() const
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
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 represents success/failure for parsing-like operations that find it important to chain tog...
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.
bool isa_and_nonnull() const
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.
std::optional< Operation::operand_range > getIndices(Operation *op)
Get and set the indices that the given load/store operation is operating on.
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.
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.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
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...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
A callable is either a symbol, or an SSA value, that is referenced by a call-like operation.
This class represents an efficient way to signal success or failure.
bool succeeded() const
Returns true if the provided LogicalResult corresponds to a success value.
bool failed() const
Returns true if the provided LogicalResult corresponds to a failure value.
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)
void addTypes(ArrayRef< Type > newTypes)
Region * addRegion()
Create a region that should be attached to the operation.