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) {
85 << name <<
"' does not reference a valid LLVM function";
86 if (func.isExternal())
87 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
105 p <<
" \"" << stringifyICmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
106 <<
", " << getOperand(1);
108 p <<
" : " << getLhs().getType();
112 p <<
" \"" << stringifyFCmpPredicate(getPredicate()) <<
"\" " << getOperand(0)
113 <<
", " << getOperand(1);
115 p <<
" : " << getLhs().getType();
122 template <
typename CmpPredicateType>
124 StringAttr predicateAttr;
127 SMLoc predicateLoc, trailingTypeLoc;
139 int64_t predicateValue = 0;
140 if (std::is_same<CmpPredicateType, ICmpPredicate>()) {
141 std::optional<ICmpPredicate> predicate =
142 symbolizeICmpPredicate(predicateAttr.getValue());
145 <<
"'" << predicateAttr.getValue()
146 <<
"' is an incorrect value of the 'predicate' attribute";
147 predicateValue =
static_cast<int64_t
>(*predicate);
149 std::optional<FCmpPredicate> predicate =
150 symbolizeFCmpPredicate(predicateAttr.getValue());
153 <<
"'" << predicateAttr.getValue()
154 <<
"' is an incorrect value of the 'predicate' attribute";
155 predicateValue =
static_cast<int64_t
>(*predicate);
165 "expected LLVM dialect-compatible type");
171 return parseCmpOp<ICmpPredicate>(parser, result);
175 return parseCmpOp<FCmpPredicate>(parser, result);
181 ShapedType shapedType = dyn_cast<ShapedType>(type);
188 if (getPredicate() != ICmpPredicate::eq &&
189 getPredicate() != ICmpPredicate::ne)
193 if (getLhs() == getRhs())
195 getPredicate() == ICmpPredicate::eq);
198 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
200 getPredicate() == ICmpPredicate::ne);
203 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
204 Value lhs = getLhs();
205 Value rhs = getRhs();
206 getLhsMutable().assign(rhs);
207 getRhsMutable().assign(lhs);
219 Type elemTy = llvm::cast<LLVM::LLVMPointerType>(getType()).getElementType();
221 elemTy = *getElemType();
229 p <<
' ' << getArraySize() <<
" x " << elemTy;
230 if (getAlignment() && *getAlignment() != 0)
232 {kElemTypeAttrName, getInallocaAttrName()});
236 {getAlignmentAttrName(), kElemTypeAttrName, getInallocaAttrName()});
237 p <<
" : " << funcTy;
245 SMLoc trailingTypeLoc;
257 std::optional<NamedAttribute> alignmentAttr =
259 if (alignmentAttr.has_value()) {
260 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
263 "expected integer alignment");
264 if (alignmentInt.getValue().isZero())
269 auto funcType = llvm::dyn_cast<FunctionType>(type);
270 if (!funcType || funcType.getNumInputs() != 1 ||
271 funcType.getNumResults() != 1)
274 "expected trailing function type with one argument and one result");
279 Type resultType = funcType.getResult(0);
280 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType)) {
281 if (ptrResultType.isOpaque())
285 result.
addTypes({funcType.getResult(0)});
292 std::optional<Type> ptrElementType) {
293 if (ptrType.isOpaque() && !ptrElementType.has_value()) {
295 <<
"' attribute if opaque pointer type is used";
297 if (!ptrType.isOpaque() && ptrElementType.has_value()) {
300 <<
"' attribute when non-opaque pointer type is used";
306 LLVMPointerType ptrType = llvm::cast<LLVMPointerType>(getType());
311 (ptrType.isOpaque()) ? *getElemType() : ptrType.getElementType();
313 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(elemTy);
314 targetExtType && !targetExtType.supportsMemOps())
316 <<
"this target extension type cannot be used in alloca";
321 Type AllocaOp::getResultPtrElementType() {
323 return getElemType().has_value() ? *getElemType()
332 assert(index == 0 &&
"invalid successor index");
341 assert(index < getNumSuccessors() &&
"invalid successor index");
343 : getFalseDestOperandsMutable());
349 std::optional<std::pair<uint32_t, uint32_t>> weights) {
354 static_cast<int32_t
>(weights->second)});
356 build(builder, result, condition, trueOperands, falseOperands, weightsAttr,
357 {}, trueDest, falseDest);
371 if (!branchWeights.empty())
374 build(builder, result, value, defaultOperands, caseOperands, caseValues,
375 weightsAttr, defaultDestination, caseDestinations);
384 if (!caseValues.empty()) {
386 static_cast<int64_t
>(caseValues.size()), value.
getType());
390 build(builder, result, value, defaultDestination, defaultOperands,
391 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
400 if (!caseValues.empty()) {
402 static_cast<int64_t
>(caseValues.size()), value.
getType());
406 build(builder, result, value, defaultDestination, defaultOperands,
407 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
423 auto parseCase = [&]() {
427 values.push_back(APInt(bitWidth, value));
440 caseDestinations.push_back(destination);
441 caseOperands.emplace_back(operands);
442 caseOperandTypes.emplace_back(operandTypes);
448 ShapedType caseValueType =
468 llvm::zip(caseValues, caseDestinations),
471 p << std::get<0>(i).getLimitedValue();
484 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
486 getCaseValues()->size() !=
487 static_cast<int64_t
>(getCaseDestinations().size())))
488 return emitOpError(
"expects number of case values to match number of "
489 "case destinations");
490 if (getBranchWeights() && getBranchWeights()->size() != getNumSuccessors())
491 return emitError(
"expects number of branch weights to match number of "
493 << getBranchWeights()->size() <<
" vs " << getNumSuccessors();
494 if (getCaseValues() &&
496 return emitError(
"expects case value type to match condition value type");
501 assert(index < getNumSuccessors() &&
"invalid successor index");
503 : getCaseOperandsMutable(index - 1));
510 constexpr int32_t GEPOp::kDynamicIndex;
514 getDynamicIndices());
519 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
520 return vectorType.getElementType();
521 if (
auto scalableVectorType = llvm::dyn_cast<LLVMScalableVectorType>(type))
522 return scalableVectorType.getElementType();
523 if (
auto fixedVectorType = llvm::dyn_cast<LLVMFixedVectorType>(type))
524 return fixedVectorType.getElementType();
533 assert(!ptrType.isOpaque() &&
534 "expected non-opaque pointer, provide elementType explicitly when "
535 "opaque pointers are used");
536 build(builder, result, resultType, ptrType.getElementType(), basePtr, indices,
537 inbounds, attributes);
548 for (
const GEPArg &iter : indices) {
553 bool requiresConst = !rawConstantIndices.empty() &&
555 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
559 rawConstantIndices.push_back(intC.getSExtValue());
561 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
562 dynamicIndices.push_back(val);
570 if (rawConstantIndices.size() == 1 || !currType)
575 .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
576 LLVMArrayType>([](
auto containerType) {
577 return containerType.getElementType();
580 int64_t memberIndex = rawConstantIndices.back();
581 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
583 return structType.
getBody()[memberIndex];
586 .Default(
Type(
nullptr));
616 inbounds, attributes);
622 build(builder, result, resultType, elementType, basePtr,
643 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
657 llvm::interleaveComma(
660 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
663 printer << cst.get<IntegerAttr>().getInt();
669 class GEPIndexError :
public llvm::ErrorInfo<GEPIndexError> {
676 std::error_code convertToErrorCode()
const override {
677 return llvm::inconvertibleErrorCode();
680 explicit GEPIndexError(
unsigned pos) : indexPos(pos) {}
684 struct GEPIndexOutOfBoundError
685 :
public llvm::ErrorInfo<GEPIndexOutOfBoundError, GEPIndexError> {
688 using ErrorInfo::ErrorInfo;
690 void log(llvm::raw_ostream &os)
const override {
691 os <<
"index " << indexPos <<
" indexing a struct is out of bounds";
696 struct GEPStaticIndexError
697 :
public llvm::ErrorInfo<GEPStaticIndexError, GEPIndexError> {
700 using ErrorInfo::ErrorInfo;
702 void log(llvm::raw_ostream &os)
const override {
703 os <<
"expected index " << indexPos <<
" indexing a struct "
717 if (indexPos >= indices.
size())
723 if (!indices[indexPos].is<IntegerAttr>())
724 return llvm::make_error<GEPStaticIndexError>(indexPos);
726 int32_t gepIndex = indices[indexPos].get<IntegerAttr>().getInt();
729 static_cast<size_t>(gepIndex) >= elementTypes.size())
730 return llvm::make_error<GEPIndexOutOfBoundError>(indexPos);
737 .Case<VectorType, LLVMScalableVectorType, LLVMFixedVectorType,
738 LLVMArrayType>([&](
auto containerType) -> llvm::Error {
760 if (
static_cast<size_t>(
761 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
762 getDynamicIndices().size())
763 return emitOpError(
"expected as many dynamic indices as specified in '")
764 << getRawConstantIndicesAttrName().getValue() <<
"'";
766 if (llvm::Error err =
773 Type LLVM::GEPOp::getSourceElementType() {
774 if (std::optional<Type> elemType = getElemType())
777 return llvm::cast<LLVMPointerType>(
782 Type GEPOp::getResultPtrElementType() {
785 Type selectedType = getSourceElementType();
790 llvm::drop_begin(indices)) {
795 if (
auto arrayType = dyn_cast<LLVMArrayType>(selectedType)) {
796 selectedType = arrayType.getElementType();
802 selectedType = cast<DestructurableTypeInterface>(selectedType)
803 .getTypeAtIndex(cast<IntegerAttr>(index));
815 void LoadOp::getEffects(
824 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
825 getOrdering() != AtomicOrdering::unordered)) {
835 if (llvm::isa<LLVMPointerType>(type))
836 return isPointerTypeAllowed;
838 std::optional<unsigned> bitWidth;
839 if (
auto floatType = llvm::dyn_cast<FloatType>(type)) {
842 bitWidth = floatType.getWidth();
844 if (
auto integerType = llvm::dyn_cast<IntegerType>(type))
845 bitWidth = integerType.getWidth();
849 return *bitWidth == 8 || *bitWidth == 16 || *bitWidth == 32 ||
854 template <
typename OpTy>
857 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
860 return memOp.emitOpError(
"unsupported type ")
861 << valueType <<
" for atomic access";
862 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
863 return memOp.emitOpError(
"unsupported ordering '")
864 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
865 if (!memOp.getAlignment())
866 return memOp.emitOpError(
"expected alignment for atomic access");
869 if (memOp.getSyncscope())
870 return memOp.emitOpError(
871 "expected syncscope to be null for non-atomic access");
876 Type valueType = getResult().getType();
878 {AtomicOrdering::release, AtomicOrdering::acq_rel});
882 unsigned alignment,
bool isVolatile,
bool isNonTemporal) {
883 auto type = llvm::cast<LLVMPointerType>(addr.
getType()).getElementType();
884 assert(type &&
"must provide explicit element type to the constructor "
885 "when the pointer type is opaque");
886 build(builder, state, type, addr, alignment, isVolatile, isNonTemporal);
890 Value addr,
unsigned alignment,
bool isVolatile,
891 bool isNonTemporal, AtomicOrdering ordering,
892 StringRef syncscope) {
893 build(builder, state, type, addr,
895 isNonTemporal, ordering,
896 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
905 static std::optional<Type>
907 auto llvmTy = llvm::dyn_cast<LLVM::LLVMPointerType>(type);
909 parser.
emitError(trailingTypeLoc,
"expected LLVM pointer type");
912 return llvmTy.getElementType();
919 SMLoc trailingTypeLoc;
923 std::optional<Type> pointerElementType =
925 if (!pointerElementType)
927 if (*pointerElementType) {
928 elementType = *pointerElementType;
942 auto pointerType = cast<LLVMPointerType>(type);
943 if (pointerType.isOpaque())
944 printer <<
" -> " << elementType;
951 void StoreOp::getEffects(
960 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
961 getOrdering() != AtomicOrdering::unordered)) {
968 Type valueType = getValue().getType();
970 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
974 Value addr,
unsigned alignment,
bool isVolatile,
975 bool isNonTemporal, AtomicOrdering ordering,
976 StringRef syncscope) {
977 build(builder, state, value, addr,
979 isNonTemporal, ordering,
980 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
982 nullptr,
nullptr,
nullptr);
989 SMLoc trailingTypeLoc;
999 std::optional<Type> pointerElementType =
1001 if (!pointerElementType)
1003 elementType = *pointerElementType;
1011 auto pointerType = cast<LLVMPointerType>(type);
1012 if (pointerType.isOpaque())
1013 printer << elementType <<
", ";
1023 build(builder, state, results, builder.
getStringAttr(callee), args);
1033 build(builder, state, results, callee, args,
nullptr,
1042 Type resultType = func.getFunctionType().getReturnType();
1043 if (!llvm::isa<LLVM::LLVMVoidType>(resultType))
1044 results.push_back(resultType);
1057 return getOperand(0);
1063 auto symRef = callee.get<SymbolRefAttr>();
1064 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1067 return setOperand(0, callee.get<
Value>());
1071 return getOperands().drop_front(getCallee().has_value() ? 0 : 1);
1076 getCalleeOperands().size());
1083 if (callee.isExternal())
1085 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1089 auto hasSubprogram = [](
Operation *op) {
1094 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1096 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1098 return callOp.emitError()
1099 <<
"inlinable function call in a function with a DISubprogram "
1100 "location must have a debug location";
1105 if (getNumResults() > 1)
1106 return emitOpError(
"must have 0 or 1 result");
1112 bool isIndirect =
false;
1118 if (!getNumOperands())
1120 "must have either a `callee` attribute or at least an operand");
1121 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).getType());
1123 return emitOpError(
"indirect call expects a pointer as callee: ")
1124 << getOperand(0).getType();
1126 if (ptrType.isOpaque())
1129 fnType = ptrType.getElementType();
1134 return emitOpError()
1136 <<
"' does not reference a symbol in the current scope";
1137 auto fn = dyn_cast<LLVMFuncOp>(callee);
1139 return emitOpError() <<
"'" << calleeName.
getValue()
1140 <<
"' does not reference a valid LLVM function";
1144 fnType = fn.getFunctionType();
1147 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1149 return emitOpError(
"callee does not have a functional type: ") << fnType;
1156 if (isIndirect && funcType.isVarArg())
1157 return emitOpError()
1158 <<
"indirect calls to variadic functions are not supported";
1162 if (!funcType.isVarArg() &&
1163 funcType.getNumParams() != (getNumOperands() - isIndirect))
1164 return emitOpError() <<
"incorrect number of operands ("
1165 << (getNumOperands() - isIndirect)
1166 <<
") for callee (expecting: "
1167 << funcType.getNumParams() <<
")";
1169 if (funcType.getNumParams() > (getNumOperands() - isIndirect))
1170 return emitOpError() <<
"incorrect number of operands ("
1171 << (getNumOperands() - isIndirect)
1172 <<
") for varargs callee (expecting at least: "
1173 << funcType.getNumParams() <<
")";
1175 for (
unsigned i = 0, e = funcType.getNumParams(); i != e; ++i)
1176 if (getOperand(i + isIndirect).getType() != funcType.getParamType(i))
1177 return emitOpError() <<
"operand type mismatch for operand " << i <<
": "
1178 << getOperand(i + isIndirect).getType()
1179 <<
" != " << funcType.getParamType(i);
1181 if (getNumResults() == 0 &&
1182 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1183 return emitOpError() <<
"expected function call to produce a value";
1185 if (getNumResults() != 0 &&
1186 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1187 return emitOpError()
1188 <<
"calling function with void result must not produce values";
1190 if (getNumResults() > 1)
1191 return emitOpError()
1192 <<
"expected LLVM function call to produce 0 or 1 result";
1194 if (getNumResults() && getResult().getType() != funcType.getReturnType())
1195 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1196 <<
" != " << funcType.getReturnType();
1202 auto callee = getCallee();
1203 bool isDirect = callee.has_value();
1213 auto args = getOperands().drop_front(isDirect ? 0 : 1);
1214 p <<
'(' << args <<
')';
1219 p << getOperand(0).getType() <<
", ";
1235 if (isDirect && types.size() != 1)
1236 return parser.
emitError(trailingTypesLoc,
1237 "expected direct call to have 1 trailing type");
1238 if (!isDirect && types.size() != 2)
1239 return parser.
emitError(trailingTypesLoc,
1240 "expected indirect call to have 2 trailing types");
1242 auto funcType = llvm::dyn_cast<FunctionType>(types.pop_back_val());
1244 return parser.
emitError(trailingTypesLoc,
1245 "expected trailing function type");
1246 if (funcType.getNumResults() > 1)
1247 return parser.
emitError(trailingTypesLoc,
1248 "expected function with 0 or 1 result");
1249 if (funcType.getNumResults() == 1 &&
1250 llvm::isa<LLVM::LLVMVoidType>(funcType.getResult(0)))
1251 return parser.
emitError(trailingTypesLoc,
1252 "expected a non-void result type");
1258 llvm::append_range(types, funcType.getInputs());
1262 if (funcType.getNumResults() != 0)
1263 result.
addTypes(funcType.getResults());
1276 if (
failed(*parseResult))
1277 return *parseResult;
1278 operands.push_back(funcPtrOperand);
1286 SymbolRefAttr funcAttr;
1292 bool isDirect = operands.empty();
1313 assert(index < getNumSuccessors() &&
"invalid successor index");
1315 : getUnwindDestOperandsMutable());
1323 return getOperand(0);
1329 auto symRef = callee.get<SymbolRefAttr>();
1330 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1333 return setOperand(0, callee.get<
Value>());
1337 return getOperands().drop_front(getCallee().has_value() ? 0 : 1);
1342 getCalleeOperands().size());
1346 if (getNumResults() > 1)
1347 return emitOpError(
"must have 0 or 1 result");
1349 Block *unwindDest = getUnwindDest();
1350 if (unwindDest->
empty())
1351 return emitError(
"must have at least one operation in unwind destination");
1354 if (!isa<LandingpadOp>(unwindDest->
front()))
1355 return emitError(
"first operation in unwind destination should be a "
1356 "llvm.landingpad operation");
1362 auto callee = getCallee();
1363 bool isDirect = callee.has_value();
1373 p <<
'(' << getOperands().drop_front(isDirect ? 0 : 1) <<
')';
1380 {InvokeOp::getOperandSegmentSizeAttr(),
"callee"});
1384 p << getOperand(0).getType() <<
", ";
1396 SymbolRefAttr funcAttr;
1397 Block *normalDest, *unwindDest;
1404 bool isDirect = operands.empty();
1427 result.
addAttribute(InvokeOp::getOperandSegmentSizeAttr(),
1429 {static_cast<int32_t>(operands.size()),
1430 static_cast<int32_t>(normalOperands.size()),
1431 static_cast<int32_t>(unwindOperands.size())}));
1441 if (LLVMFuncOp func = (*this)->getParentOfType<LLVMFuncOp>()) {
1442 if (!func.getPersonality())
1444 "llvm.landingpad needs to be in a function with a personality");
1450 if (!getCleanup() && getOperands().empty())
1451 return emitError(
"landingpad instruction expects at least one clause or "
1452 "cleanup attribute");
1454 for (
unsigned idx = 0, ie = getNumOperands(); idx < ie; idx++) {
1455 value = getOperand(idx);
1456 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1463 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1466 <<
"global addresses expected as operand to "
1467 "bitcast used in clauses for landingpad";
1475 << idx <<
" is not a known constant - null, addressof, bitcast";
1482 p << (getCleanup() ?
" cleanup " :
" ");
1485 for (
auto value : getOperands()) {
1488 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1489 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1495 p <<
": " << getType();
1536 Type llvmType = containerType;
1538 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1546 for (int64_t idx : position) {
1547 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1548 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1549 emitError(
"position out of bounds: ") << idx;
1552 llvmType = arrayType.getElementType();
1553 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1555 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1556 emitError(
"position out of bounds: ") << idx;
1559 llvmType = structType.getBody()[idx];
1561 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
1572 for (int64_t idx : position) {
1573 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
1574 llvmType = structType.getBody()[idx];
1576 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
1581 OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
1582 auto insertValueOp = getContainer().getDefiningOp<InsertValueOp>();
1584 while (insertValueOp) {
1585 if (getPosition() == insertValueOp.getPosition())
1586 return insertValueOp.getValue();
1588 std::min(getPosition().size(), insertValueOp.getPosition().size());
1599 if (getPosition().take_front(
min) ==
1600 insertValueOp.getPosition().take_front(
min))
1606 getContainerMutable().assign(insertValueOp.getContainer());
1607 result = getResult();
1608 insertValueOp = insertValueOp.getContainer().getDefiningOp<InsertValueOp>();
1614 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1616 emitError, getContainer().getType(), getPosition());
1620 if (getRes().getType() != valueType)
1621 return emitOpError() <<
"Type mismatch: extracting from "
1622 << getContainer().getType() <<
" should produce "
1623 << valueType <<
" but this op returns "
1624 << getRes().getType();
1630 build(builder, state,
1645 [&](StringRef msg) {
1659 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
1661 emitError, getContainer().getType(), getPosition());
1665 if (getValue().getType() != valueType)
1666 return emitOpError() <<
"Type mismatch: cannot insert "
1667 << getValue().getType() <<
" into "
1668 << getContainer().getType();
1678 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
1682 Type expectedType = parent.getFunctionType().getReturnType();
1683 if (llvm::isa<LLVMVoidType>(expectedType)) {
1687 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1691 if (llvm::isa<LLVMVoidType>(expectedType))
1694 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1697 if (expectedType != getArg().getType()) {
1699 diag.attachNote(parent->getLoc()) <<
"when returning from function";
1713 assert(module &&
"unexpected operation outside of a module");
1718 return dyn_cast_or_null<GlobalOp>(
1723 return dyn_cast_or_null<LLVMFuncOp>(
1732 auto global = dyn_cast_or_null<GlobalOp>(symbol);
1733 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
1735 if (!global && !
function)
1737 "must reference a global defined by 'llvm.mlir.global' or 'llvm.func'");
1739 LLVMPointerType type = getType();
1740 if (global && global.getAddrSpace() != type.getAddressSpace())
1741 return emitOpError(
"pointer address space must match address space of the "
1742 "referenced global");
1744 if (type.isOpaque())
1747 if (global && type.getElementType() != global.getType())
1749 "the type must be a pointer to the type of the referenced global");
1751 if (
function && type.getElementType() !=
function.getFunctionType())
1753 "the type must be a pointer to the type of the referenced function");
1763 StringRef symName) {
1771 Region &body = getBody();
1773 if (!isa<ComdatSelectorOp>(op))
1775 "only comdat selector symbols can appear in a comdat region");
1785 bool isConstant, Linkage linkage, StringRef name,
1786 Attribute value, uint64_t alignment,
unsigned addrSpace,
1787 bool dsoLocal,
bool threadLocal, SymbolRefAttr comdat,
1823 p <<
' ' << stringifyLinkage(getLinkage()) <<
' ';
1824 StringRef visibility = stringifyVisibility(getVisibility_());
1825 if (!visibility.empty())
1826 p << visibility <<
' ';
1827 if (getThreadLocal_())
1828 p <<
"thread_local ";
1829 if (
auto unnamedAddr = getUnnamedAddr()) {
1830 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
1838 if (
auto value = getValueOrNull())
1841 if (
auto comdat = getComdat())
1842 p <<
" comdat(" << *comdat <<
')';
1848 {SymbolTable::getSymbolAttrName(),
1849 getGlobalTypeAttrName(), getConstantAttrName(),
1850 getValueAttrName(), getLinkageAttrName(),
1851 getUnnamedAddrAttrName(), getThreadLocal_AttrName(),
1852 getVisibility_AttrName(), getComdatAttrName(),
1853 getUnnamedAddrAttrName()});
1856 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
1858 p <<
" : " << getType();
1860 Region &initializer = getInitializerRegion();
1861 if (!initializer.
empty()) {
1880 template <
typename Ty>
1881 struct EnumTraits {};
1883 #define REGISTER_ENUM_TYPE(Ty) \
1885 struct EnumTraits<Ty> { \
1886 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
1887 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
1899 template <
typename EnumTy,
typename RetTy = EnumTy>
1902 EnumTy defaultValue) {
1904 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
1909 return static_cast<RetTy
>(defaultValue);
1910 return static_cast<RetTy
>(index);
1914 std::optional<SymbolRefAttr> attr) {
1919 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
1920 return op->
emitError() <<
"expected comdat symbol";
1938 ctx, parseOptionalLLVMKeyword<Linkage>(
1939 parser, result, LLVM::Linkage::External)));
1944 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
1945 parser, result, LLVM::Visibility::Default)));
1950 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
1976 SymbolRefAttr comdat;
1989 if (types.size() > 1)
1993 if (types.empty()) {
1994 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
1997 strAttr.getValue().size());
1998 types.push_back(arrayType);
2001 "type can only be omitted for string globals");
2017 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2018 return intValue.getValue().isZero();
2019 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2020 return fpValue.getValue().isZero();
2021 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2023 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2025 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2031 if (!LLVMPointerType::isValidElementType(getType()))
2033 "expects type to be a valid element type for an LLVM pointer");
2035 return emitOpError(
"must appear at the module level");
2037 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2038 auto type = llvm::dyn_cast<LLVMArrayType>(getType());
2039 IntegerType elementType =
2040 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) : nullptr;
2041 if (!elementType || elementType.getWidth() != 8 ||
2042 type.getNumElements() != strAttr.getValue().size())
2044 "requires an i8 array type of the length equal to that of the string "
2048 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getType())) {
2049 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2050 return emitOpError()
2051 <<
"this target extension type cannot be used in a global";
2054 return emitOpError() <<
"global with target extension type can only be "
2055 "initialized with zero-initializer";
2058 if (getLinkage() == Linkage::Common) {
2059 if (
Attribute value = getValueOrNull()) {
2061 return emitOpError()
2062 <<
"expected zero value for '"
2063 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2068 if (getLinkage() == Linkage::Appending) {
2069 if (!llvm::isa<LLVMArrayType>(getType())) {
2070 return emitOpError() <<
"expected array type for '"
2071 << stringifyLinkage(Linkage::Appending)
2079 std::optional<uint64_t> alignAttr = getAlignment();
2080 if (alignAttr.has_value()) {
2081 uint64_t value = alignAttr.value();
2082 if (!llvm::isPowerOf2_64(value))
2083 return emitError() <<
"alignment attribute is not a power of 2";
2090 if (
Block *b = getInitializerBlock()) {
2091 ReturnOp ret = cast<ReturnOp>(b->getTerminator());
2092 if (ret.operand_type_begin() == ret.operand_type_end())
2093 return emitOpError(
"initializer region cannot return void");
2094 if (*ret.operand_type_begin() != getType())
2095 return emitOpError(
"initializer region type ")
2096 << *ret.operand_type_begin() <<
" does not match global type "
2100 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2101 if (!iface || !iface.hasNoEffect())
2103 <<
"ops with side effects not allowed in global initializers";
2106 if (getValueOrNull())
2107 return emitOpError(
"cannot have both initializer value and region");
2128 if (getCtors().size() != getPriorities().size())
2130 "mismatch between the number of ctors and the number of priorities");
2149 if (getDtors().size() != getPriorities().size())
2151 "mismatch between the number of dtors and the number of priorities");
2162 auto containerType = v1.
getType();
2166 build(builder, state, vType, v1, v2, mask);
2167 state.addAttributes(attrs);
2180 "expected an LLVM compatible vector type");
2192 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
2193 return emitOpError(
"expected a splat operation for scalable vectors");
2202 Block *LLVMFuncOp::addEntryBlock() {
2203 assert(empty() &&
"function already has an entry block");
2205 auto *entry =
new Block;
2209 LLVMFunctionType type = getFunctionType();
2210 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
2211 entry->addArgument(type.getParamType(i), getLoc());
2216 StringRef name,
Type type, LLVM::Linkage linkage,
2217 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
2220 std::optional<uint64_t> functionEntryCount) {
2236 if (functionEntryCount)
2239 if (argAttrs.empty())
2242 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
2243 "expected as many argument attribute lists as arguments");
2245 builder, result, argAttrs, std::nullopt,
2246 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2257 if (outputs.size() > 1) {
2258 parser.
emitError(loc,
"failed to construct function type: expected zero or "
2259 "one function result");
2265 for (
auto t : inputs) {
2267 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2268 "type for function arguments");
2271 llvmInputs.push_back(t);
2278 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
2279 "type for function results")
2297 getLinkageAttrName(result.
name),
2299 parseOptionalLLVMKeyword<Linkage>(
2300 parser, result, LLVM::Linkage::External)));
2305 parseOptionalLLVMKeyword<LLVM::Visibility, int64_t>(
2306 parser, result, LLVM::Visibility::Default)));
2311 parseOptionalLLVMKeyword<UnnamedAddr, int64_t>(
2316 getCConvAttrName(result.
name),
2318 parser, result, LLVM::CConv::C)));
2320 StringAttr nameAttr;
2330 parser,
true, entryArgs, isVariadic, resultTypes,
2335 for (
auto &arg : entryArgs)
2336 argTypes.push_back(arg.type);
2346 int64_t minRange, maxRange;
2353 getVscaleRangeAttrName(result.
name),
2360 SymbolRefAttr comdat;
2371 parser.
getBuilder(), result, entryArgs, resultAttrs,
2372 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
2385 if (getLinkage() != LLVM::Linkage::External)
2386 p << stringifyLinkage(getLinkage()) <<
' ';
2387 StringRef visibility = stringifyVisibility(getVisibility_());
2388 if (!visibility.empty())
2389 p << visibility <<
' ';
2390 if (
auto unnamedAddr = getUnnamedAddr()) {
2391 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2395 if (getCConv() != LLVM::CConv::C)
2396 p << stringifyCConv(getCConv()) <<
' ';
2400 LLVMFunctionType fnType = getFunctionType();
2403 argTypes.reserve(fnType.getNumParams());
2404 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
2405 argTypes.push_back(fnType.getParamType(i));
2407 Type returnType = fnType.getReturnType();
2408 if (!llvm::isa<LLVMVoidType>(returnType))
2409 resTypes.push_back(returnType);
2412 isVarArg(), resTypes);
2415 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
2416 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
2417 << vscale->getMaxRange().getInt() <<
')';
2420 if (
auto comdat = getComdat())
2421 p <<
" comdat(" << *comdat <<
')';
2425 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
2426 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
2427 getComdatAttrName(), getUnnamedAddrAttrName(),
2428 getVscaleRangeAttrName()});
2431 Region &body = getBody();
2432 if (!body.empty()) {
2444 if (getLinkage() == LLVM::Linkage::Common)
2445 return emitOpError() <<
"functions cannot have '"
2446 << stringifyLinkage(LLVM::Linkage::Common)
2453 if (getLinkage() != LLVM::Linkage::External &&
2454 getLinkage() != LLVM::Linkage::ExternWeak)
2455 return emitOpError() <<
"external functions must have '"
2456 << stringifyLinkage(LLVM::Linkage::External)
2458 << stringifyLinkage(LLVM::Linkage::ExternWeak)
2463 Type landingpadResultTy;
2464 StringRef diagnosticMessage;
2465 bool isLandingpadTypeConsistent =
2467 const auto checkType = [&](
Type type, StringRef errorMessage) {
2468 if (!landingpadResultTy) {
2469 landingpadResultTy = type;
2472 if (landingpadResultTy != type) {
2473 diagnosticMessage = errorMessage;
2479 .Case<LandingpadOp>([&](
auto landingpad) {
2480 constexpr StringLiteral errorMessage =
2481 "'llvm.landingpad' should have a consistent result type "
2482 "inside a function";
2483 return checkType(landingpad.getType(), errorMessage);
2485 .Case<ResumeOp>([&](
auto resume) {
2486 constexpr StringLiteral errorMessage =
2487 "'llvm.resume' should have a consistent input type inside a "
2489 return checkType(resume.getValue().getType(), errorMessage);
2492 }).wasInterrupted();
2493 if (!isLandingpadTypeConsistent) {
2494 assert(!diagnosticMessage.empty() &&
2495 "Expecting a non-empty diagnostic message");
2508 unsigned numArguments = getFunctionType().getNumParams();
2509 Block &entryBlock = front();
2510 for (
unsigned i = 0; i < numArguments; ++i) {
2513 return emitOpError(
"entry block argument #")
2514 << i <<
" is not of LLVM type";
2520 Region *LLVMFuncOp::getCallableRegion() {
2531 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getType()))
2532 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
2533 return emitOpError()
2534 <<
"target extension type does not support zero-initializer";
2544 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
2545 auto arrayType = llvm::dyn_cast<LLVMArrayType>(getType());
2546 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
2547 !arrayType.getElementType().isInteger(8)) {
2548 return emitOpError() <<
"expected array type of "
2549 << sAttr.getValue().size()
2550 <<
" i8 elements for the string constant";
2554 if (
auto structType = llvm::dyn_cast<LLVMStructType>(getType())) {
2555 if (structType.getBody().size() != 2 ||
2556 structType.getBody()[0] != structType.getBody()[1]) {
2557 return emitError() <<
"expected struct type with two elements of the "
2558 "same type, the type of a complex constant";
2561 auto arrayAttr = llvm::dyn_cast<ArrayAttr>(getValue());
2562 if (!arrayAttr || arrayAttr.size() != 2) {
2563 return emitOpError() <<
"expected array attribute with two elements, "
2564 "representing a complex constant";
2566 auto re = llvm::dyn_cast<TypedAttr>(arrayAttr[0]);
2567 auto im = llvm::dyn_cast<TypedAttr>(arrayAttr[1]);
2568 if (!re || !im || re.getType() != im.getType()) {
2569 return emitOpError()
2570 <<
"expected array attribute with two elements of the same type";
2573 Type elementType = structType.getBody()[0];
2574 if (!llvm::isa<IntegerType, Float16Type, Float32Type, Float64Type>(
2577 <<
"expected struct element types to be floating point type or "
2582 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getType())) {
2583 return emitOpError() <<
"does not support target extension type.";
2585 if (!llvm::isa<IntegerAttr, ArrayAttr, FloatAttr, ElementsAttr>(getValue()))
2586 return emitOpError()
2587 <<
"only supports integer, float, string or elements attributes";
2591 bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
2593 auto typedAttr = dyn_cast<TypedAttr>(value);
2600 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
2605 if (isBuildableWith(value, type))
2606 return builder.
create<LLVM::ConstantOp>(loc, cast<TypedAttr>(value));
2611 OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
2619 AtomicOrdering ordering, StringRef syncscope,
2620 unsigned alignment,
bool isVolatile) {
2621 build(builder, state, val.
getType(), binOp, ptr, val, ordering,
2622 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
2625 nullptr,
nullptr,
nullptr);
2629 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().getType());
2630 auto valType = getVal().getType();
2631 if (!ptrType.isOpaque() && valType != ptrType.getElementType())
2632 return emitOpError(
"expected LLVM IR element type for operand #0 to "
2633 "match type for operand #1");
2634 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
2635 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax) {
2637 return emitOpError(
"expected LLVM IR floating point type");
2638 }
else if (getBinOp() == AtomicBinOp::xchg) {
2640 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
2642 auto intType = llvm::dyn_cast<IntegerType>(valType);
2643 unsigned intBitWidth = intType ? intType.getWidth() : 0;
2644 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
2646 return emitOpError(
"expected LLVM IR integer type");
2649 if (
static_cast<unsigned>(getOrdering()) <
2650 static_cast<unsigned>(AtomicOrdering::monotonic))
2651 return emitOpError() <<
"expected at least '"
2652 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
2665 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
2670 AtomicOrdering successOrdering,
2671 AtomicOrdering failureOrdering, StringRef syncscope,
2672 unsigned alignment,
bool isWeak,
bool isVolatile) {
2674 successOrdering, failureOrdering,
2675 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
2677 isVolatile,
nullptr,
2678 nullptr,
nullptr,
nullptr);
2682 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().getType());
2684 return emitOpError(
"expected LLVM IR pointer type for operand #0");
2685 auto valType = getVal().getType();
2686 if (!ptrType.isOpaque() && valType != ptrType.getElementType())
2687 return emitOpError(
"expected LLVM IR element type for operand #0 to "
2688 "match type for all other operands");
2691 return emitOpError(
"unexpected LLVM IR type");
2692 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
2693 getFailureOrdering() < AtomicOrdering::monotonic)
2694 return emitOpError(
"ordering must be at least 'monotonic'");
2695 if (getFailureOrdering() == AtomicOrdering::release ||
2696 getFailureOrdering() == AtomicOrdering::acq_rel)
2697 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
2706 AtomicOrdering ordering, StringRef syncscope) {
2707 build(builder, state, ordering,
2708 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
2712 if (getOrdering() == AtomicOrdering::not_atomic ||
2713 getOrdering() == AtomicOrdering::unordered ||
2714 getOrdering() == AtomicOrdering::monotonic)
2715 return emitOpError(
"can be given only acquire, release, acq_rel, "
2716 "and seq_cst orderings");
2726 template <
class ExtOp>
2728 IntegerType inputType, outputType;
2732 "input type is a vector but output type is an integer");
2735 return op.
emitError(
"input and output vectors are of incompatible shape");
2744 inputType = cast<IntegerType>(op.getArg().getType());
2748 "input type is an integer but output type is a vector");
2751 if (outputType.getWidth() <= inputType.getWidth())
2752 return op.
emitError(
"integer width of the output type is smaller or "
2753 "equal to the integer width of the input type");
2764 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
2768 size_t targetSize = cast<IntegerType>(getType()).getWidth();
2782 OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
2784 if (getArg().getType() == getType())
2787 if (
auto prev = getArg().getDefiningOp<BitcastOp>())
2788 if (prev.getArg().getType() == getType())
2789 return prev.getArg();
2794 auto resultType = llvm::dyn_cast<LLVMPointerType>(
2796 auto sourceType = llvm::dyn_cast<LLVMPointerType>(
2801 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
2802 return emitOpError(
"can only cast pointers from and to pointers");
2807 auto isVector = [](
Type type) {
2808 return llvm::isa<VectorType, LLVMScalableVectorType, LLVMFixedVectorType>(
2814 if (isVector(getResult().getType()) && !isVector(getArg().getType()))
2815 return emitOpError(
"cannot cast pointer to vector of pointers");
2817 if (!isVector(getResult().getType()) && isVector(getArg().getType()))
2818 return emitOpError(
"cannot cast vector of pointers to pointer");
2822 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
2823 return emitOpError(
"cannot cast pointers of different address spaces, "
2824 "use 'llvm.addrspacecast' instead");
2833 OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
2835 if (getArg().getType() == getType())
2838 if (
auto prev = getArg().getDefiningOp<AddrSpaceCastOp>())
2839 if (prev.getArg().getType() == getType())
2840 return prev.getArg();
2850 adaptor.getDynamicIndices());
2853 if (
getBase().getType() == getType() && indices.size() == 1)
2854 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(indices[0]))
2855 if (integer.getValue().isZero())
2859 bool changed =
false;
2862 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
2865 if (!indices.isDynamicIndex(iter.index()) || !integer ||
2869 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
2870 gepArgs.emplace_back(val);
2872 gepArgs.emplace_back(existing.get<IntegerAttr>().getInt());
2878 gepArgs.emplace_back(integer.getInt());
2886 getDynamicIndicesMutable().assign(dynamicIndices);
2887 setRawConstantIndices(rawConstantIndices);
2888 return Value{*
this};
2899 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
2903 if (rhs.getValue().getZExtValue() >=
2904 getLhs().getType().getIntOrFloatBitWidth())
2907 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
2919 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
2923 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
2935 if (!getIntrin().startswith(
"llvm."))
2936 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
2950 .Case<AccessGroupAttr, AliasScopeAttr, AliasScopeDomainAttr,
2951 DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr,
2952 DIDerivedTypeAttr, DIFileAttr, DILabelAttr, DILexicalBlockAttr,
2953 DILexicalBlockFileAttr, DILocalVariableAttr, DIModuleAttr,
2954 DINamespaceAttr, DINullTypeAttr, DISubprogramAttr,
2955 DISubroutineTypeAttr, LoopAnnotationAttr, LoopVectorizeAttr,
2956 LoopInterleaveAttr, LoopUnrollAttr, LoopUnrollAndJamAttr,
2957 LoopLICMAttr, LoopDistributeAttr, LoopPipelineAttr,
2958 LoopPeeledAttr, LoopUnswitchAttr, TBAARootAttr, TBAATagAttr,
2959 TBAATypeDescriptorAttr>([&](
auto attr) {
2960 os << decltype(attr)::getMnemonic();
2961 return AliasResult::OverridableAlias;
2972 void LLVMDialect::initialize() {
2973 registerAttributes();
2976 addTypes<LLVMVoidType,
2988 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
2991 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
2995 allowUnknownOperations();
2997 addInterfaces<LLVMOpAsmDialectInterface>();
3002 #define GET_OP_CLASSES
3003 #include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
3005 #define GET_OP_CLASSES
3006 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
3011 llvm::DataLayout::parse(descr);
3012 if (maybeDataLayout)
3015 std::string message;
3016 llvm::raw_string_ostream messageStream(message);
3017 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
3018 reportError(
"invalid data layout descriptor: " + messageStream.str());
3029 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
3031 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
3032 return verifyDataLayoutString(
3033 stringAttr.getValue(),
3034 [op](
const Twine &message) { op->emitOpError() << message.str(); });
3037 << LLVM::LLVMDialect::getDataLayoutAttrName()
3038 <<
"' to be a string attributes";
3049 StringAttr name = paramAttr.
getName();
3052 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
3053 return op->
emitError() << name <<
" should be a unit attribute";
3057 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
3058 return op->
emitError() << name <<
" should be a type attribute";
3062 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
3063 return op->
emitError() << name <<
" should be an integer attribute";
3067 if (!llvm::isa<LLVMPointerType>(paramType))
3069 << name <<
" attribute attached to non-pointer LLVM type";
3073 if (!llvm::isa<IntegerType>(paramType))
3075 << name <<
" attribute attached to non-integer LLVM type";
3079 if (
failed(checkPointerType()))
3081 auto ptrType = llvm::cast<LLVMPointerType>(paramType);
3082 auto typeAttr = llvm::cast<TypeAttr>(paramAttr.
getValue());
3084 if (!ptrType.isOpaque() && ptrType.getElementType() != typeAttr.getValue())
3087 <<
" attribute attached to LLVM pointer argument of "
3093 if (name == LLVMDialect::getNoAliasAttrName() ||
3094 name == LLVMDialect::getReadonlyAttrName() ||
3095 name == LLVMDialect::getReadnoneAttrName() ||
3096 name == LLVMDialect::getWriteOnlyAttrName() ||
3097 name == LLVMDialect::getNestAttrName() ||
3098 name == LLVMDialect::getNoCaptureAttrName() ||
3099 name == LLVMDialect::getNoFreeAttrName() ||
3100 name == LLVMDialect::getNonNullAttrName()) {
3101 if (
failed(checkUnitAttrType()))
3103 if (verifyValueType &&
failed(checkPointerType()))
3109 if (name == LLVMDialect::getStructRetAttrName() ||
3110 name == LLVMDialect::getByValAttrName() ||
3111 name == LLVMDialect::getByRefAttrName() ||
3112 name == LLVMDialect::getInAllocaAttrName() ||
3113 name == LLVMDialect::getPreallocatedAttrName()) {
3114 if (
failed(checkTypeAttrType()))
3116 if (verifyValueType &&
failed(checkPointerTypeMatches()))
3122 if (name == LLVMDialect::getSExtAttrName() ||
3123 name == LLVMDialect::getZExtAttrName()) {
3124 if (
failed(checkUnitAttrType()))
3126 if (verifyValueType &&
failed(checkIntegerType()))
3132 if (name == LLVMDialect::getAlignAttrName() ||
3133 name == LLVMDialect::getDereferenceableAttrName() ||
3134 name == LLVMDialect::getDereferenceableOrNullAttrName() ||
3135 name == LLVMDialect::getStackAlignmentAttrName()) {
3136 if (
failed(checkIntegerAttrType()))
3138 if (verifyValueType &&
failed(checkPointerType()))
3144 if (name == LLVMDialect::getNoUndefAttrName() ||
3145 name == LLVMDialect::getInRegAttrName() ||
3146 name == LLVMDialect::getReturnedAttrName())
3147 return checkUnitAttrType();
3157 auto funcOp = dyn_cast<FunctionOpInterface>(op);
3160 Type argType = funcOp.getArgumentTypes()[argIdx];
3162 return verifyParameterAttribute(op, argType, argAttr);
3169 auto funcOp = dyn_cast<FunctionOpInterface>(op);
3172 Type resType = funcOp.getResultTypes()[resIdx];
3176 if (llvm::isa<LLVMVoidType>(resType))
3177 return op->
emitError() <<
"cannot attach result attributes to functions "
3178 "with a void return";
3182 auto name = resAttr.
getName();
3183 if (name == LLVMDialect::getAllocAlignAttrName() ||
3184 name == LLVMDialect::getAllocatedPointerAttrName() ||
3185 name == LLVMDialect::getByValAttrName() ||
3186 name == LLVMDialect::getByRefAttrName() ||
3187 name == LLVMDialect::getInAllocaAttrName() ||
3188 name == LLVMDialect::getNestAttrName() ||
3189 name == LLVMDialect::getNoCaptureAttrName() ||
3190 name == LLVMDialect::getNoFreeAttrName() ||
3191 name == LLVMDialect::getPreallocatedAttrName() ||
3192 name == LLVMDialect::getReadnoneAttrName() ||
3193 name == LLVMDialect::getReadonlyAttrName() ||
3194 name == LLVMDialect::getReturnedAttrName() ||
3195 name == LLVMDialect::getStackAlignmentAttrName() ||
3196 name == LLVMDialect::getStructRetAttrName() ||
3197 name == LLVMDialect::getWriteOnlyAttrName())
3198 return op->
emitError() << name <<
" is not a valid result attribute";
3199 return verifyParameterAttribute(op, resType, resAttr);
3204 return LLVM::ConstantOp::materialize(builder, value, type, loc);
3212 StringRef name, StringRef value,
3213 LLVM::Linkage linkage,
3214 bool useOpaquePointers) {
3217 "expected builder to point to a block constrained in an op");
3220 assert(module &&
"builder points to an op outside of a module");
3226 auto global = moduleBuilder.
create<LLVM::GlobalOp>(
3227 loc, type,
true, linkage, name,
3230 LLVMPointerType resultType;
3231 LLVMPointerType charPtr;
3232 if (!useOpaquePointers) {
3240 Value globalPtr = builder.
create<LLVM::AddressOfOp>(loc, resultType,
3241 global.getSymNameAttr());
3242 return builder.
create<LLVM::GEPOp>(loc, charPtr, type, globalPtr,
static std::string toString(bytecode::Section::ID sectionID)
Stringify the given section ID.
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 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 void printStoreType(OpAsmPrinter &printer, Operation *op, Type elementType, Type type)
Prints the StoreOp type either using the typed or opaque pointer format.
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)
static LogicalResult verifyOpaquePtr(Operation *op, LLVMPointerType ptrType, std::optional< Type > ptrElementType)
Checks that the elemental type is present in either the pointer type or the attribute,...
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 void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type flagType, DenseIntElementsAttr caseValues, SuccessorRange caseDestinations, OperandRangeRange caseOperands, const TypeRangeRange &caseOperandTypes)
static std::optional< Type > getLoadStoreElementType(OpAsmParser &parser, Type type, SMLoc trailingTypeLoc)
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 void printLoadType(OpAsmPrinter &printer, Operation *op, Type type, Type elementType)
Prints the LoadOp type either using the typed or opaque pointer format.
static ParseResult parseStoreType(OpAsmParser &parser, Type &elementType, Type &type)
Parses the StoreOp type either using the typed or opaque pointer format.
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 llvm::Error verifyStructIndices(Type baseGEPType, unsigned indexPos, GEPIndicesAdaptor< ValueRange > indices)
For the given structIndices and indices, check if they're complied with baseGEPType,...
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 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 ParseResult parseLoadType(OpAsmParser &parser, Type &type, Type &elementType)
Parses the LoadOp type either using the typed or opaque pointer format.
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 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 parseArrow()=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)
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*'.
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.
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.
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.
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.
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 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.
Value createGlobalString(Location loc, OpBuilder &builder, StringRef name, StringRef value, Linkage linkage, bool useOpaquePointers)
Create an LLVM global containing the string "value" at the module containing surrounding the insertio...
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.
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.
This header declares functions that assist transformations in the MemRef dialect.
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.
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.