20#include "mlir/IR/Attributes.h"
21#include "mlir/IR/BuiltinOps.h"
22#include "mlir/IR/BuiltinTypes.h"
23#include "mlir/IR/DialectImplementation.h"
24#include "mlir/IR/PatternMatch.h"
25#include "mlir/IR/Value.h"
26#include "mlir/Interfaces/ControlFlowInterfaces.h"
27#include "mlir/Interfaces/FunctionImplementation.h"
28#include "mlir/Support/LLVM.h"
31#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
32#include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc"
34#include "llvm/ADT/SetOperations.h"
35#include "llvm/ADT/SmallSet.h"
36#include "llvm/ADT/TypeSwitch.h"
37#include "llvm/Support/Casting.h"
38#include "llvm/Support/LogicalResult.h"
50struct CIROpAsmDialectInterface :
public OpAsmDialectInterface {
51 using OpAsmDialectInterface::OpAsmDialectInterface;
53 AliasResult getAlias(Type type, raw_ostream &os)
const final {
54 if (
auto recordType = dyn_cast<cir::RecordType>(type)) {
57 os <<
"rec_anon_" <<
recordType.getKindAsStr();
59 os <<
"rec_" << nameAttr.getValue();
60 return AliasResult::OverridableAlias;
62 if (
auto intType = dyn_cast<cir::IntType>(type)) {
65 unsigned width = intType.getWidth();
66 if (width < 8 || !llvm::isPowerOf2_32(width))
67 return AliasResult::NoAlias;
68 os << intType.getAlias();
69 return AliasResult::OverridableAlias;
71 if (
auto voidType = dyn_cast<cir::VoidType>(type)) {
72 os << voidType.getAlias();
73 return AliasResult::OverridableAlias;
76 return AliasResult::NoAlias;
79 AliasResult getAlias(Attribute attr, raw_ostream &os)
const final {
80 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr)) {
81 os << (boolAttr.getValue() ?
"true" :
"false");
82 return AliasResult::FinalAlias;
84 if (
auto bitfield = mlir::dyn_cast<cir::BitfieldInfoAttr>(attr)) {
85 os <<
"bfi_" << bitfield.getName().str();
86 return AliasResult::FinalAlias;
88 if (
auto dynCastInfoAttr = mlir::dyn_cast<cir::DynamicCastInfoAttr>(attr)) {
89 os << dynCastInfoAttr.getAlias();
90 return AliasResult::FinalAlias;
92 if (
auto cmpThreeWayInfoAttr =
93 mlir::dyn_cast<cir::CmpThreeWayInfoAttr>(attr)) {
94 os << cmpThreeWayInfoAttr.getAlias();
95 return AliasResult::FinalAlias;
97 return AliasResult::NoAlias;
102void cir::CIRDialect::initialize() {
104 registerAttributes();
105 registerCIRDialectOperations(
this);
106 addInterfaces<CIROpAsmDialectInterface>();
110Operation *cir::CIRDialect::materializeConstant(mlir::OpBuilder &builder,
111 mlir::Attribute value,
113 mlir::Location loc) {
114 return cir::ConstantOp::create(builder, loc, type,
115 mlir::cast<mlir::TypedAttr>(value));
119 return attrName == CIRDialect::getOpenCLVersionAttrName() ||
120 attrName == CIRDialect::getOpenCLCXXVersionAttrName() ||
121 attrName == CIRDialect::getOpenCLSPIRVersionAttrName();
125 NamedAttribute attr) {
126 StringRef attrName = attr.getName().getValue();
127 if (isa<ModuleOp>(op))
130 return op->emitError() << attrName
131 <<
" attribute must be attached to a module";
135 cir::OpenCLVersionAttr cxxVersion) {
136 return (openCLVersion.getMajorVersion() == 2 &&
137 openCLVersion.getMinorVersion() == 0 &&
138 cxxVersion.getMajorVersion() == 1 &&
139 cxxVersion.getMinorVersion() == 0) ||
140 (openCLVersion.getMajorVersion() == 3 &&
141 openCLVersion.getMinorVersion() == 0 &&
142 cxxVersion.getMajorVersion() == 2021 &&
143 cxxVersion.getMinorVersion() == 0);
147 cir::OpenCLVersionAttr cxxVersion) {
148 Attribute openCLAttr =
149 module->getAttr(CIRDialect::getOpenCLVersionAttrName());
151 return module.emitError()
152 << "module attribute '" << CIRDialect::getOpenCLCXXVersionAttrName()
153 << "' requires the companion attribute '"
154 << CIRDialect::getOpenCLVersionAttrName() << "'";
156 auto openCLVersion = dyn_cast<cir::OpenCLVersionAttr>(openCLAttr);
161 return module.emitError("incompatible OpenCL and C++ for OpenCL versions");
167 NamedAttribute attr) {
171 StringRef attrName = attr.getName().getValue();
172 auto version = dyn_cast<cir::OpenCLVersionAttr>(attr.getValue());
174 return op->emitError() <<
"expected " << attrName
175 <<
" to be #cir.cl.version";
178 if (attrName == CIRDialect::getOpenCLCXXVersionAttrName())
184LogicalResult cir::CIRDialect::verifyRegionArgAttribute(
185 Operation *op,
unsigned ,
unsigned ,
186 NamedAttribute attr) {
193LogicalResult cir::CIRDialect::verifyRegionResultAttribute(
194 Operation *op,
unsigned ,
unsigned ,
195 NamedAttribute attr) {
207 cir::OffloadKind expected) {
208 auto attr =
module->getAttrOfType<cir::OffloadKindAttr>(
209 cir::CIRDialect::getOffloadKindAttrName());
211 return module.emitOpError()
212 << "expects '" << cir::CIRDialect::getOffloadKindAttrName()
213 << "' offload kind attribute";
214 if (attr.getValue() != expected)
215 return module.emitOpError()
216 << "expects '" << cir::CIRDialect::getOffloadKindAttrName()
217 << "' value '" << cir::stringifyOffloadKind(expected) << "'";
226 auto container = mlir::dyn_cast<mlir::ModuleOp>(op);
228 return op->emitOpError()
229 <<
"expects '" << cir::CIRDialect::getOffloadContainerAttrName()
230 <<
"' attribute to be attached to '"
231 << mlir::ModuleOp::getOperationName() <<
"'";
233 mlir::Block &body = *container.getBody();
235 return container.emitOpError()
236 <<
"expects host module as the first nested op";
238 auto host = mlir::dyn_cast<mlir::ModuleOp>(body.front());
240 return container.emitOpError()
241 <<
"expects host module as the first nested op";
246 if (std::next(body.begin()) == body.end())
247 return container.emitOpError() <<
"expects at least one device module";
249 for (
auto &op : llvm::drop_begin(body)) {
250 auto module = mlir::dyn_cast<mlir::ModuleOp>(op);
252 return container.emitOpError()
253 <<
"expects only nested builtin.module ops";
261cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
262 mlir::NamedAttribute attr) {
263 llvm::StringRef attrName =
attr.getName().getValue();
267 if (attrName == getCXXABIAttrName()) {
268 if (!mlir::isa<mlir::ModuleOp>(op))
269 return op->emitOpError() <<
"expects '" << getCXXABIAttrName()
270 <<
"' attribute to be attached to '"
271 << mlir::ModuleOp::getOperationName() <<
"'";
272 auto abi = mlir::dyn_cast<mlir::StringAttr>(
attr.getValue());
274 return op->emitOpError()
275 <<
"expects '" << getCXXABIAttrName() <<
"' to be a string";
277 StringRef abival = abi.getValue();
279 return op->emitOpError() <<
"unknown C++ ABI '" << abi.getValue() <<
"'";
282 if (
auto triple = op->getAttrOfType<mlir::StringAttr>(getTripleAttrName()))
284 llvm::Triple(triple.getValue()),
kind))
285 return op->emitOpError()
286 <<
"C++ ABI '" << abi.getValue()
287 <<
"' is not supported on target '" << triple.getValue() <<
"'";
292 if (attrName == getOffloadContainerAttrName()) {
293 if (!mlir::isa<mlir::UnitAttr>(
attr.getValue()))
294 return op->emitOpError() <<
"expects '" << getOffloadContainerAttrName()
295 <<
"' to be a unit attribute";
302 if (attrName == getOffloadKindAttrName() && !mlir::isa<mlir::ModuleOp>(op))
303 return op->emitOpError() <<
"expects '" << getOffloadKindAttrName()
304 <<
"' attribute to be attached to '"
305 << mlir::ModuleOp::getOperationName() <<
"'";
307 if (attrName == getModuleFramePointerAttrName()) {
308 if (!mlir::isa<mlir::ModuleOp>(op))
309 return op->emitOpError() <<
"expects '" << getModuleFramePointerAttrName()
310 <<
"' attribute to be attached to '"
311 << mlir::ModuleOp::getOperationName() <<
"'";
312 if (!mlir::isa<cir::FramePointerKindAttr>(
attr.getValue()))
313 return op->emitOpError() <<
"expects '" << getModuleFramePointerAttrName()
314 <<
"' to be a #cir.frame_pointer attribute";
320 if (attrName == getCUDADeviceBinaryAttrName()) {
321 auto bytes = mlir::dyn_cast<mlir::StringAttr>(
attr.getValue());
324 if (!arrayTy || arrayTy.getSize() !=
bytes.size())
325 return op->emitOpError()
326 <<
"expects '" << getCUDADeviceBinaryAttrName()
327 <<
"' to be a string typed as an array of its length";
328 return cir::ConstArrayAttr::verify([&] {
return op->emitOpError(); },
345 for (
auto en : llvm::enumerate(keywords)) {
346 if (succeeded(parser.parseOptionalKeyword(en.value())))
353template <
typename Ty>
struct EnumTraits {};
355#define REGISTER_ENUM_TYPE(Ty) \
356 template <> struct EnumTraits<cir::Ty> { \
357 static llvm::StringRef stringify(cir::Ty value) { \
358 return stringify##Ty(value); \
360 static unsigned getMaxEnumVal() { return cir::getMaxEnumValFor##Ty(); } \
371template <
typename EnumTy,
typename RetTy = EnumTy>
374 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
375 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
379 return static_cast<RetTy
>(defaultValue);
380 return static_cast<RetTy
>(index);
384template <
typename EnumTy,
typename RetTy = EnumTy>
387 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
388 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
393 result =
static_cast<RetTy
>(index);
401 Location eLoc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
402 OpBuilder builder(parser.getBuilder().getContext());
407 builder.createBlock(®ion);
409 Block &block = region.back();
411 if (!block.empty() && block.back().hasTrait<OpTrait::IsTerminator>())
415 if (!region.hasOneBlock())
416 return parser.emitError(errLoc,
417 "multi-block region must not omit terminator");
420 builder.setInsertionPointToEnd(&block);
421 cir::YieldOp::create(builder, eLoc);
427 const auto singleNonEmptyBlock = r.hasOneBlock() && !r.back().empty();
428 const auto yieldsNothing = [&r]() {
429 auto y = dyn_cast<cir::YieldOp>(r.back().getTerminator());
430 return y && y.getArgs().empty();
432 return singleNonEmptyBlock && yieldsNothing();
437template <
typename ExpectedProducerOp>
439 StringRef operandName) {
440 Operation *producer = operand.getDefiningOp();
441 if (!producer || !isa<ExpectedProducerOp>(producer))
442 return op->emitOpError()
443 <<
"operand '" << operandName <<
"' must be produced by '"
444 << ExpectedProducerOp::getOperationName() <<
"'";
453 cir::InlineKindAttr &inlineKindAttr) {
455 static constexpr llvm::StringRef keywords[] = {
"no_inline",
"always_inline",
459 llvm::StringRef keyword;
460 if (parser.parseOptionalKeyword(&keyword, keywords).failed()) {
466 auto inlineKindResult = ::cir::symbolizeEnum<::cir::InlineKind>(keyword);
467 if (!inlineKindResult) {
468 return parser.emitError(parser.getCurrentLocation(),
"expected one of [")
470 <<
"] for inlineKind, got: " << keyword;
474 ::cir::InlineKindAttr::get(parser.getContext(), *inlineKindResult);
479 if (inlineKindAttr) {
480 p <<
" " << stringifyInlineKind(inlineKindAttr.getValue());
489 mlir::Region ®ion) {
490 auto regionLoc = parser.getCurrentLocation();
491 if (parser.parseRegion(region))
499 cir::ScopeOp &op, mlir::Region ®ion) {
500 printer.printRegion(region,
509void cir::AllocaOp::build(mlir::OpBuilder &odsBuilder,
510 mlir::OperationState &odsState, mlir::Type addr,
511 llvm::StringRef name, mlir::IntegerAttr alignment) {
512 odsState.addAttribute(getNameAttrName(odsState.name),
513 odsBuilder.getStringAttr(name));
515 odsState.addAttribute(getAlignmentAttrName(odsState.name), alignment);
517 odsState.addTypes(addr);
521 mlir::Value ptr = addr;
522 while (cir::CastOp castOp = ptr.getDefiningOp<cir::CastOp>()) {
523 if (!castOp.isAllocaPreservingCast())
525 ptr = castOp.getSrc();
527 return ptr.getDefiningOp<cir::AllocaOp>();
535 auto ptrTy = mlir::cast<cir::PointerType>(op.getAddr().getType());
536 mlir::Type pointeeTy = ptrTy.getPointee();
538 mlir::Block &body = op.getBody().front();
539 if (body.getNumArguments() != 1)
540 return op.emitOpError(
"body must have exactly one block argument");
542 auto expectedEltPtrTy =
543 mlir::dyn_cast<cir::PointerType>(body.getArgument(0).getType());
544 if (!expectedEltPtrTy)
545 return op.emitOpError(
"block argument must be a !cir.ptr type");
547 if (op.getNumElements()) {
548 auto recTy = mlir::dyn_cast<cir::RecordType>(pointeeTy);
550 return op.emitOpError(
551 "when 'num_elements' is present, 'addr' must be a pointer to a "
552 "!cir.struct or !cir.union type");
554 if (expectedEltPtrTy != ptrTy)
555 return op.emitOpError(
"when 'num_elements' is present, 'addr' type must "
556 "match the block argument type");
558 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(pointeeTy);
560 return op.emitOpError(
561 "when 'num_elements' is absent, 'addr' must be a pointer to a "
564 mlir::Type innerEltTy = arrayTy.getElementType();
565 while (
auto nested = mlir::dyn_cast<cir::ArrayType>(innerEltTy))
566 innerEltTy = nested.getElementType();
568 auto recTy = mlir::dyn_cast<cir::RecordType>(innerEltTy);
570 return op.emitOpError(
"the block argument type must be a pointer to a "
571 "!cir.struct or !cir.union type");
573 if (expectedEltPtrTy.getPointee() != innerEltTy)
574 return op.emitOpError(
575 "block argument pointee type must match the innermost array "
578 if (expectedEltPtrTy.getAddrSpace() != ptrTy.getAddrSpace())
579 return op.emitOpError(
580 "block argument address space must match the 'addr' address space");
586LogicalResult cir::ArrayCtor::verify() {
590 mlir::Region &partialDtor = getPartialDtor();
591 if (!partialDtor.empty()) {
592 mlir::Block &dtorBlock = partialDtor.front();
593 if (dtorBlock.getNumArguments() != 1)
594 return emitOpError(
"partial_dtor must have exactly one block argument");
596 auto bodyArgTy = getBody().front().getArgument(0).getType();
597 if (dtorBlock.getArgument(0).getType() != bodyArgTy)
598 return emitOpError(
"partial_dtor block argument type must match "
599 "the body block argument type");
609LogicalResult cir::DeleteArrayOp::verify() {
610 if (getDtorMayThrow() && !getElementDtorAttr())
612 "'dtor_may_throw' requires an 'element_dtor' to be present");
621 cir::AssumeBundleKindAttr kindAttr,
622 OperandRange bundleArgs, TypeRange bundleArgTypes) {
623 cir::AssumeBundleKind
kind = kindAttr.getValue();
624 if (
kind == cir::AssumeBundleKind::None)
627 p <<
" " << cir::stringifyAssumeBundleKind(
kind);
628 if (bundleArgs.empty())
632 p.printOperands(bundleArgs);
634 llvm::interleaveComma(bundleArgTypes, p);
639 OpAsmParser &p, cir::AssumeBundleKindAttr &bundleKindAttr,
643 auto loc = p.getCurrentLocation();
644 if (failed(p.parseOptionalKeyword(&keyword))) {
645 bundleKindAttr = cir::AssumeBundleKindAttr::get(
646 p.getContext(), cir::AssumeBundleKind::None);
650 std::optional<cir::AssumeBundleKind> parsedKind =
651 cir::symbolizeAssumeBundleKind(keyword);
653 return p.emitError(loc,
"unknown assume bundle kind '") << keyword <<
"'";
655 bundleKindAttr = cir::AssumeBundleKindAttr::get(p.getContext(), *parsedKind);
657 if (p.parseOptionalLParen())
660 if (p.parseOperandList(bundleArgs) || p.parseColon() ||
661 p.parseTypeList(bundleArgTypes) || p.parseRParen())
667LogicalResult cir::AssumeOp::verify() {
668 cir::AssumeBundleKind
kind = getBundleKind();
669 size_t numArgs = getBundleArgs().size();
671 if (
kind == cir::AssumeBundleKind::None) {
673 return emitOpError(
"unexpected bundle operands for kind 'none'");
678 return emitOpError(
"expected bundle operands for kind '")
679 << cir::stringifyAssumeBundleKind(
kind) <<
"'";
682 case cir::AssumeBundleKind::Align:
683 if (numArgs != 2 && numArgs != 3)
684 return emitOpError(
"align bundle expects 2 or 3 operands");
686 case cir::AssumeBundleKind::SeparateStorage:
688 return emitOpError(
"separate_storage bundle expects 2 operands");
690 case cir::AssumeBundleKind::Dereferenceable:
692 return emitOpError(
"dereferenceable bundle expects 2 operands");
705cir::LocalInitOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
706 cir::GlobalOp global = getReferencedGlobal(symbolTable);
708 return emitOpError(
"'")
709 << getGlobalName() <<
"' does not reference a valid cir.global";
711 if (getTls() && !global.getTlsModel())
712 return emitOpError(
"access to global not marked thread local");
714 if (!global.getDynamicInitGuard().has_value())
715 return emitOpError(
"static_local attribute mismatch");
727 for (mlir::Operation *parent = op->getParentOp(); parent;
728 parent = parent->getParentOp()) {
729 mlir::Region *ctorRegion =
nullptr;
730 if (
auto global = mlir::dyn_cast<cir::GlobalOp>(parent))
731 ctorRegion = &global.getCtorRegion();
732 else if (
auto localInit = mlir::dyn_cast<cir::LocalInitOp>(parent))
733 ctorRegion = &localInit.getCtorRegion();
734 else if (mlir::isa<cir::FuncOp, cir::RegisterExitDtorOp>(parent))
737 return ctorRegion->isAncestor(op->getParentRegion());
742LogicalResult cir::RegisterExitDtorOp::verify() {
743 mlir::Block &body = getBody().front();
744 if (body.without_terminator().empty())
745 return emitOpError(
"body must destroy the object");
746 if (body.getTerminator()->getNumOperands())
747 return emitOpError(
"body must not yield a value");
749 return emitOpError(
"must be in the ctor region of a cir.global or "
755cir::RegisterExitDtorOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
756 auto global = symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(
757 *
this, getObjectAttr());
759 return emitOpError(
"'")
760 << getObject() <<
"' does not reference a valid cir.global";
761 if (!global.getCtorRegion().empty() || !global.getDtorRegion().empty())
762 return emitOpError(
"object must not have ctor or dtor regions");
774void cir::ConditionOp::getSuccessorRegions(
781 if (
auto loopOp = dyn_cast<LoopOpInterface>(getOperation()->getParentOp())) {
782 regions.emplace_back(&loopOp.getBody());
783 if (mlir::Region *cleanup = loopOp.maybeGetCleanup())
784 regions.emplace_back(cleanup);
786 regions.emplace_back(getOperation());
791 auto await = cast<AwaitOp>(getOperation()->getParentOp());
792 regions.emplace_back(&await.getResume());
793 regions.emplace_back(&await.getSuspend());
797cir::ConditionOp::getMutableSuccessorOperands(RegionSuccessor point) {
799 return MutableOperandRange(getOperation(), 0, 0);
803cir::ResumeOp::getMutableSuccessorOperands(RegionSuccessor point) {
805 return MutableOperandRange(getOperation(), 0, 0);
809cir::CoroSuspendPoint::getMutableSuccessorOperands(RegionSuccessor point) {
811 return MutableOperandRange(getOperation(), 0, 0);
814LogicalResult cir::ConditionOp::verify() {
815 if (!isa<LoopOpInterface, AwaitOp>(getOperation()->getParentOp()))
816 return emitOpError(
"condition must be within a conditional region");
824template <
typename LoopOpTy>
826 std::optional<cir::CleanupKind> cleanupKind = op.getCleanupKind();
830 if (cleanupKind.has_value() == op.getCleanup().empty())
831 return op.emitOpError(
"cleanup kind must be present if and only if the "
832 "cleanup region is non-empty");
837 if (cleanupKind == cir::CleanupKind::EH)
838 return op.emitOpError(
"loop cleanup kind must be 'normal' or 'all', "
853 mlir::Attribute attrType) {
854 if (isa<cir::ConstPtrAttr>(attrType)) {
855 if (!mlir::isa<cir::PointerType>(opType))
856 return op->emitOpError(
857 "pointer constant initializing a non-pointer type");
861 if (isa<cir::DataMemberAttr, cir::DataMemberOffsetAttr, cir::MethodAttr>(
868 if (isa<cir::ZeroAttr>(attrType)) {
869 if (isa<
cir::RecordType, cir::ArrayType, cir::MatrixType, cir::VectorType,
870 cir::ComplexType>(opType))
872 return op->emitOpError(
873 "zero expects struct, array, vector, or complex type");
876 if (mlir::isa<cir::UndefAttr>(attrType)) {
877 if (!mlir::isa<cir::VoidType>(opType))
879 return op->emitOpError(
"undef expects non-void type");
882 if (mlir::isa<cir::BoolAttr>(attrType)) {
883 if (!mlir::isa<cir::BoolType>(opType))
884 return op->emitOpError(
"result type (")
885 << opType <<
") must be '!cir.bool' for '" << attrType <<
"'";
889 if (mlir::isa<cir::IntAttr, cir::FPAttr>(attrType)) {
890 auto at = cast<TypedAttr>(attrType);
891 if (at.getType() != opType) {
892 return op->emitOpError(
"result type (")
893 << opType <<
") does not match value type (" << at.getType()
899 if (mlir::isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr,
900 cir::ConstArrayAttr, cir::ConstVectorAttr,
901 cir::ConstComplexAttr, cir::ConstRecordAttr,
902 cir::GlobalOffsetAttr, cir::GlobalViewAttr, cir::PoisonAttr,
903 cir::TypeInfoAttr, cir::VTableAttr>(attrType))
906 assert(isa<TypedAttr>(attrType) &&
"What else could we be looking at here?");
907 return op->emitOpError(
"global with type ")
908 << cast<TypedAttr>(attrType).getType() <<
" not yet supported";
911LogicalResult cir::ConstantOp::verify() {
918OpFoldResult cir::ConstantOp::fold(FoldAdaptor ) {
928 case cir::CastKind::floating:
929 case cir::CastKind::int_to_float:
930 case cir::CastKind::float_to_int:
931 case cir::CastKind::float_to_bool:
932 case cir::CastKind::bool_to_float:
933 case cir::CastKind::float_to_complex:
934 case cir::CastKind::float_complex_to_real:
935 case cir::CastKind::float_complex_to_bool:
936 case cir::CastKind::float_complex:
937 case cir::CastKind::float_complex_to_int_complex:
938 case cir::CastKind::int_complex_to_float_complex:
945LogicalResult cir::CastOp::verify() {
946 mlir::Type resType =
getType();
947 mlir::Type srcType = getSrc().getType();
952 <<
"'fenv' is only valid for floating-point cast kinds";
956 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
957 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
958 if (srcPtrTy && resPtrTy && (
kind != cir::CastKind::address_space))
959 if (srcPtrTy.getAddrSpace() != resPtrTy.getAddrSpace()) {
960 return emitOpError() <<
"result type address space does not match the "
961 "address space of the operand";
964 auto srcVTy = mlir::dyn_cast<cir::VectorType>(srcType);
965 auto resVTy = mlir::dyn_cast<cir::VectorType>(resType);
966 if (srcVTy && resVTy) {
967 if ((
kind == cir::CastKind::int_to_float ||
968 kind == cir::CastKind::float_to_int) &&
969 srcVTy.getSize() != resVTy.getSize()) {
971 <<
"vector float-to-int and int-to-float casts require "
972 "source and destination vectors to have the same number of "
977 srcType = srcVTy.getElementType();
978 resType = resVTy.getElementType();
982 case cir::CastKind::int_to_bool: {
983 if (!mlir::isa<cir::BoolType>(resType))
984 return emitOpError() <<
"requires !cir.bool type for result";
985 if (!mlir::isa<cir::IntType>(srcType))
986 return emitOpError() <<
"requires !cir.int type for source";
989 case cir::CastKind::ptr_to_bool: {
990 if (!mlir::isa<cir::BoolType>(resType))
991 return emitOpError() <<
"requires !cir.bool type for result";
992 if (!mlir::isa<cir::PointerType>(srcType))
993 return emitOpError() <<
"requires !cir.ptr type for source";
996 case cir::CastKind::integral: {
997 if (!mlir::isa<cir::IntType>(resType))
998 return emitOpError() <<
"requires !cir.int type for result";
999 if (!mlir::isa<cir::IntType>(srcType))
1000 return emitOpError() <<
"requires !cir.int type for source";
1003 case cir::CastKind::array_to_ptrdecay: {
1004 const auto arrayPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
1005 const auto flatPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
1006 if (!arrayPtrTy || !flatPtrTy)
1007 return emitOpError() <<
"requires !cir.ptr type for source and result";
1012 case cir::CastKind::bitcast: {
1014 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
1015 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
1017 if (srcPtrTy && resPtrTy) {
1023 case cir::CastKind::floating: {
1024 if (!mlir::isa<cir::FPTypeInterface>(srcType) ||
1025 !mlir::isa<cir::FPTypeInterface>(resType))
1026 return emitOpError() <<
"requires !cir.float type for source and result";
1029 case cir::CastKind::float_to_int: {
1030 if (!mlir::isa<cir::FPTypeInterface>(srcType))
1031 return emitOpError() <<
"requires !cir.float type for source";
1032 if (!mlir::dyn_cast<cir::IntType>(resType))
1033 return emitOpError() <<
"requires !cir.int type for result";
1036 case cir::CastKind::int_to_ptr: {
1037 if (!mlir::dyn_cast<cir::IntType>(srcType))
1038 return emitOpError() <<
"requires !cir.int type for source";
1039 if (!mlir::dyn_cast<cir::PointerType>(resType))
1040 return emitOpError() <<
"requires !cir.ptr type for result";
1043 case cir::CastKind::ptr_to_int: {
1044 if (!mlir::dyn_cast<cir::PointerType>(srcType))
1045 return emitOpError() <<
"requires !cir.ptr type for source";
1046 if (!mlir::dyn_cast<cir::IntType>(resType))
1047 return emitOpError() <<
"requires !cir.int type for result";
1050 case cir::CastKind::float_to_bool: {
1051 if (!mlir::isa<cir::FPTypeInterface>(srcType))
1052 return emitOpError() <<
"requires !cir.float type for source";
1053 if (!mlir::isa<cir::BoolType>(resType))
1054 return emitOpError() <<
"requires !cir.bool type for result";
1057 case cir::CastKind::bool_to_int: {
1058 if (!mlir::isa<cir::BoolType>(srcType))
1059 return emitOpError() <<
"requires !cir.bool type for source";
1060 if (!mlir::isa<cir::IntType>(resType))
1061 return emitOpError() <<
"requires !cir.int type for result";
1064 case cir::CastKind::int_to_float: {
1065 if (!mlir::isa<cir::IntType>(srcType))
1066 return emitOpError() <<
"requires !cir.int type for source";
1067 if (!mlir::isa<cir::FPTypeInterface>(resType))
1068 return emitOpError() <<
"requires !cir.float type for result";
1071 case cir::CastKind::bool_to_float: {
1072 if (!mlir::isa<cir::BoolType>(srcType))
1073 return emitOpError() <<
"requires !cir.bool type for source";
1074 if (!mlir::isa<cir::FPTypeInterface>(resType))
1075 return emitOpError() <<
"requires !cir.float type for result";
1078 case cir::CastKind::address_space: {
1079 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
1080 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
1081 if (!srcPtrTy || !resPtrTy)
1082 return emitOpError() <<
"requires !cir.ptr type for source and result";
1083 if (srcPtrTy.getPointee() != resPtrTy.getPointee())
1084 return emitOpError() <<
"requires two types differ in addrspace only";
1087 case cir::CastKind::float_to_complex: {
1088 if (!mlir::isa<cir::FPTypeInterface>(srcType))
1089 return emitOpError() <<
"requires !cir.float type for source";
1090 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
1092 return emitOpError() <<
"requires !cir.complex type for result";
1093 if (srcType != resComplexTy.getElementType())
1094 return emitOpError() <<
"requires source type match result element type";
1097 case cir::CastKind::int_to_complex: {
1098 if (!mlir::isa<cir::IntType>(srcType))
1099 return emitOpError() <<
"requires !cir.int type for source";
1100 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
1102 return emitOpError() <<
"requires !cir.complex type for result";
1103 if (srcType != resComplexTy.getElementType())
1104 return emitOpError() <<
"requires source type match result element type";
1107 case cir::CastKind::float_complex_to_real: {
1108 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1110 return emitOpError() <<
"requires !cir.complex type for source";
1111 if (!mlir::isa<cir::FPTypeInterface>(resType))
1112 return emitOpError() <<
"requires !cir.float type for result";
1113 if (srcComplexTy.getElementType() != resType)
1114 return emitOpError() <<
"requires source element type match result type";
1117 case cir::CastKind::int_complex_to_real: {
1118 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1120 return emitOpError() <<
"requires !cir.complex type for source";
1121 if (!mlir::isa<cir::IntType>(resType))
1122 return emitOpError() <<
"requires !cir.int type for result";
1123 if (srcComplexTy.getElementType() != resType)
1124 return emitOpError() <<
"requires source element type match result type";
1127 case cir::CastKind::float_complex_to_bool: {
1128 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1129 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
1130 return emitOpError()
1131 <<
"requires floating point !cir.complex type for source";
1132 if (!mlir::isa<cir::BoolType>(resType))
1133 return emitOpError() <<
"requires !cir.bool type for result";
1136 case cir::CastKind::int_complex_to_bool: {
1137 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1138 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
1139 return emitOpError()
1140 <<
"requires floating point !cir.complex type for source";
1141 if (!mlir::isa<cir::BoolType>(resType))
1142 return emitOpError() <<
"requires !cir.bool type for result";
1145 case cir::CastKind::float_complex: {
1146 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1147 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
1148 return emitOpError()
1149 <<
"requires floating point !cir.complex type for source";
1150 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
1151 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
1152 return emitOpError()
1153 <<
"requires floating point !cir.complex type for result";
1156 case cir::CastKind::float_complex_to_int_complex: {
1157 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1158 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
1159 return emitOpError()
1160 <<
"requires floating point !cir.complex type for source";
1161 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
1162 if (!resComplexTy || !resComplexTy.isIntegerComplex())
1163 return emitOpError() <<
"requires integer !cir.complex type for result";
1166 case cir::CastKind::int_complex: {
1167 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1168 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
1169 return emitOpError() <<
"requires integer !cir.complex type for source";
1170 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
1171 if (!resComplexTy || !resComplexTy.isIntegerComplex())
1172 return emitOpError() <<
"requires integer !cir.complex type for result";
1175 case cir::CastKind::int_complex_to_float_complex: {
1176 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1177 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
1178 return emitOpError() <<
"requires integer !cir.complex type for source";
1179 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
1180 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
1181 return emitOpError()
1182 <<
"requires floating point !cir.complex type for result";
1185 case cir::CastKind::member_ptr_to_bool: {
1186 if (!mlir::isa<cir::DataMemberType, cir::MethodType>(srcType))
1187 return emitOpError()
1188 <<
"requires !cir.data_member or !cir.method type for source";
1189 if (!mlir::isa<cir::BoolType>(resType))
1190 return emitOpError() <<
"requires !cir.bool type for result";
1194 llvm_unreachable(
"Unknown CastOp kind?");
1198 auto kind = op.getKind();
1199 return kind == cir::CastKind::bool_to_int ||
1200 kind == cir::CastKind::int_to_bool ||
kind == cir::CastKind::integral;
1204 const auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty);
1205 return ptrTy && mlir::isa<cir::FuncType>(ptrTy.getPointee());
1209 cir::CastOp head = op, tail = op;
1215 op = head.getSrc().getDefiningOp<cir::CastOp>();
1221 if (head.getKind() == cir::CastKind::bool_to_int &&
1222 tail.getKind() == cir::CastKind::int_to_bool)
1223 return head.getSrc();
1228 if (head.getKind() == cir::CastKind::int_to_bool &&
1229 tail.getKind() == cir::CastKind::int_to_bool)
1230 return head.getResult();
1238 if (tail.getKind() == cir::CastKind::bitcast) {
1239 auto *inner = tail.getSrc().getDefiningOp();
1241 auto innerCast = mlir::dyn_cast<cir::CastOp>(inner);
1242 if (innerCast && innerCast.getKind() == cir::CastKind::bitcast &&
1243 innerCast.getSrc().getType() == tail.getType() &&
1244 innerCast.getType() == tail.getSrc().getType()) {
1245 return innerCast.getSrc();
1253OpFoldResult cir::CastOp::fold(FoldAdaptor adaptor) {
1254 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getSrc())) {
1256 return cir::PoisonAttr::get(getContext(),
getType());
1260 if (mlir::isa_and_present<cir::UndefAttr>(adaptor.getSrc()))
1261 return cir::UndefAttr::get(
getType());
1265 case cir::CastKind::integral:
1266 case cir::CastKind::bitcast:
1267 case cir::CastKind::address_space:
1268 case cir::CastKind::float_complex:
1269 case cir::CastKind::int_complex: {
1283 if (
auto srcConst = getSrc().getDefiningOp<cir::ConstantOp>()) {
1285 case cir::CastKind::integral: {
1286 mlir::Type srcTy = getSrc().getType();
1288 assert(mlir::isa<cir::VectorType>(srcTy) ==
1289 mlir::isa<cir::VectorType>(
getType()));
1290 if (mlir::isa<cir::VectorType>(srcTy))
1293 auto srcIntTy = mlir::cast<cir::IntType>(srcTy);
1294 auto dstIntTy = mlir::cast<cir::IntType>(
getType());
1295 auto constIntAttr = srcConst.getValueAttr<cir::IntAttr>();
1299 APInt srcValue = constIntAttr.getValue();
1300 APInt newVal = srcIntTy.isSigned()
1301 ? srcValue.sextOrTrunc(dstIntTy.getWidth())
1302 : srcValue.zextOrTrunc(dstIntTy.getWidth());
1303 return cir::IntAttr::get(dstIntTy, newVal);
1316LogicalResult cir::BuiltinIntCastOp::verify() {
1317 mlir::Type srcType = getSrc().getType();
1318 mlir::Type resType =
getType();
1320 auto srcCirInt = mlir::dyn_cast<cir::IntType>(srcType);
1321 auto resCirInt = mlir::dyn_cast<cir::IntType>(resType);
1325 if (
static_cast<bool>(srcCirInt) ==
static_cast<bool>(resCirInt))
1326 return emitOpError()
1327 <<
"requires exactly one '!cir.int' operand or result; the other "
1328 "must be a builtin integer or 'index' type";
1330 mlir::Type
builtinType = srcCirInt ? resType : srcType;
1331 if (!mlir::isa<mlir::IntegerType, mlir::IndexType>(builtinType))
1332 return emitOpError() <<
"requires a builtin integer or 'index' type on the "
1337 if (
auto builtinInt = mlir::dyn_cast<mlir::IntegerType>(builtinType)) {
1338 cir::IntType cirInt = srcCirInt ? srcCirInt : resCirInt;
1339 if (cirInt.getWidth() != builtinInt.getWidth())
1340 return emitOpError()
1341 <<
"requires the CIR and builtin integer types to have the same "
1342 "width; use 'cir.cast' for width conversions";
1348OpFoldResult cir::BuiltinIntCastOp::fold(FoldAdaptor adaptor) {
1351 if (
auto inner = getSrc().getDefiningOp<cir::BuiltinIntCastOp>())
1352 if (inner.getSrc().getType() ==
getType())
1353 return inner.getSrc();
1361mlir::OperandRange cir::CallOp::getArgOperands() {
1363 return getArgs().drop_front(1);
1367mlir::MutableOperandRange cir::CallOp::getArgOperandsMutable() {
1368 mlir::MutableOperandRange args = getArgsMutable();
1370 return args.slice(1, args.size() - 1);
1374mlir::Value cir::CallOp::getIndirectCall() {
1375 assert(isIndirect());
1376 return getOperand(0);
1380Value cir::CallOp::getArgOperand(
unsigned i) {
1383 return getOperand(i);
1387unsigned cir::CallOp::getNumArgOperands() {
1389 return this->getOperation()->getNumOperands() - 1;
1390 return this->getOperation()->getNumOperands();
1393static mlir::ParseResult
1395 mlir::OperationState &result) {
1396 mlir::Block *normalDestSuccessor;
1397 if (parser.parseSuccessor(normalDestSuccessor))
1398 return mlir::failure();
1400 if (parser.parseComma())
1401 return mlir::failure();
1403 mlir::Block *unwindDestSuccessor;
1404 if (parser.parseSuccessor(unwindDestSuccessor))
1405 return mlir::failure();
1407 result.addSuccessors(normalDestSuccessor);
1408 result.addSuccessors(unwindDestSuccessor);
1409 return mlir::success();
1418 const mlir::NamedAttrList &attrs) {
1419 if (mlir::Attribute effects =
1420 attrs.get(CIRDialect::getMemoryEffectsAttrName()))
1421 if (!mlir::isa<cir::MemoryEffectsAttr>(effects))
1422 return parser.emitError(loc,
"attribute '")
1423 << CIRDialect::getMemoryEffectsAttrName()
1424 <<
"' must be a #cir.memory_effects attribute";
1426 if (mlir::Attribute uwtable = attrs.get(CIRDialect::getUwtableAttrName()))
1427 if (!mlir::isa<cir::UnwindTableKindAttr>(uwtable))
1428 return parser.emitError(loc,
"attribute '")
1429 << CIRDialect::getUwtableAttrName()
1430 <<
"' must be a #cir.uwtable attribute";
1432 if (mlir::Attribute framePointer =
1433 attrs.get(CIRDialect::getFramePointerAttrName()))
1434 if (!mlir::isa<cir::FramePointerKindAttr>(framePointer))
1435 return parser.emitError(loc,
"attribute '")
1436 << CIRDialect::getFramePointerAttrName()
1437 <<
"' must be a #cir.frame_pointer attribute";
1439 for (llvm::StringRef name :
1440 {CIRDialect::getNoUnwindAttrName(), CIRDialect::getWillReturnAttrName(),
1441 CIRDialect::getMustProgressAttrName()})
1442 if (mlir::Attribute flag = attrs.get(name))
1443 if (!mlir::isa<mlir::UnitAttr>(flag))
1444 return parser.emitError(loc,
"attribute '")
1445 << name <<
"' must be a unit attribute";
1447 return mlir::success();
1451 mlir::OperationState &result,
1452 bool hasDestinationBlocks =
false) {
1455 mlir::FlatSymbolRefAttr calleeAttr;
1459 .parseOptionalAttribute(calleeAttr, CIRDialect::getCalleeAttrName(),
1462 OpAsmParser::UnresolvedOperand indirectVal;
1464 if (parser.parseOperand(indirectVal).failed())
1466 ops.push_back(indirectVal);
1469 if (parser.parseLParen())
1470 return mlir::failure();
1472 opsLoc = parser.getCurrentLocation();
1473 if (parser.parseOperandList(ops))
1474 return mlir::failure();
1475 if (parser.parseRParen())
1476 return mlir::failure();
1478 if (hasDestinationBlocks &&
1480 return ::mlir::failure();
1483 if (parser.parseOptionalKeyword(
"cc").succeeded()) {
1484 cir::CallingConv callingConv;
1485 if (parser.parseLParen().failed())
1488 return parser.emitError(parser.getCurrentLocation(),
1489 "unknown calling convention");
1490 if (parser.parseRParen().failed())
1492 result.addAttribute(
1493 CIRDialect::getCallingConvAttrName(),
1494 cir::CallingConvAttr::get(parser.getContext(), callingConv));
1497 if (parser.parseOptionalKeyword(
"musttail").succeeded())
1498 result.addAttribute(CIRDialect::getMustTailAttrName(),
1499 mlir::UnitAttr::get(parser.getContext()));
1501 if (parser.parseOptionalKeyword(
"nothrow").succeeded())
1502 result.addAttribute(CIRDialect::getNoThrowAttrName(),
1503 mlir::UnitAttr::get(parser.getContext()));
1505 if (parser.parseOptionalKeyword(
"nounwind").succeeded())
1506 result.addAttribute(CIRDialect::getNoUnwindAttrName(),
1507 mlir::UnitAttr::get(parser.getContext()));
1509 if (parser.parseOptionalKeyword(
"willreturn").succeeded())
1510 result.addAttribute(CIRDialect::getWillReturnAttrName(),
1511 mlir::UnitAttr::get(parser.getContext()));
1513 llvm::SMLoc attrsLoc = parser.getCurrentLocation();
1514 if (parser.parseOptionalAttrDict(result.attributes))
1515 return ::mlir::failure();
1518 return ::mlir::failure();
1520 if (parser.parseColon())
1521 return ::mlir::failure();
1527 if (call_interface_impl::parseFunctionSignature(parser, argTypes, argAttrs,
1528 resultTypes, resultAttrs))
1529 return mlir::failure();
1531 if (resultTypes.size() > 1 || resultAttrs.size() > 1)
1532 return parser.emitError(
1533 parser.getCurrentLocation(),
1534 "functions with multiple return types are not supported");
1536 result.addTypes(resultTypes);
1538 if (parser.resolveOperands(ops, argTypes, opsLoc, result.operands))
1539 return mlir::failure();
1541 if (!resultAttrs.empty() && resultAttrs[0])
1542 result.addAttribute(
1543 CIRDialect::getResAttrsAttrName(),
1544 mlir::ArrayAttr::get(parser.getContext(), {resultAttrs[0]}));
1549 bool argAttrsEmpty =
true;
1551 llvm::transform(argAttrs, std::back_inserter(convertedArgAttrs),
1552 [&](DictionaryAttr da) -> mlir::Attribute {
1554 argAttrsEmpty =
false;
1558 if (!argAttrsEmpty) {
1563 argAttrsRef = argAttrsRef.drop_front();
1565 result.addAttribute(CIRDialect::getArgAttrsAttrName(),
1566 mlir::ArrayAttr::get(parser.getContext(), argAttrsRef));
1569 return mlir::success();
1573 mlir::FlatSymbolRefAttr calleeSym,
1574 mlir::Value indirectCallee,
1575 mlir::OpAsmPrinter &printer,
bool isNothrow,
1576 ArrayAttr argAttrs, ArrayAttr resAttrs,
1577 mlir::Block *normalDest =
nullptr,
1578 mlir::Block *unwindDest =
nullptr) {
1581 auto callLikeOp = mlir::cast<cir::CIRCallOpInterface>(op);
1582 auto ops = callLikeOp.getArgOperands();
1586 printer.printAttributeWithoutType(calleeSym);
1589 assert(indirectCallee);
1590 printer << indirectCallee;
1593 printer <<
"(" << ops <<
")";
1596 assert(unwindDest &&
"expected two successors");
1597 auto tryCall = cast<cir::TryCallOp>(op);
1598 printer <<
' ' << tryCall.getNormalDest();
1601 printer << tryCall.getUnwindDest();
1604 cir::CallingConv callingConv = callLikeOp.getCallingConv();
1605 if (callingConv != cir::CallingConv::C)
1606 printer <<
" cc(" << stringifyCallingConv(callingConv) <<
")";
1608 if (op->hasAttr(CIRDialect::getMustTailAttrName()))
1609 printer <<
" musttail";
1612 printer <<
" nothrow";
1614 if (op->hasAttr(CIRDialect::getNoUnwindAttrName()))
1615 printer <<
" nounwind";
1617 if (op->hasAttr(CIRDialect::getWillReturnAttrName()))
1618 printer <<
" willreturn";
1620 llvm::StringRef elidedAttrs[] = {
1621 CIRDialect::getCalleeAttrName(),
1622 CIRDialect::getCallingConvAttrName(),
1623 CIRDialect::getMustTailAttrName(),
1624 CIRDialect::getNoThrowAttrName(),
1625 CIRDialect::getNoUnwindAttrName(),
1626 CIRDialect::getWillReturnAttrName(),
1627 CIRDialect::getOperandSegmentSizesAttrName(),
1634 for (mlir::NamedAttribute attr : op->getDiscardableAttrs())
1635 if (!llvm::is_contained(elidedAttrs, attr.getName()))
1636 attrs.push_back(attr);
1637 op->getName().walkInherentAttrs(op, [&](llvm::StringRef name,
1638 mlir::Attribute &attr) {
1639 if (!llvm::is_contained(elidedAttrs, name))
1640 attrs.emplace_back(mlir::StringAttr::get(op->getContext(), name), attr);
1642 llvm::sort(attrs, [](mlir::NamedAttribute lhs, mlir::NamedAttribute rhs) {
1643 return lhs.getName().strref() < rhs.getName().strref();
1645 printer.printOptionalAttrDict(attrs);
1647 if (calleeSym || !argAttrs) {
1648 call_interface_impl::printFunctionSignature(
1649 printer, op->getOperands().getTypes(), argAttrs,
1650 false, op->getResultTypes(), resAttrs);
1658 shimmedArgAttrs.push_back(mlir::DictionaryAttr::get(op->getContext(), {}));
1659 shimmedArgAttrs.append(argAttrs.begin(), argAttrs.end());
1660 call_interface_impl::printFunctionSignature(
1661 printer, op->getOperands().getTypes(),
1662 mlir::ArrayAttr::get(op->getContext(), shimmedArgAttrs),
1663 false, op->getResultTypes(), resAttrs);
1667mlir::ParseResult cir::CallOp::parse(mlir::OpAsmParser &parser,
1668 mlir::OperationState &result) {
1672void cir::CallOp::print(mlir::OpAsmPrinter &p) {
1673 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
1674 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
1675 getArgAttrsAttr(), getResAttrsAttr());
1680 SymbolTableCollection &symbolTable) {
1681 auto callIf = cast<cir::CIRCallOpInterface>(op);
1685 cir::FuncType fnType;
1686 bool hasPrototype =
true;
1688 op->getAttrOfType<FlatSymbolRefAttr>(CIRDialect::getCalleeAttrName());
1690 if (op->getNumOperands() == 0)
1691 return op->emitOpError(
"indirect call requires a callee operand");
1692 mlir::Type calleeTy = callIf.getIndirectCall().getType();
1693 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(calleeTy))
1694 fnType = mlir::dyn_cast<cir::FuncType>(ptrTy.getPointee());
1696 return op->emitOpError()
1697 <<
"indirect callee must be a pointer to a function, but has type "
1700 auto fn = symbolTable.lookupNearestSymbolFrom<cir::FuncOp>(op, fnAttr);
1702 return op->emitOpError() <<
"'" << fnAttr.getValue()
1703 <<
"' does not reference a valid function";
1704 fnType = fn.getFunctionType();
1705 hasPrototype = !fn.getNoProto();
1711 unsigned numCallOperands = callIf.getNumArgOperands();
1712 unsigned numFnOpOperands = fnType.getNumInputs();
1714 if (!fnType.isVarArg() && numCallOperands != numFnOpOperands)
1715 return op->emitOpError(
"incorrect number of operands for callee");
1716 if (fnType.isVarArg() && numCallOperands < numFnOpOperands)
1717 return op->emitOpError(
"too few operands for callee");
1719 for (
unsigned i = 0, e = numFnOpOperands; i != e; ++i)
1720 if (callIf.getArgOperand(i).getType() != fnType.getInput(i))
1721 return op->emitOpError(
"operand type mismatch: expected operand type ")
1722 << fnType.getInput(i) <<
", but provided "
1723 << callIf.getArgOperand(i).getType() <<
" for operand number "
1730 if (fnType.hasVoidReturn() && op->getNumResults() != 0)
1731 return op->emitOpError(
"callee returns void but call has results");
1734 if (!fnType.hasVoidReturn() && op->getNumResults() != 1)
1735 return op->emitOpError(
"incorrect number of results for callee");
1738 if (!fnType.hasVoidReturn() &&
1739 op->getResultTypes().front() != fnType.getReturnType()) {
1740 return op->emitOpError(
"result type mismatch: expected ")
1741 << fnType.getReturnType() <<
", but provided "
1742 << op->getResult(0).getType();
1745 return mlir::success();
1749cir::CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1757mlir::OperandRange cir::TryCallOp::getArgOperands() {
1759 return getArgs().drop_front(1);
1763mlir::MutableOperandRange cir::TryCallOp::getArgOperandsMutable() {
1764 mlir::MutableOperandRange args = getArgsMutable();
1766 return args.slice(1, args.size() - 1);
1770mlir::Value cir::TryCallOp::getIndirectCall() {
1771 assert(isIndirect());
1772 return getOperand(0);
1776Value cir::TryCallOp::getArgOperand(
unsigned i) {
1779 return getOperand(i);
1783unsigned cir::TryCallOp::getNumArgOperands() {
1785 return this->getOperation()->getNumOperands() - 1;
1786 return this->getOperation()->getNumOperands();
1790cir::TryCallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1794mlir::ParseResult cir::TryCallOp::parse(mlir::OpAsmParser &parser,
1795 mlir::OperationState &result) {
1799void cir::TryCallOp::print(::mlir::OpAsmPrinter &p) {
1800 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
1801 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
1802 getArgAttrsAttr(), getResAttrsAttr(), getNormalDest(),
1811 cir::FuncOp function) {
1813 if (op.getNumOperands() > 1)
1814 return op.emitOpError() <<
"expects at most 1 return operand";
1817 auto expectedTy = function.getFunctionType().getReturnType();
1819 (op.getNumOperands() == 0 ? cir::VoidType::get(op.getContext())
1820 : op.getOperand(0).getType());
1821 if (actualTy != expectedTy)
1822 return op.emitOpError() <<
"returns " << actualTy
1823 <<
" but enclosing function returns " << expectedTy;
1825 return mlir::success();
1828mlir::LogicalResult cir::ReturnOp::verify() {
1831 auto *fnOp = getOperation()->getParentOp();
1832 while (!isa<cir::FuncOp>(fnOp))
1833 fnOp = fnOp->getParentOp();
1846ParseResult cir::IfOp::parse(OpAsmParser &parser, OperationState &result) {
1848 result.regions.reserve(2);
1849 Region *thenRegion = result.addRegion();
1850 Region *elseRegion = result.addRegion();
1852 mlir::Builder &builder = parser.getBuilder();
1853 OpAsmParser::UnresolvedOperand cond;
1854 Type boolType = cir::BoolType::get(builder.getContext());
1856 if (parser.parseOperand(cond) ||
1857 parser.resolveOperand(cond, boolType, result.operands))
1861 mlir::SMLoc parseThenLoc = parser.getCurrentLocation();
1862 if (parser.parseRegion(*thenRegion, {}, {}))
1869 if (!parser.parseOptionalKeyword(
"else")) {
1870 mlir::SMLoc parseElseLoc = parser.getCurrentLocation();
1871 if (parser.parseRegion(*elseRegion, {}, {}))
1878 if (parser.parseOptionalAttrDict(result.attributes))
1883void cir::IfOp::print(OpAsmPrinter &p) {
1884 p <<
" " << getCondition() <<
" ";
1885 mlir::Region &thenRegion = this->getThenRegion();
1886 p.printRegion(thenRegion,
1891 mlir::Region &elseRegion = this->getElseRegion();
1892 if (!elseRegion.empty()) {
1894 p.printRegion(elseRegion,
1899 p.printOptionalAttrDict(
1900 getOperation()->getDiscardableAttrDictionary().getValue());
1906 cir::YieldOp::create(builder, loc);
1914void cir::IfOp::getSuccessorRegions(mlir::RegionBranchPoint point,
1915 SmallVectorImpl<RegionSuccessor> ®ions) {
1917 if (!point.isParent()) {
1918 regions.emplace_back(getOperation());
1923 Region *elseRegion = &this->getElseRegion();
1924 if (elseRegion->empty())
1925 elseRegion =
nullptr;
1928 regions.push_back(RegionSuccessor(&getThenRegion()));
1930 regions.push_back(RegionSuccessor(elseRegion));
1932 regions.emplace_back(getOperation());
1935void cir::IfOp::build(OpBuilder &builder, OperationState &result,
Value cond,
1938 assert(thenBuilder &&
"the builder callback for 'then' must be present");
1939 result.addOperands(cond);
1941 OpBuilder::InsertionGuard guard(builder);
1942 Region *thenRegion = result.addRegion();
1943 builder.createBlock(thenRegion);
1944 thenBuilder(builder, result.location);
1946 Region *elseRegion = result.addRegion();
1947 if (!withElseRegion)
1950 builder.createBlock(elseRegion);
1951 elseBuilder(builder, result.location);
1958void cir::ScopeOp::build(
1959 OpBuilder &builder, OperationState &result,
1960 function_ref<
void(OpBuilder &, Type &, Location)> scopeBuilder) {
1961 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1963 OpBuilder::InsertionGuard guard(builder);
1964 Region *scopeRegion = result.addRegion();
1965 builder.createBlock(scopeRegion);
1969 scopeBuilder(builder, yieldTy, result.location);
1972 result.addTypes(TypeRange{yieldTy});
1975void cir::ScopeOp::build(
1976 OpBuilder &builder, OperationState &result,
1977 function_ref<
void(OpBuilder &, Location)> scopeBuilder) {
1978 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1979 OpBuilder::InsertionGuard guard(builder);
1980 Region *scopeRegion = result.addRegion();
1981 builder.createBlock(scopeRegion);
1983 scopeBuilder(builder, result.location);
1986LogicalResult cir::ScopeOp::verify() {
1987 if (getRegion().empty()) {
1988 return emitOpError() <<
"cir.scope must not be empty since it should "
1989 "include at least an implicit cir.yield ";
1992 mlir::Block &lastBlock = getRegion().back();
1993 if (lastBlock.empty() || !lastBlock.mightHaveTerminator() ||
1994 !lastBlock.getTerminator()->hasTrait<OpTrait::IsTerminator>())
1995 return emitOpError() <<
"last block of cir.scope must be terminated";
1999LogicalResult cir::ScopeOp::fold(FoldAdaptor ,
2000 SmallVectorImpl<OpFoldResult> &results) {
2002 if (!getRegion().hasOneBlock())
2004 Block &block = getRegion().front();
2005 if (block.getOperations().size() != 1)
2008 auto yield = dyn_cast<cir::YieldOp>(block.front());
2013 if (getNumResults() != 1 || yield.getNumOperands() != 1)
2016 results.push_back(yield.getOperand(0));
2025 for (mlir::Block &block : cleanupRegion) {
2026 for (mlir::Operation &op : block) {
2027 if (isa<cir::YieldOp, cir::LifetimeEndOp, cir::StackRestoreOp>(op))
2030 auto loadOp = dyn_cast<cir::LoadOp>(op);
2031 if (loadOp && loadOp.getResult().hasOneUse() &&
2032 isa<cir::StackRestoreOp>(*loadOp.getResult().getUsers().begin()))
2040LogicalResult cir::CleanupScopeOp::verify() {
2044 cir::CallOp mustTailCall;
2045 getBodyRegion().walk([&](cir::CallOp callOp) {
2046 if (!callOp.getMusttail())
2047 return WalkResult::advance();
2048 mustTailCall = callOp;
2049 return WalkResult::interrupt();
2057 InFlightDiagnostic diag =
2058 emitOpError(
"cleanup is not redundant before a return, so it cannot be "
2059 "skipped by a musttail call");
2060 diag.attachNote(mustTailCall.getLoc()) <<
"musttail call is here";
2064void cir::CleanupScopeOp::getSuccessorRegions(
2065 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
2070 if (point.isParent()) {
2071 regions.reserve(regions.size() + 2);
2072 regions.emplace_back(&getBodyRegion());
2073 regions.emplace_back(&getCleanupRegion());
2077 mlir::Operation *term = point.getTerminatorPredecessorOrNull();
2078 if (term->getParentRegion() == &getCleanupRegion()) {
2079 regions.emplace_back(getOperation());
2083 regions.emplace_back(&getCleanupRegion());
2088 cir::CleanupKindAttr
kind = getCleanupKindAttr();
2089 if (isa<cir::ResumeOp>(term) ? !
kind.isEH() : !
kind.isNormal())
2090 regions.emplace_back(getOperation());
2093LogicalResult cir::CleanupScopeOp::canonicalize(CleanupScopeOp op,
2094 PatternRewriter &rewriter) {
2095 auto isRegionTrivial = [](Region ®ion) {
2096 assert(!region.empty() &&
"CleanupScopeOp regions must not be empty");
2097 if (!region.hasOneBlock())
2099 Block &block = llvm::getSingleElement(region);
2100 return llvm::hasSingleElement(block) &&
2101 isa<cir::YieldOp>(llvm::getSingleElement(block));
2104 Region &body = op.getBodyRegion();
2105 Region &
cleanup = op.getCleanupRegion();
2109 if (op.getCleanupKind() == CleanupKind::EH && isRegionTrivial(body)) {
2110 rewriter.eraseOp(op);
2116 if (!isRegionTrivial(cleanup) || !body.hasOneBlock())
2119 Block &bodyBlock = body.front();
2120 if (!isa<cir::YieldOp>(bodyBlock.getTerminator()))
2123 Operation *yield = bodyBlock.getTerminator();
2124 rewriter.inlineBlockBefore(&bodyBlock, op);
2125 rewriter.eraseOp(yield);
2126 rewriter.eraseOp(op);
2130void cir::CleanupScopeOp::build(
2131 OpBuilder &builder, OperationState &result, CleanupKind cleanupKind,
2132 function_ref<
void(OpBuilder &, Location)> bodyBuilder,
2133 function_ref<
void(OpBuilder &, Location)> cleanupBuilder) {
2134 result.addAttribute(getCleanupKindAttrName(result.name),
2135 CleanupKindAttr::get(builder.getContext(), cleanupKind));
2137 OpBuilder::InsertionGuard guard(builder);
2140 Region *bodyRegion = result.addRegion();
2141 builder.createBlock(bodyRegion);
2143 bodyBuilder(builder, result.location);
2146 Region *cleanupRegion = result.addRegion();
2147 builder.createBlock(cleanupRegion);
2149 cleanupBuilder(builder, result.location);
2164LogicalResult cir::BrOp::canonicalize(BrOp op, PatternRewriter &rewriter) {
2165 Block *src = op->getBlock();
2166 Block *dst = op.getDest();
2173 if (src->getNumSuccessors() != 1 || dst->getSinglePredecessor() != src)
2178 if (isa<cir::LabelOp, cir::IndirectBrOp>(dst->front()))
2184 if (llvm::any_of(op.getDestOperands(), [&](
Value operand) {
2185 auto arg = dyn_cast<BlockArgument>(operand);
2186 return arg && arg.getOwner() == dst;
2192 rewriter.eraseOp(op);
2193 rewriter.mergeBlocks(dst, src, operands);
2197mlir::SuccessorOperands cir::BrOp::getSuccessorOperands(
unsigned index) {
2198 assert(index == 0 &&
"invalid successor index");
2199 return mlir::SuccessorOperands(getDestOperandsMutable());
2210mlir::SuccessorOperands
2211cir::IndirectBrOp::getSuccessorOperands(
unsigned index) {
2212 assert(index < getNumSuccessors() &&
"invalid successor index");
2213 return mlir::SuccessorOperands(getSuccOperandsMutable()[index]);
2217 OpAsmParser &parser, Type &flagType,
2218 SmallVectorImpl<Block *> &succOperandBlocks,
2221 if (failed(parser.parseCommaSeparatedList(
2222 OpAsmParser::Delimiter::Square,
2224 Block *destination = nullptr;
2225 SmallVector<OpAsmParser::UnresolvedOperand> operands;
2226 SmallVector<Type> operandTypes;
2228 if (parser.parseSuccessor(destination).failed())
2231 if (succeeded(parser.parseOptionalLParen())) {
2232 if (failed(parser.parseOperandList(
2233 operands, OpAsmParser::Delimiter::None)) ||
2234 failed(parser.parseColonTypeList(operandTypes)) ||
2235 failed(parser.parseRParen()))
2238 succOperandBlocks.push_back(destination);
2239 succOperands.emplace_back(operands);
2240 succOperandsTypes.emplace_back(operandTypes);
2243 "successor blocks")))
2249 Type flagType, SuccessorRange succs,
2250 OperandRangeRange succOperands,
2251 const TypeRangeRange &succOperandsTypes) {
2254 llvm::zip(succs, succOperands),
2257 p.printSuccessorAndUseList(std::get<0>(i), std::get<1>(i));
2260 if (!succOperands.empty())
2269mlir::SuccessorOperands cir::BrCondOp::getSuccessorOperands(
unsigned index) {
2270 assert(index < getNumSuccessors() &&
"invalid successor index");
2271 return SuccessorOperands(index == 0 ? getDestOperandsTrueMutable()
2272 : getDestOperandsFalseMutable());
2276 if (IntegerAttr condAttr = dyn_cast_if_present<IntegerAttr>(operands.front()))
2277 return condAttr.getValue().isOne() ? getDestTrue() : getDestFalse();
2285void cir::CaseOp::build(OpBuilder &builder, OperationState &result,
2286 ArrayAttr value, CaseOpKind
kind,
2287 OpBuilder::InsertPoint &insertPoint) {
2288 OpBuilder::InsertionGuard guardSwitch(builder);
2289 result.addAttribute(
"value", value);
2290 result.getOrAddProperties<Properties>().
kind =
2291 cir::CaseOpKindAttr::get(builder.getContext(),
kind);
2292 Region *caseRegion = result.addRegion();
2293 builder.createBlock(caseRegion);
2295 insertPoint = builder.saveInsertionPoint();
2302void cir::SwitchOp::build(OpBuilder &builder, OperationState &result,
2304 assert(switchBuilder &&
"the builder callback for regions must be present");
2305 OpBuilder::InsertionGuard guardSwitch(builder);
2306 Region *switchRegion = result.addRegion();
2307 builder.createBlock(switchRegion);
2308 result.addOperands({cond});
2309 switchBuilder(builder, result.location, result);
2313 walk<mlir::WalkOrder::PreOrder>([&](mlir::Operation *op) {
2315 if (isa<cir::SwitchOp>(op) && op != *
this)
2316 return WalkResult::skip();
2318 if (
auto caseOp = dyn_cast<cir::CaseOp>(op))
2319 cases.push_back(caseOp);
2321 return WalkResult::advance();
2326 collectCases(cases);
2328 if (getBody().empty())
2331 if (!isa<YieldOp>(getBody().front().back()))
2334 if (!llvm::all_of(getBody().front(),
2335 [](Operation &op) {
return isa<CaseOp, YieldOp>(op); }))
2338 return llvm::all_of(cases, [
this](CaseOp op) {
2339 return op->getParentOfType<SwitchOp>() == *
this;
2347void cir::SwitchFlatOp::build(OpBuilder &builder, OperationState &result,
2348 Value value, Block *defaultDestination,
2349 ValueRange defaultOperands,
2351 BlockRange caseDestinations,
2354 std::vector<mlir::Attribute> caseValuesAttrs;
2355 for (
const APInt &val : caseValues)
2356 caseValuesAttrs.push_back(cir::IntAttr::get(value.getType(), val));
2357 mlir::ArrayAttr attrs = ArrayAttr::get(builder.getContext(), caseValuesAttrs);
2359 build(builder, result, value, defaultOperands, caseOperands, attrs,
2360 defaultDestination, caseDestinations);
2363SuccessorOperands cir::SwitchFlatOp::getSuccessorOperands(
unsigned index) {
2364 assert(index < getNumSuccessors() &&
"invalid successor index");
2366 return SuccessorOperands(getDefaultOperandsMutable());
2367 return SuccessorOperands(getCaseOperandsMutable()[index - 1]);
2372 auto cond = dyn_cast_if_present<cir::IntAttr>(operands.front());
2375 for (
auto [value, dest] : llvm::zip(getCaseValues(), getCaseDestinations())) {
2376 const APInt &caseValue = cast<cir::IntAttr>(value).getValue();
2377 if (caseValue == cond.getValue())
2380 return getDefaultDestination();
2386 OpAsmParser &parser, Type flagType, mlir::ArrayAttr &caseValues,
2387 SmallVectorImpl<Block *> &caseDestinations,
2391 if (failed(parser.parseLSquare()))
2393 if (succeeded(parser.parseOptionalRSquare()))
2397 auto parseCase = [&]() {
2399 if (failed(parser.parseInteger(value)))
2402 values.push_back(cir::IntAttr::get(flagType, value));
2407 if (parser.parseColon() || parser.parseSuccessor(destination))
2409 if (!parser.parseOptionalLParen()) {
2410 if (parser.parseOperandList(operands, OpAsmParser::Delimiter::None,
2412 parser.parseColonTypeList(operandTypes) || parser.parseRParen())
2415 caseDestinations.push_back(destination);
2416 caseOperands.emplace_back(operands);
2417 caseOperandTypes.emplace_back(operandTypes);
2420 if (failed(parser.parseCommaSeparatedList(parseCase)))
2423 caseValues = ArrayAttr::get(flagType.getContext(), values);
2425 return parser.parseRSquare();
2429 Type flagType, mlir::ArrayAttr caseValues,
2430 SuccessorRange caseDestinations,
2431 OperandRangeRange caseOperands,
2432 const TypeRangeRange &caseOperandTypes) {
2442 llvm::zip(caseValues, caseDestinations),
2445 mlir::Attribute a = std::get<0>(i);
2446 p << mlir::cast<cir::IntAttr>(a).getValue();
2448 p.printSuccessorAndUseList(std::get<1>(i), caseOperands[index++]);
2463 mlir::Attribute &valueAttr) {
2465 return parser.parseAttribute(valueAttr,
"value", attr);
2469 p.printAttribute(value);
2472mlir::LogicalResult cir::GlobalOp::verify() {
2475 if (mlir::isa<cir::FuncType>(getSymType()))
2476 return emitOpError(
"global type cannot be a function type");
2480 if (getInitialValue().has_value()) {
2488 if (!getCtorRegion().empty() && !getInitialValue().has_value())
2490 "cannot have a constructor region without an initial value");
2492 std::optional<DynamicInitInfoAttr>
info = getDynamicInitInfo();
2494 if ((getDynamicInitGuard().has_value()) && (!info ||
info->getLocal()) &&
2495 (!getCtorRegion().empty() || !getDtorRegion().empty()))
2497 "Cannot have a static-local global-op with a constructor or "
2498 "destructor, they require in-function initialization via LocalInitOp");
2504 if (getDynamicInitGuard().has_value() != getDynamicInitInfo().has_value())
2505 return emitOpError(
"'dynamic_init_guard' and 'dynamic_init_info' must be "
2506 "present together");
2515 if (getDynamicInitGuard().has_value() && !getTlsRefs()->getGuardName())
2516 return emitOpError(
"cannot have a dynamic-init guard combined with "
2517 "ordered tls references");
2519 return emitOpError(
"'tls_refs' only valid for tls");
2522 if (getAliasee().has_value()) {
2523 if (getInitialValue().has_value() || !getCtorRegion().empty() ||
2524 !getDtorRegion().empty())
2525 return emitOpError(
"global alias shall not have an initializer or "
2526 "constructor/destructor regions");
2535void cir::GlobalOp::build(
2536 OpBuilder &odsBuilder, OperationState &odsState, llvm::StringRef sym_name,
2537 mlir::Type sym_type,
bool isConstant,
2538 mlir::ptr::MemorySpaceAttrInterface addrSpace,
2539 cir::GlobalLinkageKind linkage,
2540 function_ref<
void(OpBuilder &, Location)> ctorBuilder,
2541 function_ref<
void(OpBuilder &, Location)> dtorBuilder) {
2542 odsState.addAttribute(getSymNameAttrName(odsState.name),
2543 odsBuilder.getStringAttr(sym_name));
2544 odsState.addAttribute(getSymTypeAttrName(odsState.name),
2545 mlir::TypeAttr::get(sym_type));
2546 auto &properties = odsState.getOrAddProperties<cir::GlobalOp::Properties>();
2547 properties.setConstant(isConstant);
2551 odsState.addAttribute(getAddrSpaceAttrName(odsState.name), addrSpace);
2553 cir::GlobalLinkageKindAttr linkageAttr =
2554 cir::GlobalLinkageKindAttr::get(odsBuilder.getContext(), linkage);
2555 odsState.addAttribute(getLinkageAttrName(odsState.name), linkageAttr);
2557 Region *ctorRegion = odsState.addRegion();
2559 odsBuilder.createBlock(ctorRegion);
2560 ctorBuilder(odsBuilder, odsState.location);
2563 Region *dtorRegion = odsState.addRegion();
2565 odsBuilder.createBlock(dtorRegion);
2566 dtorBuilder(odsBuilder, odsState.location);
2575void cir::GlobalOp::getSuccessorRegions(
2576 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
2578 if (!point.isParent()) {
2579 regions.emplace_back(getOperation());
2584 Region *ctorRegion = &this->getCtorRegion();
2585 if (ctorRegion->empty())
2586 ctorRegion =
nullptr;
2589 Region *dtorRegion = &this->getDtorRegion();
2590 if (dtorRegion->empty())
2591 dtorRegion =
nullptr;
2595 regions.push_back(RegionSuccessor(ctorRegion));
2597 regions.push_back(RegionSuccessor(dtorRegion));
2604 if (!comdat.getValue().empty())
2605 p <<
"(\"" << comdat.getValue() <<
"\")";
2609 StringAttr comdat) {
2614 if (parser.parseOptionalKeyword(
"comdat").failed())
2616 std::string comdatKey;
2617 if (succeeded(parser.parseOptionalLParen())) {
2618 if (parser.parseString(&comdatKey).failed() ||
2619 parser.parseRParen().failed())
2622 comdatAttr = parser.getBuilder().getStringAttr(comdatKey);
2627 TypeAttr type, Attribute initAttr,
2628 mlir::Region &ctorRegion,
2629 mlir::Region &dtorRegion) {
2630 auto printType = [&]() { p <<
": " << type; };
2633 if (op.isDeclaration() || op.getAliasee()) {
2642 if (!ctorRegion.empty()) {
2644 p.printRegion(ctorRegion,
2649 if (!dtorRegion.empty()) {
2651 p.printRegion(dtorRegion,
2659 Attribute &initialValueAttr,
2660 mlir::Region &ctorRegion,
2661 mlir::Region &dtorRegion) {
2663 if (parser.parseOptionalEqual().failed()) {
2666 if (parser.parseColonType(opTy))
2675 assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
2676 "Non-typed attrs shouldn't appear here.");
2677 opTy = mlir::cast<mlir::TypedAttr>(initialValueAttr).getType();
2681 if (!parser.parseOptionalKeyword(
"ctor")) {
2682 auto parseLoc = parser.getCurrentLocation();
2683 if (parser.parseRegion(ctorRegion, {}, {}))
2691 if (!parser.parseOptionalKeyword(
"dtor")) {
2692 auto parseLoc = parser.getCurrentLocation();
2693 if (parser.parseRegion(dtorRegion, {}, {}))
2700 typeAttr = TypeAttr::get(opTy);
2709cir::GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2712 mlir::Operation *op =
2713 symbolTable.lookupNearestSymbolFrom(*
this, getNameAttr());
2714 if (op ==
nullptr || !(isa<GlobalOp>(op) || isa<FuncOp>(op)))
2715 return emitOpError(
"'")
2717 <<
"' does not reference a valid cir.global or cir.func";
2720 mlir::ptr::MemorySpaceAttrInterface symAddrSpaceAttr{};
2721 if (
auto g = dyn_cast<GlobalOp>(op)) {
2722 symTy = g.getSymType();
2723 symAddrSpaceAttr = g.getAddrSpaceAttr();
2726 if (getTls() && !g.getTlsModel())
2727 return emitOpError(
"access to global not marked thread local");
2732 bool getGlobalIsStaticLocal = getStaticLocal();
2733 bool globalIsStaticLocal =
2734 g.getDynamicInitGuard().has_value() &&
2735 (!g.getDynamicInitInfo() || g.getDynamicInitInfo()->getLocal());
2737 if (getGlobalIsStaticLocal != globalIsStaticLocal &&
2738 !getOperation()->getParentOfType<cir::GlobalOp>())
2739 return emitOpError(
"static_local attribute mismatch");
2740 }
else if (
auto f = dyn_cast<FuncOp>(op)) {
2741 symTy = f.getFunctionType();
2743 llvm_unreachable(
"Unexpected operation for GetGlobalOp");
2746 auto resultType = dyn_cast<PointerType>(getAddr().
getType());
2747 if (!resultType || symTy != resultType.getPointee())
2748 return emitOpError(
"result type pointee type '")
2749 << resultType.getPointee() <<
"' does not match type " << symTy
2750 <<
" of the global @" <<
getName();
2754 dyn_cast_if_present<TargetAddressSpaceAttr>(resultType.getAddrSpace());
2756 isa<FuncOp>(op) && targetAS &&
2757 targetAS.getValue() ==
2760 if (!isProgramAS && symAddrSpaceAttr != resultType.getAddrSpace()) {
2761 return emitOpError()
2762 <<
"result type address space does not match the address "
2763 "space of the global @"
2775cir::VTableAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2781 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
2783 return emitOpError(
"'")
2784 <<
name <<
"' does not reference a valid cir.global";
2785 std::optional<mlir::Attribute> init = op.getInitialValue();
2788 if (!isa<cir::VTableAttr>(*init))
2789 return emitOpError(
"Expected #cir.vtable in initializer for global '")
2799cir::VTTAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2808 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
2810 return emitOpError(
"'")
2811 <<
name <<
"' does not reference a valid cir.global";
2812 std::optional<mlir::Attribute> init = op.getInitialValue();
2815 if (!isa<cir::ConstArrayAttr>(*init))
2817 "Expected constant array in initializer for global VTT '")
2822LogicalResult cir::VTTAddrPointOp::verify() {
2824 if (
getName() && getSymAddr())
2825 return emitOpError(
"should use either a symbol or value, but not both");
2831 mlir::Type resultType = getAddr().getType();
2832 mlir::Type resTy = cir::PointerType::get(
2833 cir::PointerType::get(cir::VoidType::get(getContext())));
2835 if (resultType != resTy)
2836 return emitOpError(
"result type must be ")
2837 << resTy <<
", but provided result type is " << resultType;
2852 return name == CIRDialect::getMemoryEffectsAttrName() ||
2853 name == CIRDialect::getUwtableAttrName() ||
2854 name == CIRDialect::getFramePointerAttrName();
2857void cir::FuncOp::build(OpBuilder &builder, OperationState &result,
2858 StringRef name, FuncType type,
2859 GlobalLinkageKind linkage, CallingConv callingConv) {
2861 result.addAttribute(getSymNameAttrName(result.name),
2862 builder.getStringAttr(name));
2863 result.addAttribute(getFunctionTypeAttrName(result.name),
2864 TypeAttr::get(type));
2865 result.addAttribute(
2867 GlobalLinkageKindAttr::get(builder.getContext(), linkage));
2868 result.addAttribute(getCallingConvAttrName(result.name),
2869 CallingConvAttr::get(builder.getContext(), callingConv));
2872 result.addAttribute(getRequiresCallConvLoweringAttrName(result.name),
2873 builder.getUnitAttr());
2881cir::AnnotationAttr::verify(function_ref<InFlightDiagnostic()> emitError,
2882 mlir::StringAttr name, mlir::ArrayAttr args) {
2885 for (mlir::Attribute arg : args) {
2886 if (!isa<mlir::StringAttr, mlir::IntegerAttr>(arg))
2887 return emitError() <<
"annotation args must be StringAttr or IntegerAttr,"
2893ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
2894 llvm::SMLoc loc = parser.getCurrentLocation();
2895 mlir::Builder &builder = parser.getBuilder();
2897 mlir::StringAttr builtinNameAttr = getBuiltinAttrName(state.name);
2898 mlir::StringAttr coroutineKindNameAttr = getCoroutineKindAttrName(state.name);
2899 mlir::StringAttr inlineKindNameAttr = getInlineKindAttrName(state.name);
2900 mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
2901 mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
2902 mlir::StringAttr requiresCallConvLoweringNameAttr =
2903 getRequiresCallConvLoweringAttrName(state.name);
2904 mlir::StringAttr comdatNameAttr = getComdatAttrName(state.name);
2905 mlir::StringAttr alignmentNameAttr = getAlignmentAttrName(state.name);
2906 mlir::StringAttr preferredAlignmentNameAttr =
2907 getPreferredAlignmentAttrName(state.name);
2908 mlir::StringAttr visNameAttr = getSymVisibilityAttrName(state.name);
2909 mlir::StringAttr dsoLocalNameAttr = getDsoLocalAttrName(state.name);
2910 mlir::StringAttr funcInfoNameAttr = getFuncInfoAttrName(state.name);
2912 if (::mlir::succeeded(parser.parseOptionalKeyword(builtinNameAttr.strref())))
2913 state.addAttribute(builtinNameAttr, parser.getBuilder().getUnitAttr());
2917 static constexpr llvm::StringRef keywords[] = {
"coroutine",
2918 "flattened_coroutine"};
2919 llvm::StringRef keyword;
2920 if (parser.parseOptionalKeyword(&keyword, keywords).succeeded())
2922 coroutineKindNameAttr,
2923 cir::CoroutineKindAttr::get(builder.getContext(),
2924 *cir::symbolizeCoroutineKind(keyword)));
2928 cir::InlineKindAttr inlineKindAttr;
2932 state.addAttribute(inlineKindNameAttr, inlineKindAttr);
2934 if (::mlir::succeeded(parser.parseOptionalKeyword(lambdaNameAttr.strref())))
2935 state.addAttribute(lambdaNameAttr, parser.getBuilder().getUnitAttr());
2936 if (parser.parseOptionalKeyword(noProtoNameAttr).succeeded())
2937 state.addAttribute(noProtoNameAttr, parser.getBuilder().getUnitAttr());
2940 StringAttr comdatAttr;
2944 state.addAttribute(comdatNameAttr, comdatAttr);
2947 auto parseAlignmentBody = [&](
int64_t &value) {
2948 if (parser.parseLParen().failed() || parser.parseInteger(value).failed() ||
2949 parser.parseRParen().failed())
2953 return static_cast<LogicalResult
>(parser.emitError(
2954 loc,
"function alignment must be a positive integer"));
2959 if (parser.parseOptionalKeyword(alignmentNameAttr).succeeded()) {
2961 if (parseAlignmentBody(value).failed())
2963 state.addAttribute(alignmentNameAttr, builder.getI64IntegerAttr(value));
2966 if (parser.parseOptionalKeyword(preferredAlignmentNameAttr).succeeded()) {
2968 if (parseAlignmentBody(value).failed())
2970 state.addAttribute(preferredAlignmentNameAttr,
2971 builder.getI64IntegerAttr(value));
2976 GlobalLinkageKindAttr::get(
2977 parser.getContext(),
2979 parser, GlobalLinkageKind::ExternalLinkage)));
2981 ::llvm::StringRef visAttrStr;
2982 if (parser.parseOptionalKeyword(&visAttrStr, {
"private",
"public",
"nested"})
2984 state.addAttribute(visNameAttr,
2985 parser.getBuilder().getStringAttr(visAttrStr));
2988 state.getOrAddProperties<cir::FuncOp::Properties>().global_visibility =
2991 if (parser.parseOptionalKeyword(dsoLocalNameAttr).succeeded())
2992 state.addAttribute(dsoLocalNameAttr, parser.getBuilder().getUnitAttr());
2994 StringAttr nameAttr;
2995 if (parser.parseSymbolName(nameAttr, getSymNameAttrName(state.name),
3001 bool isVariadic =
false;
3002 if (function_interface_impl::parseFunctionSignatureWithArguments(
3003 parser,
true, arguments, isVariadic, resultTypes,
3008 bool argAttrsEmpty =
true;
3009 for (OpAsmParser::Argument &arg : arguments) {
3010 argTypes.push_back(
arg.type);
3014 argAttrs.push_back(
arg.attrs);
3016 argAttrsEmpty =
false;
3020 if (resultTypes.size() > 1 || resultAttrs.size() > 1)
3021 return parser.emitError(
3022 loc,
"functions with multiple return types are not supported");
3024 mlir::Type returnType =
3025 (resultTypes.empty() ? cir::VoidType::get(builder.getContext())
3026 : resultTypes.front());
3028 cir::FuncType fnType =
3029 cir::FuncType::getChecked([&]() {
return parser.emitError(loc); },
3030 argTypes, returnType, isVariadic);
3034 state.addAttribute(getFunctionTypeAttrName(state.name),
3035 TypeAttr::get(fnType));
3037 if (!resultAttrs.empty() && resultAttrs[0])
3039 getResAttrsAttrName(state.name),
3040 mlir::ArrayAttr::get(parser.getContext(), {resultAttrs[0]}));
3043 state.addAttribute(getArgAttrsAttrName(state.name),
3044 mlir::ArrayAttr::get(parser.getContext(), argAttrs));
3046 bool hasAlias =
false;
3047 mlir::StringAttr aliaseeNameAttr = getAliaseeAttrName(state.name);
3048 if (parser.parseOptionalKeyword(
"alias").succeeded()) {
3049 if (parser.parseLParen().failed())
3051 mlir::StringAttr aliaseeAttr;
3052 if (parser.parseOptionalSymbolName(aliaseeAttr).failed())
3054 state.addAttribute(aliaseeNameAttr, FlatSymbolRefAttr::get(aliaseeAttr));
3055 if (parser.parseRParen().failed())
3060 mlir::StringAttr personalityNameAttr = getPersonalityAttrName(state.name);
3061 if (parser.parseOptionalKeyword(
"personality").succeeded()) {
3062 if (parser.parseLParen().failed())
3064 mlir::StringAttr personalityAttr;
3065 if (parser.parseOptionalSymbolName(personalityAttr).failed())
3067 state.addAttribute(personalityNameAttr,
3068 FlatSymbolRefAttr::get(personalityAttr));
3069 if (parser.parseRParen().failed())
3074 mlir::StringAttr callConvNameAttr = getCallingConvAttrName(state.name);
3075 cir::CallingConv callConv = cir::CallingConv::C;
3076 if (parser.parseOptionalKeyword(
"cc").succeeded()) {
3077 if (parser.parseLParen().failed())
3080 return parser.emitError(loc) <<
"unknown calling convention";
3081 if (parser.parseRParen().failed())
3084 state.addAttribute(callConvNameAttr,
3085 cir::CallingConvAttr::get(parser.getContext(), callConv));
3087 auto parseGlobalDtorCtor =
3088 [&](StringRef keyword,
3089 llvm::function_ref<void(std::optional<int> prio)> createAttr)
3090 -> mlir::LogicalResult {
3091 if (mlir::succeeded(parser.parseOptionalKeyword(keyword))) {
3092 std::optional<int> priority;
3093 if (mlir::succeeded(parser.parseOptionalLParen())) {
3094 auto parsedPriority = mlir::FieldParser<int>::parse(parser);
3095 if (mlir::failed(parsedPriority))
3096 return parser.emitError(parser.getCurrentLocation(),
3097 "failed to parse 'priority', of type 'int'");
3098 priority = parsedPriority.value_or(
int());
3100 if (parser.parseRParen())
3103 createAttr(priority);
3109 if (parser.parseOptionalKeyword(
"func_info").succeeded()) {
3110 if (parser.parseLess().failed())
3113 llvm::SMLoc attrLoc = parser.getCurrentLocation();
3114 mlir::Attribute
attr;
3115 if (parser.parseAttribute(attr).failed())
3117 if (!mlir::isa<cir::CXXCtorAttr, cir::CXXDtorAttr, cir::CXXAssignAttr,
3118 cir::FuncIdentityAttr>(attr))
3119 return parser.emitError(attrLoc,
3120 "expected a function info attribute, got ")
3122 state.addAttribute(funcInfoNameAttr, attr);
3124 if (parser.parseGreater().failed())
3128 if (parseGlobalDtorCtor(
"global_ctor", [&](std::optional<int> priority) {
3129 mlir::IntegerAttr globalCtorPriorityAttr =
3130 builder.getI32IntegerAttr(priority.value_or(65535));
3131 state.addAttribute(getGlobalCtorPriorityAttrName(state.name),
3132 globalCtorPriorityAttr);
3136 if (parseGlobalDtorCtor(
"global_dtor", [&](std::optional<int> priority) {
3137 mlir::IntegerAttr globalDtorPriorityAttr =
3138 builder.getI32IntegerAttr(priority.value_or(65535));
3139 state.addAttribute(getGlobalDtorPriorityAttrName(state.name),
3140 globalDtorPriorityAttr);
3145 mlir::StringAttr annotationsNameAttr = getAnnotationsAttrName(state.name);
3146 mlir::ArrayAttr annotationsAttr;
3147 if (parser.parseOptionalAttribute(annotationsAttr).has_value() &&
3149 state.addAttribute(annotationsNameAttr, annotationsAttr);
3151 if (parser.parseOptionalKeyword(requiresCallConvLoweringNameAttr).succeeded())
3152 state.addAttribute(requiresCallConvLoweringNameAttr,
3153 parser.getBuilder().getUnitAttr());
3156 NamedAttrList parsedAttrs;
3157 llvm::SMLoc attrsLoc = parser.getCurrentLocation();
3158 if (parser.parseOptionalAttrDictWithKeyword(parsedAttrs))
3162 for (StringRef disallowed : cir::FuncOp::getAttributeNames()) {
3165 if (parsedAttrs.get(disallowed))
3166 return parser.emitError(loc,
"attribute '")
3168 <<
"' should not be specified in the explicit attribute list";
3174 state.attributes.append(parsedAttrs);
3177 auto *body = state.addRegion();
3178 OptionalParseResult parseResult = parser.parseOptionalRegion(
3179 *body, arguments,
false);
3180 if (parseResult.has_value()) {
3182 return parser.emitError(loc,
"function alias shall not have a body");
3183 if (failed(*parseResult))
3187 return parser.emitError(loc,
"expected non-empty function body");
3196bool cir::FuncOp::isDeclaration() {
3199 std::optional<StringRef> aliasee = getAliasee();
3201 return getFunctionBody().empty();
3207bool cir::FuncOp::isCXXSpecialMemberFunction() {
3210 mlir::Attribute
attr = getFuncInfoAttr();
3211 return attr && mlir::isa<CXXCtorAttr, CXXDtorAttr, CXXAssignAttr>(attr);
3214bool cir::FuncOp::isCxxConstructor() {
3215 auto attr = getFuncInfoAttr();
3216 return attr && dyn_cast<CXXCtorAttr>(attr);
3219bool cir::FuncOp::isCxxDestructor() {
3220 auto attr = getFuncInfoAttr();
3221 return attr && dyn_cast<CXXDtorAttr>(attr);
3224bool cir::FuncOp::isCxxSpecialAssignment() {
3225 auto attr = getFuncInfoAttr();
3226 return attr && dyn_cast<CXXAssignAttr>(attr);
3229std::optional<CtorKind> cir::FuncOp::getCxxConstructorKind() {
3230 mlir::Attribute
attr = getFuncInfoAttr();
3232 if (
auto ctor = dyn_cast<CXXCtorAttr>(attr))
3233 return ctor.getCtorKind();
3235 return std::nullopt;
3238std::optional<AssignKind> cir::FuncOp::getCxxSpecialAssignKind() {
3239 mlir::Attribute
attr = getFuncInfoAttr();
3241 if (
auto assign = dyn_cast<CXXAssignAttr>(attr))
3242 return assign.getAssignKind();
3244 return std::nullopt;
3247bool cir::FuncOp::isCxxTrivialMemberFunction() {
3248 mlir::Attribute
attr = getFuncInfoAttr();
3250 if (
auto ctor = dyn_cast<CXXCtorAttr>(attr))
3251 return ctor.getIsTrivial();
3252 if (
auto dtor = dyn_cast<CXXDtorAttr>(attr))
3253 return dtor.getIsTrivial();
3254 if (
auto assign = dyn_cast<CXXAssignAttr>(attr))
3255 return assign.getIsTrivial();
3260mlir::Region *cir::FuncOp::getCallableRegion() {
3264 if (getBody().empty())
3269void cir::FuncOp::print(OpAsmPrinter &p) {
3273 if (std::optional<cir::CoroutineKind> coroKind = getCoroutineKind())
3274 p <<
' ' << cir::stringifyCoroutineKind(*coroKind);
3284 if (getComdatAttr()) {
3290 p <<
" alignment(" << *getAlignment() <<
')';
3292 if (getPreferredAlignment())
3293 p <<
" preferred_alignment(" << *getPreferredAlignment() <<
')';
3295 if (getLinkage() != GlobalLinkageKind::ExternalLinkage)
3296 p <<
' ' << stringifyGlobalLinkageKind(getLinkage());
3298 mlir::SymbolTable::Visibility vis = getVisibility();
3299 if (vis != mlir::SymbolTable::Visibility::Public)
3302 if (getGlobalVisibility() != cir::VisibilityKind::Default)
3303 p <<
' ' << stringifyVisibilityKind(getGlobalVisibility());
3309 p.printSymbolName(getSymName());
3310 cir::FuncType fnType = getFunctionType();
3311 function_interface_impl::printFunctionSignature(
3312 p, *
this, fnType.getInputs(), fnType.isVarArg(), fnType.getReturnTypes());
3314 if (std::optional<StringRef> aliaseeName = getAliasee()) {
3316 p.printSymbolName(*aliaseeName);
3320 if (getCallingConv() != cir::CallingConv::C) {
3322 p << stringifyCallingConv(getCallingConv());
3326 if (std::optional<StringRef> personalityName = getPersonality()) {
3327 p <<
" personality(";
3328 p.printSymbolName(*personalityName);
3332 if (mlir::Attribute funcInfo = getFuncInfoAttr()) {
3334 p.printAttribute(funcInfo);
3338 if (
auto globalCtorPriority = getGlobalCtorPriority()) {
3339 p <<
" global_ctor";
3340 if (globalCtorPriority.value() != 65535)
3341 p <<
"(" << globalCtorPriority.value() <<
")";
3344 if (
auto globalDtorPriority = getGlobalDtorPriority()) {
3345 p <<
" global_dtor";
3346 if (globalDtorPriority.value() != 65535)
3347 p <<
"(" << globalDtorPriority.value() <<
")";
3350 if (mlir::ArrayAttr annotations = getAnnotationsAttr()) {
3352 p.printAttribute(annotations);
3355 if (getRequiresCallConvLowering())
3356 p <<
' ' << getRequiresCallConvLoweringAttrName().getValue();
3360 for (llvm::StringRef name : cir::FuncOp::getAttributeNames())
3362 elidedAttrs.push_back(name);
3363 function_interface_impl::printFunctionAttributes(p, *
this, elidedAttrs);
3366 Region &body = getOperation()->getRegion(0);
3367 if (!body.empty()) {
3369 p.printRegion(body,
false,
3374mlir::LogicalResult cir::FuncOp::verify() {
3376 if (!isDeclaration() && getCoroutineKind() == cir::CoroutineKind::Coroutine) {
3377 int coroutineOpCount = 0;
3378 this->walk([&](Operation *op) {
3379 if (isa<CoroutineOp>(op)) {
3381 if (coroutineOpCount > 1) {
3382 return mlir::WalkResult::interrupt();
3385 return mlir::WalkResult::advance();
3387 if (coroutineOpCount != 1)
3388 return emitOpError()
3389 <<
"coroutine function must have exactly one cir.coroutine op";
3392 llvm::SmallSet<llvm::StringRef, 16> labels;
3393 llvm::SmallSet<llvm::StringRef, 16> gotos;
3394 llvm::SmallSet<llvm::StringRef, 16> blockAddresses;
3395 bool invalidBlockAddress =
false;
3396 getOperation()->walk([&](mlir::Operation *op) {
3397 if (
auto lab = dyn_cast<cir::LabelOp>(op)) {
3398 labels.insert(lab.getLabel());
3399 }
else if (
auto goTo = dyn_cast<cir::GotoOp>(op)) {
3400 gotos.insert(goTo.getLabel());
3401 }
else if (
auto blkAdd = dyn_cast<cir::BlockAddressOp>(op)) {
3402 if (blkAdd.getBlockAddrInfoAttr().getFunc().getAttr() != getSymName()) {
3404 invalidBlockAddress =
true;
3405 return mlir::WalkResult::interrupt();
3407 blockAddresses.insert(blkAdd.getBlockAddrInfoAttr().getLabel());
3409 return mlir::WalkResult::advance();
3412 if (invalidBlockAddress)
3413 return emitOpError() <<
"blockaddress references a different function";
3415 llvm::SmallSet<llvm::StringRef, 16> mismatched;
3416 if (!labels.empty() || !gotos.empty()) {
3417 mismatched = llvm::set_difference(gotos, labels);
3419 if (!mismatched.empty())
3420 return emitOpError() <<
"goto/label mismatch";
3425 if (!labels.empty() || !blockAddresses.empty()) {
3426 mismatched = llvm::set_difference(blockAddresses, labels);
3428 if (!mismatched.empty())
3429 return emitOpError()
3430 <<
"expects an existing label target in the referenced function";
3444LogicalResult cir::AddOp::verify() {
3445 if (getSaturated() && (getNoSignedWrap() || getNoUnsignedWrap()))
3446 return emitOpError()
3447 <<
"the nsw/nuw flags and the saturated flag are mutually exclusive";
3448 return mlir::success();
3451LogicalResult cir::SubOp::verify() {
3452 if (getSaturated() && (getNoSignedWrap() || getNoUnsignedWrap()))
3453 return emitOpError()
3454 <<
"the nsw/nuw flags and the saturated flag are mutually exclusive";
3455 return mlir::success();
3462void cir::TernaryOp::build(
3463 OpBuilder &builder, OperationState &result,
Value cond,
3464 function_ref<
void(OpBuilder &, Location)> trueBuilder,
3465 function_ref<
void(OpBuilder &, Location)> falseBuilder) {
3466 result.addOperands(cond);
3467 OpBuilder::InsertionGuard guard(builder);
3468 Region *trueRegion = result.addRegion();
3469 builder.createBlock(trueRegion);
3470 trueBuilder(builder, result.location);
3471 Region *falseRegion = result.addRegion();
3472 builder.createBlock(falseRegion);
3473 falseBuilder(builder, result.location);
3478 if (trueRegion->back().mightHaveTerminator())
3479 yield = dyn_cast_or_null<cir::YieldOp>(trueRegion->back().getTerminator());
3480 if (!yield && falseRegion->back().mightHaveTerminator())
3481 yield = dyn_cast_or_null<cir::YieldOp>(falseRegion->back().getTerminator());
3483 assert((!yield || yield.getNumOperands() <= 1) &&
3484 "expected zero or one result type");
3485 if (yield && yield.getNumOperands() == 1)
3486 result.addTypes(TypeRange{yield.getOperandTypes().front()});
3493OpFoldResult cir::SelectOp::fold(FoldAdaptor adaptor) {
3495 mlir::dyn_cast_if_present<cir::BoolAttr>(adaptor.getCondition()))
3496 return condition.getValue() ? getTrueValue() : getFalseValue();
3499 mlir::Attribute trueValue = adaptor.getTrueValue();
3500 mlir::Attribute falseValue = adaptor.getFalseValue();
3501 if (trueValue == falseValue)
3503 if (getTrueValue() == getFalseValue())
3504 return getTrueValue();
3509LogicalResult cir::SelectOp::verify() {
3511 auto condTy = dyn_cast<cir::VectorType>(getCondition().
getType());
3518 if (!isa<cir::VectorType>(getTrueValue().
getType()) ||
3519 !isa<cir::VectorType>(getFalseValue().
getType())) {
3520 return emitOpError()
3521 <<
"expected both true and false operands to be vector types "
3522 "when the condition is a vector boolean type";
3531LogicalResult cir::ShiftOp::verify() {
3532 mlir::Operation *op = getOperation();
3533 auto op0VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(0).getType());
3534 auto op1VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(1).getType());
3535 if (!op0VecTy ^ !op1VecTy)
3536 return emitOpError() <<
"input types cannot be one vector and one scalar";
3539 if (op0VecTy.getSize() != op1VecTy.getSize())
3540 return emitOpError() <<
"input vector types must have the same size";
3542 auto opResultTy = mlir::dyn_cast<cir::VectorType>(
getType());
3544 return emitOpError() <<
"the type of the result must be a vector "
3545 <<
"if it is vector shift";
3547 auto op0VecEleTy = mlir::cast<cir::IntType>(op0VecTy.getElementType());
3548 auto op1VecEleTy = mlir::cast<cir::IntType>(op1VecTy.getElementType());
3549 if (op0VecEleTy.getWidth() != op1VecEleTy.getWidth())
3550 return emitOpError()
3551 <<
"vector operands do not have the same elements sizes";
3553 auto resVecEleTy = mlir::cast<cir::IntType>(opResultTy.getElementType());
3554 if (op0VecEleTy.getWidth() != resVecEleTy.getWidth())
3555 return emitOpError() <<
"vector operands and result type do not have the "
3556 "same elements sizes";
3559 return mlir::success();
3566LogicalResult cir::LabelOp::verify() {
3567 mlir::Operation *op = getOperation();
3568 mlir::Block *blk = op->getBlock();
3569 if (&blk->front() != op)
3570 return emitError() <<
"must be the first operation in a block";
3572 return mlir::success();
3579OpFoldResult cir::IncOp::fold(FoldAdaptor adaptor) {
3580 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3581 return adaptor.getInput();
3589OpFoldResult cir::DecOp::fold(FoldAdaptor adaptor) {
3590 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3591 return adaptor.getInput();
3599OpFoldResult cir::MinusOp::fold(FoldAdaptor adaptor) {
3600 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3601 return adaptor.getInput();
3606 mlir::dyn_cast_if_present<cir::IntAttr>(adaptor.getInput())) {
3607 APInt val = intAttr.getValue();
3609 return cir::IntAttr::get(
getType(), val);
3619OpFoldResult cir::FNegOp::fold(FoldAdaptor adaptor) {
3620 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3621 return adaptor.getInput();
3625 mlir::dyn_cast_if_present<cir::FPAttr>(adaptor.getInput())) {
3626 APFloat val = fpAttr.getValue();
3628 return cir::FPAttr::get(
getType(), val);
3638OpFoldResult cir::NotOp::fold(FoldAdaptor adaptor) {
3639 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3640 return adaptor.getInput();
3645 if (mlir::Attribute attr = adaptor.getInput()) {
3646 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr)) {
3647 APInt val = intAttr.getValue();
3649 return cir::IntAttr::get(
getType(), val);
3651 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr))
3652 return cir::BoolAttr::get(getContext(), !boolAttr.getValue());
3662LogicalResult cir::BaseClassAddrOp::verify() {
3663 if (getSrcAddr().
getType().getAddrSpace() !=
getType().getAddrSpace())
3664 return emitOpError() <<
"address space mismatch";
3665 return mlir::success();
3668LogicalResult cir::DerivedClassAddrOp::verify() {
3669 if (getSrcAddr().
getType().getAddrSpace() !=
getType().getAddrSpace())
3670 return emitOpError() <<
"address space mismatch";
3671 return mlir::success();
3679 mlir::Type resultTy) {
3682 mlir::Type inputMemberTy;
3683 mlir::Type resultMemberTy;
3684 if (mlir::isa<cir::DataMemberType>(src.getType())) {
3686 mlir::cast<cir::DataMemberType>(src.getType()).getMemberTy();
3687 resultMemberTy = mlir::cast<cir::DataMemberType>(resultTy).getMemberTy();
3690 if (inputMemberTy != resultMemberTy)
3691 return op->emitOpError()
3692 <<
"member types of the operand and the result do not match";
3694 return mlir::success();
3697LogicalResult cir::BaseDataMemberOp::verify() {
3701LogicalResult cir::DerivedDataMemberOp::verify() {
3709LogicalResult cir::BaseMethodOp::verify() {
3713LogicalResult cir::DerivedMethodOp::verify() {
3721void cir::AwaitOp::build(OpBuilder &builder, OperationState &result,
3725 result.addAttribute(getKindAttrName(result.name),
3726 cir::AwaitKindAttr::get(builder.getContext(),
kind));
3728 OpBuilder::InsertionGuard guard(builder);
3729 Region *readyRegion = result.addRegion();
3730 builder.createBlock(readyRegion);
3731 readyBuilder(builder, result.location);
3735 OpBuilder::InsertionGuard guard(builder);
3736 Region *suspendRegion = result.addRegion();
3737 builder.createBlock(suspendRegion);
3738 suspendBuilder(builder, result.location);
3742 OpBuilder::InsertionGuard guard(builder);
3743 Region *resumeRegion = result.addRegion();
3744 builder.createBlock(resumeRegion);
3745 resumeBuilder(builder, result.location);
3749void cir::AwaitOp::getSuccessorRegions(
3750 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
3751 assert(point.isParent() || point.getTerminatorPredecessorOrNull());
3754 if (point.isParent()) {
3755 regions.emplace_back(&getReady());
3759 mlir::Region *parentRegion =
3760 point.getTerminatorPredecessorOrNull()->getParentRegion();
3769 if (&getReady() == parentRegion) {
3770 regions.emplace_back(&getResume());
3771 regions.emplace_back(&getSuspend());
3778 if (&getSuspend() == parentRegion) {
3779 regions.emplace_back(&getResume());
3780 regions.emplace_back(getOperation());
3785 regions.emplace_back(getOperation());
3788LogicalResult cir::AwaitOp::verify() {
3789 if (!isa<ConditionOp>(this->getReady().back().getTerminator()))
3790 return emitOpError(
"ready region must end with cir.condition");
3791 if (this->getSuspend().empty())
3792 return emitOpError(
"suspend region must not be empty");
3793 if (!isa<CoroSuspendPoint>(this->getSuspend().back().getTerminator()))
3794 return emitOpError(
"suspend region must end with cir.coro.suspend_point");
3802LogicalResult cir::CoReturnOp::verify() {
3803 mlir::Operation *coRet = getOperation();
3804 auto coroutine = coRet->getParentOfType<CoroutineOp>();
3805 if (!coroutine.getBody().isAncestor(getOperation()->getParentRegion()))
3806 return emitOpError(
"must be inside the cir.coroutine body region");
3814void cir::CoroutineOp::build(OpBuilder &builder, OperationState &result,
3821 OpBuilder::InsertionGuard guard(builder);
3822 Region *initialRegion = result.addRegion();
3823 builder.createBlock(initialRegion);
3824 initialSuspendBuilder(builder, result.location);
3828 OpBuilder::InsertionGuard guard(builder);
3829 Region *bodyRegion = result.addRegion();
3830 builder.createBlock(bodyRegion);
3831 bodyBuilder(builder, result.location);
3835 OpBuilder::InsertionGuard guard(builder);
3836 Region *finalRegion = result.addRegion();
3837 builder.createBlock(finalRegion);
3838 finalSuspendBuilder(builder, result.location);
3842 OpBuilder::InsertionGuard guard(builder);
3843 Region *destroyRegion = result.addRegion();
3844 builder.createBlock(destroyRegion);
3845 destroyBuilder(builder, result.location);
3849 OpBuilder::InsertionGuard guard(builder);
3850 Region *exitRegion = result.addRegion();
3851 builder.createBlock(exitRegion);
3852 exitBuilder(builder, result.location);
3856void cir::CoroutineOp::getSuccessorRegions(
3857 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
3860 if (point.isParent()) {
3861 regions.emplace_back(&getInitialSuspend());
3865 mlir::Region *parent =
3866 point.getTerminatorPredecessorOrNull()->getParentRegion();
3872 if (parent == &getInitialSuspend()) {
3873 regions.emplace_back(&getBody());
3874 regions.emplace_back(&getExit());
3875 regions.emplace_back(&getDestroy());
3883 if (parent == &getBody()) {
3884 regions.emplace_back(&getFinalSuspend());
3885 regions.emplace_back(&getExit());
3886 regions.emplace_back(&getDestroy());
3894 if (parent == &getFinalSuspend()) {
3895 regions.emplace_back(
3897 regions.emplace_back(&getExit());
3905 if (parent == &getDestroy()) {
3906 regions.emplace_back(&getExit());
3907 regions.push_back(RegionSuccessor(getOperation()));
3911 if (parent == &getExit()) {
3912 regions.emplace_back(getOperation());
3918cir::CoroutineOp::getSuccessorInputs(RegionSuccessor successor) {
3919 return ValueRange();
3922LogicalResult cir::CoroutineOp::verify() {
3923 mlir::Region &initialSuspend = getInitialSuspend();
3924 mlir::Region &body = getBody();
3925 mlir::Region &finalSuspend = getFinalSuspend();
3926 mlir::Region &destroy = getDestroy();
3927 mlir::Region &exit = getExit();
3932 int initAwaitCount = 0;
3933 bool hasInvalidAwait =
false;
3935 initialSuspend.walk([&](Operation *op) {
3936 auto awaitOp = mlir::dyn_cast<AwaitOp>(op);
3938 return mlir::WalkResult::advance();
3940 if (awaitOp.getKind() == cir::AwaitKind::Init)
3943 hasInvalidAwait =
true;
3945 if (initAwaitCount > 1 || hasInvalidAwait)
3946 return mlir::WalkResult::interrupt();
3948 return mlir::WalkResult::advance();
3951 if (hasInvalidAwait)
3952 return emitOpError(
"'initial_suspend' must not contain any cir.await other "
3953 "than the 'init' one");
3954 if (initAwaitCount != 1)
3956 "must have exactly one 'init' cir.await in 'initial_suspend'");
3959 int finalAwaitCount = 0;
3960 hasInvalidAwait =
false;
3962 finalSuspend.walk([&](Operation *op) {
3963 auto awaitOp = mlir::dyn_cast<AwaitOp>(op);
3965 return mlir::WalkResult::advance();
3967 if (awaitOp.getKind() == cir::AwaitKind::Final)
3970 hasInvalidAwait =
true;
3972 if (finalAwaitCount > 1 || hasInvalidAwait)
3973 return mlir::WalkResult::interrupt();
3975 return mlir::WalkResult::advance();
3978 if (hasInvalidAwait)
3979 return emitOpError(
"'final_suspend' must not contain any cir.await other "
3980 "than the 'final' one");
3981 if (finalAwaitCount > 1)
3983 "must have one or zero 'final' cir.await in 'final_suspend'");
3990 if (initialSuspend.empty() || initialSuspend.back().empty())
3991 return emitOpError(
"initial_suspend region must not be empty");
3992 if (!isa<YieldOp>(initialSuspend.back().back()))
3993 return emitOpError(
"'initial_suspend' must end with cir.yield");
3995 if (body.empty() || body.back().empty())
3996 return emitOpError(
"'body' region must not be empty");
3997 if (!isa<YieldOp, CoReturnOp>(body.back().back()))
3998 return emitOpError(
"'body' must end with cir.yield or cir.co_return");
4000 if (finalSuspend.empty() || finalSuspend.back().empty())
4001 return emitOpError(
"'final_suspend' region must not be empty");
4002 if (!isa<YieldOp>(finalSuspend.back().back()))
4003 return emitOpError(
"'final_suspend' must end with cir.yield");
4005 if (destroy.empty() || destroy.back().empty())
4006 return emitOpError(
"'destroy' region must not be empty");
4007 if (!isa<YieldOp>(destroy.back().back()))
4008 return emitOpError(
"'destroy' must end with cir.yield");
4010 if (exit.empty() || exit.back().empty())
4011 return emitOpError(
"'exit' region must not be empty");
4012 if (!isa<ReturnOp>(exit.back().back()))
4013 return emitOpError(
"'exit' must end with cir.return");
4015 return mlir::success();
4026 mlir::Type srcType, mlir::Type dstType) {
4027 printer.printType(srcType);
4028 if (srcType != dstType) {
4030 printer.printType(dstType);
4035 mlir::Type &srcType,
4036 mlir::Type &dstType) {
4037 if (parser.parseType(srcType))
4038 return mlir::failure();
4039 if (parser.parseOptionalComma().succeeded()) {
4040 if (parser.parseType(dstType))
4041 return mlir::failure();
4045 return mlir::success();
4048LogicalResult cir::CopyOp::verify() {
4053 if (!
getType().getPointee().hasTrait<DataLayoutTypeInterface::Trait>())
4054 return emitError() <<
"missing data layout for pointee type";
4056 if (getSkipTailPadding() &&
4057 !mlir::isa<cir::RecordType>(
getType().getPointee()))
4059 <<
"skip_tail_padding is only valid for record pointee types";
4061 return mlir::success();
4068LogicalResult cir::PtrMaskOp::verify() {
4069 mlir::DataLayout layout = mlir::DataLayout::closest(*
this);
4070 std::optional<uint64_t> indexWidth =
4071 layout.getTypeIndexBitwidth(getPtr().
getType());
4073 return emitOpError() <<
"pointer has no index width";
4075 uint64_t maskWidth = getMask().getType().getWidth();
4076 if (maskWidth != *indexWidth)
4077 return emitOpError() <<
"mask width " << maskWidth
4078 <<
" must equal the pointer index width "
4081 return mlir::success();
4088LogicalResult cir::GetRuntimeMemberOp::verify() {
4089 cir::DataMemberType memberPtrTy = getMember().getType();
4091 if (getAddr().
getType().getPointee() != memberPtrTy.getClassTy())
4092 return emitError() <<
"record type does not match the member pointer type";
4093 if (
getType().getPointee() != memberPtrTy.getMemberTy())
4094 return emitError() <<
"result type does not match the member pointer type";
4095 return mlir::success();
4102LogicalResult cir::GetMethodOp::verify() {
4103 cir::MethodType methodTy = getMethod().getType();
4106 cir::PointerType objectPtrTy = getObject().getType();
4107 mlir::Type objectTy = objectPtrTy.getPointee();
4109 if (methodTy.getClassTy() != objectTy)
4110 return emitError() <<
"method class type and object type do not match";
4113 auto calleeTy = mlir::cast<cir::FuncType>(getCallee().
getType().getPointee());
4114 cir::FuncType methodFuncTy = methodTy.getMemberFuncTy();
4121 if (methodFuncTy.getReturnType() != calleeTy.getReturnType())
4123 <<
"method return type and callee return type do not match";
4128 if (calleeArgsTy.empty())
4129 return emitError() <<
"callee parameter list lacks receiver object ptr";
4131 auto calleeThisArgPtrTy = mlir::dyn_cast<cir::PointerType>(calleeArgsTy[0]);
4132 if (!calleeThisArgPtrTy ||
4133 !mlir::isa<cir::VoidType>(calleeThisArgPtrTy.getPointee())) {
4135 <<
"the first parameter of callee must be a void pointer";
4138 if (calleeArgsTy.size() != methodFuncArgsTy.size())
4139 return emitError() <<
"callee and method parameter counts do not match";
4141 if (calleeArgsTy.size() > 1 &&
4142 calleeArgsTy.slice(1) != methodFuncArgsTy.slice(1))
4144 <<
"callee parameters and method parameters do not match";
4146 return mlir::success();
4157LogicalResult cir::GetMemberOp::verify() {
4158 const auto recordTy = dyn_cast<RecordType>(getAddrTy().getPointee());
4160 return emitError() <<
"expected pointer to a record type";
4162 if (recordTy.getMembers().size() <=
getIndex())
4163 return emitError() <<
"member index out of bounds";
4167 return emitError() <<
"member owns no storage to point at";
4169 if (pointeeTy !=
getType().getPointee())
4170 return emitError() <<
"member type mismatch";
4172 if (getAddrTy().getAddrSpace() !=
getType().getAddrSpace())
4173 return emitError() <<
"address space mismatch";
4175 return mlir::success();
4182LogicalResult cir::ExtractMemberOp::verify() {
4183 if (mlir::isa<cir::UnionType>(getRecord().
getType()))
4185 <<
"cir.extract_member currently does not support unions";
4186 auto structTy = mlir::cast<cir::StructType>(getRecord().
getType());
4187 if (structTy.getMembers().size() <=
getIndex())
4188 return emitError() <<
"member index out of bounds";
4189 mlir::Type memberTy = structTy.getMembers()[
getIndex()];
4190 if (mlir::isa<cir::BitFieldType>(memberTy))
4191 return emitError() <<
"cir.extract_member does not support bit-fields";
4193 return emitError() <<
"member type mismatch";
4194 return mlir::success();
4201LogicalResult cir::InsertMemberOp::verify() {
4202 if (mlir::isa<cir::UnionType>(getRecord().
getType()))
4203 return emitError() <<
"cir.insert_member currently does not support unions";
4204 auto structTy = mlir::cast<cir::StructType>(getRecord().
getType());
4205 if (structTy.getMembers().size() <=
getIndex())
4206 return emitError() <<
"member index out of bounds";
4207 mlir::Type memberTy = structTy.getMembers()[
getIndex()];
4208 if (mlir::isa<cir::BitFieldType>(memberTy))
4209 return emitError() <<
"cir.insert_member does not support bit-fields";
4210 if (memberTy != getValue().
getType())
4211 return emitError() <<
"member type mismatch";
4213 return mlir::success();
4220OpFoldResult cir::VecCreateOp::fold(FoldAdaptor adaptor) {
4221 if (llvm::any_of(getElements(), [](mlir::Value value) {
4222 return !value.getDefiningOp<cir::ConstantOp>();
4226 return cir::ConstVectorAttr::get(
4227 getType(), mlir::ArrayAttr::get(getContext(), adaptor.getElements()));
4230LogicalResult cir::VecCreateOp::verify() {
4234 const cir::VectorType vecTy =
getType();
4235 if (vecTy.isScalable())
4236 return emitOpError() <<
"scalable vectors are not supported";
4238 if (getElements().size() != vecTy.getFixedSize()) {
4239 return emitOpError() <<
"operand count of " << getElements().size()
4240 <<
" doesn't match vector type " << vecTy
4241 <<
" element count of " << vecTy.getFixedSize();
4244 const mlir::Type elementType = vecTy.getElementType();
4245 for (
const mlir::Value element : getElements()) {
4246 if (element.getType() != elementType) {
4247 return emitOpError() <<
"operand type " << element.getType()
4248 <<
" doesn't match vector element type "
4260OpFoldResult cir::VecExtractOp::fold(FoldAdaptor adaptor) {
4261 const auto vectorAttr =
4262 llvm::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec());
4266 const auto indexAttr =
4267 llvm::dyn_cast_if_present<cir::IntAttr>(adaptor.getIndex());
4271 const mlir::ArrayAttr elements = vectorAttr.getElts();
4272 const uint64_t index = indexAttr.getUInt();
4273 if (index >= elements.size())
4276 return elements[index];
4283LogicalResult cir::CmpOp::verify() {
4284 if (getFenvAttr() && !cir::isAnyFloatingPointType(getLhs().
getType()))
4285 return emitOpError()
4286 <<
"'fenv' is only valid for floating-point comparisons";
4294LogicalResult cir::VecCmpOp::verify() {
4295 if (getFenvAttr() && !cir::isFPOrVectorOfFPType(getLhs().
getType()))
4296 return emitOpError()
4297 <<
"'fenv' is only valid for floating-point comparisons";
4301OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
4311 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getLhs());
4313 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getRhs());
4314 if (!lhsVecAttr || !rhsVecAttr)
4317 mlir::Type inputElemTy =
4318 mlir::cast<cir::VectorType>(lhsVecAttr.getType()).getElementType();
4319 if (!isAnyIntegerOrFloatingPointType(inputElemTy))
4322 cir::CmpOpKind opKind = adaptor.getKind();
4323 mlir::ArrayAttr lhsVecElhs = lhsVecAttr.getElts();
4324 mlir::ArrayAttr rhsVecElhs = rhsVecAttr.getElts();
4325 uint64_t vecSize = lhsVecElhs.size();
4328 bool isIntAttr = vecSize && mlir::isa<cir::IntAttr>(lhsVecElhs[0]);
4329 bool isUnsignedInt =
4330 isIntAttr && mlir::cast<cir::IntType>(inputElemTy).isUnsigned();
4331 for (uint64_t i = 0; i < vecSize; i++) {
4332 mlir::Attribute lhsAttr = lhsVecElhs[i];
4333 mlir::Attribute rhsAttr = rhsVecElhs[i];
4334 bool cmpResult =
false;
4336 case cir::CmpOpKind::lt: {
4339 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() <
4340 mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
4342 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <
4343 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
4345 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <
4346 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
4350 case cir::CmpOpKind::le: {
4353 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() <=
4354 mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
4356 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <=
4357 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
4359 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <=
4360 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
4364 case cir::CmpOpKind::gt: {
4367 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() >
4368 mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
4370 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >
4371 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
4373 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >
4374 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
4378 case cir::CmpOpKind::ge: {
4381 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() >=
4382 mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
4384 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >=
4385 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
4387 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >=
4388 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
4392 case cir::CmpOpKind::eq: {
4394 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() ==
4395 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
4397 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() ==
4398 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
4402 case cir::CmpOpKind::ne: {
4404 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() !=
4405 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
4407 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() !=
4408 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
4412 case cir::CmpOpKind::one: {
4413 llvm::APFloat::cmpResult cr =
4414 mlir::cast<cir::FPAttr>(lhsAttr).getValue().compare(
4415 mlir::cast<cir::FPAttr>(rhsAttr).getValue());
4417 cr != llvm::APFloat::cmpUnordered && cr != llvm::APFloat::cmpEqual;
4420 case cir::CmpOpKind::uno: {
4421 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue().compare(
4422 mlir::cast<cir::FPAttr>(rhsAttr).getValue()) ==
4423 llvm::APFloat::cmpUnordered;
4432 cir::IntAttr::get(
getType().getElementType(), cmpResult ? -1LL : 0LL);
4435 return cir::ConstVectorAttr::get(
4436 getType(), mlir::ArrayAttr::get(getContext(), elements));
4443OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor adaptor) {
4445 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec1());
4447 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec2());
4448 if (!vec1Attr || !vec2Attr)
4451 mlir::Type vec1ElemTy =
4452 mlir::cast<cir::VectorType>(vec1Attr.getType()).getElementType();
4454 mlir::ArrayAttr vec1Elts = vec1Attr.getElts();
4455 mlir::ArrayAttr vec2Elts = vec2Attr.getElts();
4456 mlir::ArrayAttr indicesElts = adaptor.getIndices();
4459 elements.reserve(indicesElts.size());
4461 uint64_t vec1Size = vec1Elts.size();
4462 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
4463 if (idxAttr.getSInt() == -1) {
4464 elements.push_back(cir::UndefAttr::get(vec1ElemTy));
4468 uint64_t idxValue = idxAttr.getUInt();
4469 elements.push_back(idxValue < vec1Size ? vec1Elts[idxValue]
4470 : vec2Elts[idxValue - vec1Size]);
4473 return cir::ConstVectorAttr::get(
4474 getType(), mlir::ArrayAttr::get(getContext(), elements));
4477LogicalResult cir::VecShuffleOp::verify() {
4478 if (getVec1().
getType().isScalable() || getVec2().
getType().isScalable() ||
4479 getResult().
getType().isScalable())
4480 return emitOpError() <<
"scalable vectors are not supported";
4484 if (getIndices().size() != getResult().
getType().getFixedSize()) {
4485 return emitOpError() <<
": the number of elements in " << getIndices()
4486 <<
" and " << getResult().getType() <<
" don't match";
4491 if (getVec1().
getType().getElementType() !=
4492 getResult().
getType().getElementType()) {
4493 return emitOpError() <<
": element types of " << getVec1().getType()
4494 <<
" and " << getResult().getType() <<
" don't match";
4497 const uint64_t maxValidIndex = getVec1().getType().getFixedSize() +
4498 getVec2().getType().getFixedSize() - 1;
4500 getIndices().getAsRange<cir::IntAttr>(), [&](cir::IntAttr idxAttr) {
4501 return idxAttr.getSInt() != -1 && idxAttr.getUInt() > maxValidIndex;
4503 return emitOpError() <<
": index for __builtin_shufflevector must be "
4504 "less than the total number of vector elements";
4513OpFoldResult cir::VecShuffleDynamicOp::fold(FoldAdaptor adaptor) {
4514 mlir::Attribute vec = adaptor.getVec();
4515 mlir::Attribute indices = adaptor.getIndices();
4516 if (mlir::isa_and_nonnull<cir::ConstVectorAttr>(vec) &&
4517 mlir::isa_and_nonnull<cir::ConstVectorAttr>(indices)) {
4518 auto vecAttr = mlir::cast<cir::ConstVectorAttr>(vec);
4519 auto indicesAttr = mlir::cast<cir::ConstVectorAttr>(indices);
4521 mlir::ArrayAttr vecElts = vecAttr.getElts();
4522 mlir::ArrayAttr indicesElts = indicesAttr.getElts();
4524 const uint64_t numElements = vecElts.size();
4527 elements.reserve(numElements);
4529 const uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
4530 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
4531 uint64_t idxValue = idxAttr.getUInt();
4532 uint64_t newIdx = idxValue & maskBits;
4533 elements.push_back(vecElts[newIdx]);
4536 return cir::ConstVectorAttr::get(
4537 getType(), mlir::ArrayAttr::get(getContext(), elements));
4543LogicalResult cir::VecShuffleDynamicOp::verify() {
4545 if (getVec().
getType().getSize() !=
4546 mlir::cast<cir::VectorType>(getIndices().
getType()).getSize()) {
4547 return emitOpError() <<
": the number of elements in " << getVec().getType()
4548 <<
" and " << getIndices().getType() <<
" don't match";
4557LogicalResult cir::VecTernaryOp::verify() {
4562 if (getCond().
getType().getSize() != getLhs().
getType().getSize()) {
4563 return emitOpError() <<
": the number of elements in "
4564 << getCond().getType() <<
" and " << getLhs().getType()
4570OpFoldResult cir::VecTernaryOp::fold(FoldAdaptor adaptor) {
4571 mlir::Attribute cond = adaptor.getCond();
4572 mlir::Attribute lhs = adaptor.getLhs();
4573 mlir::Attribute rhs = adaptor.getRhs();
4575 if (!mlir::isa_and_nonnull<cir::ConstVectorAttr>(cond) ||
4576 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(lhs) ||
4577 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(rhs))
4579 auto condVec = mlir::cast<cir::ConstVectorAttr>(cond);
4580 auto lhsVec = mlir::cast<cir::ConstVectorAttr>(lhs);
4581 auto rhsVec = mlir::cast<cir::ConstVectorAttr>(rhs);
4583 mlir::ArrayAttr condElts = condVec.getElts();
4586 elements.reserve(condElts.size());
4588 for (
const auto &[idx, condAttr] :
4589 llvm::enumerate(condElts.getAsRange<cir::IntAttr>())) {
4590 if (condAttr.getSInt()) {
4591 elements.push_back(lhsVec.getElts()[idx]);
4593 elements.push_back(rhsVec.getElts()[idx]);
4597 cir::VectorType vecTy = getLhs().getType();
4598 return cir::ConstVectorAttr::get(
4599 vecTy, mlir::ArrayAttr::get(getContext(), elements));
4606LogicalResult cir::MatrixTransposeOp::verify() {
4607 cir::MatrixType valueTy = getValue().getType();
4608 cir::MatrixType resultTy = getResult().getType();
4610 if ((valueTy.getElementType() != resultTy.getElementType()) ||
4611 (valueTy.getNumRows() != resultTy.getNumColumns()) ||
4612 (valueTy.getNumColumns() != resultTy.getNumRows())) {
4614 cir::MatrixType::get(valueTy.getElementType(), valueTy.getNumColumns(),
4615 valueTy.getNumRows());
4616 emitOpError() <<
"operand type " << valueTy <<
" expects result type of "
4617 << expectedTy <<
" but got " << resultTy;
4628LogicalResult cir::ComplexCreateOp::verify() {
4631 <<
"operand type of cir.complex.create does not match its result type";
4638OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) {
4639 mlir::Attribute real = adaptor.getReal();
4640 mlir::Attribute imag = adaptor.getImag();
4646 auto realAttr = mlir::cast<mlir::TypedAttr>(real);
4647 auto imagAttr = mlir::cast<mlir::TypedAttr>(imag);
4648 return cir::ConstComplexAttr::get(realAttr, imagAttr);
4655LogicalResult cir::ComplexRealOp::verify() {
4656 mlir::Type operandTy = getOperand().getType();
4657 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
4658 operandTy = complexOperandTy.getElementType();
4661 emitOpError() <<
": result type does not match operand type";
4668OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) {
4669 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
4672 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
4673 return complexCreateOp.getOperand(0);
4676 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
4677 return complex ? complex.getReal() :
nullptr;
4684LogicalResult cir::ComplexImagOp::verify() {
4685 mlir::Type operandTy = getOperand().getType();
4686 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
4687 operandTy = complexOperandTy.getElementType();
4690 emitOpError() <<
": result type does not match operand type";
4697OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) {
4698 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
4701 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
4702 return complexCreateOp.getOperand(1);
4705 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
4706 return complex ? complex.getImag() :
nullptr;
4713LogicalResult cir::ComplexRealPtrOp::verify() {
4714 mlir::Type resultPointeeTy =
getType().getPointee();
4715 cir::PointerType operandPtrTy = getOperand().getType();
4716 auto operandPointeeTy =
4717 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
4719 if (resultPointeeTy != operandPointeeTy.getElementType()) {
4720 return emitOpError() <<
": result type does not match operand type";
4730LogicalResult cir::ComplexImagPtrOp::verify() {
4731 mlir::Type resultPointeeTy =
getType().getPointee();
4732 cir::PointerType operandPtrTy = getOperand().getType();
4733 auto operandPointeeTy =
4734 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
4736 if (resultPointeeTy != operandPointeeTy.getElementType()) {
4737 return emitOpError()
4738 <<
"cir.complex.imag_ptr result type does not match operand type";
4749 llvm::function_ref<llvm::APInt(
const llvm::APInt &)> func,
4750 bool poisonZero =
false) {
4751 if (mlir::isa_and_present<cir::PoisonAttr>(inputAttr)) {
4756 auto input = mlir::dyn_cast_if_present<IntAttr>(inputAttr);
4760 llvm::APInt inputValue = input.getValue();
4761 if (poisonZero && inputValue.isZero())
4762 return cir::PoisonAttr::get(input.getType());
4764 llvm::APInt resultValue = func(inputValue);
4765 return IntAttr::get(input.getType(), resultValue);
4768OpFoldResult BitClrsbOp::fold(FoldAdaptor adaptor) {
4769 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4770 unsigned resultValue =
4771 inputValue.getBitWidth() - inputValue.getSignificantBits();
4772 return llvm::APInt(inputValue.getBitWidth(), resultValue);
4776OpFoldResult BitClzOp::fold(FoldAdaptor adaptor) {
4779 [](
const llvm::APInt &inputValue) {
4780 unsigned resultValue = inputValue.countLeadingZeros();
4781 return llvm::APInt(inputValue.getBitWidth(), resultValue);
4786OpFoldResult BitCtzOp::fold(FoldAdaptor adaptor) {
4789 [](
const llvm::APInt &inputValue) {
4790 return llvm::APInt(inputValue.getBitWidth(),
4791 inputValue.countTrailingZeros());
4796OpFoldResult BitFfsOp::fold(FoldAdaptor adaptor) {
4797 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4798 unsigned trailingZeros = inputValue.countTrailingZeros();
4800 trailingZeros == inputValue.getBitWidth() ? 0 : trailingZeros + 1;
4801 return llvm::APInt(inputValue.getBitWidth(), result);
4805OpFoldResult BitParityOp::fold(FoldAdaptor adaptor) {
4806 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4807 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount() % 2);
4811OpFoldResult BitPopcountOp::fold(FoldAdaptor adaptor) {
4812 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4813 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount());
4817OpFoldResult BitReverseOp::fold(FoldAdaptor adaptor) {
4818 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4819 return inputValue.reverseBits();
4823OpFoldResult ByteSwapOp::fold(FoldAdaptor adaptor) {
4824 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4825 return inputValue.byteSwap();
4829OpFoldResult RotateOp::fold(FoldAdaptor adaptor) {
4830 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()) ||
4831 mlir::isa_and_present<cir::PoisonAttr>(adaptor.getAmount())) {
4833 return cir::PoisonAttr::get(
getType());
4836 auto input = mlir::dyn_cast_if_present<IntAttr>(adaptor.getInput());
4837 auto amount = mlir::dyn_cast_if_present<IntAttr>(adaptor.getAmount());
4838 if (!input && !amount)
4847 llvm::APInt inputValue;
4849 inputValue = input.getValue();
4850 if (inputValue.isZero() || inputValue.isAllOnes()) {
4856 uint64_t amountValue;
4858 amountValue = amount.getValue().urem(getInput().
getType().getWidth());
4859 if (amountValue == 0) {
4865 if (!input || !amount)
4868 assert(inputValue.getBitWidth() == getInput().
getType().getWidth() &&
4869 "input value must have the same bit width as the input type");
4871 llvm::APInt resultValue;
4873 resultValue = inputValue.rotl(amountValue);
4875 resultValue = inputValue.rotr(amountValue);
4877 return IntAttr::get(input.getContext(), input.getType(), resultValue);
4884void cir::InlineAsmOp::print(OpAsmPrinter &p) {
4885 p <<
'(' << getAsmFlavor() <<
", ";
4890 auto *nameIt = names.begin();
4891 auto *attrIt = getOperandAttrs().begin();
4893 for (mlir::OperandRange ops : getAsmOperands()) {
4894 p << *nameIt <<
" = ";
4897 llvm::interleaveComma(llvm::make_range(ops.begin(), ops.end()), p,
4899 p.printOperand(value);
4900 p <<
" : " << value.getType();
4901 if (mlir::isa<mlir::UnitAttr>(*attrIt))
4902 p <<
" (maybe_memory)";
4911 p.printString(getAsmString());
4913 p.printString(getConstraints());
4917 if (getSideEffects())
4918 p <<
" side_effects";
4920 p.printOptionalAttrDict(
4921 getOperation()->getDiscardableAttrDictionary().getValue());
4923 if (
auto v = getRes())
4924 p <<
" -> " << v.getType();
4927void cir::InlineAsmOp::build(OpBuilder &odsBuilder, OperationState &odsState,
4929 StringRef asmString, StringRef constraints,
4930 bool sideEffects, cir::AsmFlavor asmFlavor,
4934 for (
auto operandRange : asmOperands) {
4935 segments.push_back(operandRange.size());
4936 odsState.addOperands(operandRange);
4939 odsState.addAttribute(
4940 "operands_segments",
4941 DenseI32ArrayAttr::get(odsBuilder.getContext(), segments));
4942 odsState.addAttribute(
"asm_string", odsBuilder.getStringAttr(asmString));
4943 odsState.addAttribute(
"constraints", odsBuilder.getStringAttr(constraints));
4944 odsState.addAttribute(
"asm_flavor",
4945 AsmFlavorAttr::get(odsBuilder.getContext(), asmFlavor));
4948 odsState.addAttribute(
"side_effects", odsBuilder.getUnitAttr());
4950 odsState.addAttribute(
"operand_attrs", odsBuilder.getArrayAttr(operandAttrs));
4953ParseResult cir::InlineAsmOp::parse(OpAsmParser &parser,
4954 OperationState &result) {
4957 std::string asmString, constraints;
4959 MLIRContext *ctxt = parser.getBuilder().getContext();
4961 auto error = [&](
const Twine &msg) -> LogicalResult {
4962 return parser.emitError(parser.getCurrentLocation(), msg);
4965 auto expected = [&](
const std::string &c) {
4966 return error(
"expected '" + c +
"'");
4969 if (parser.parseLParen().failed())
4970 return expected(
"(");
4972 auto flavor = FieldParser<AsmFlavor, AsmFlavor>::parse(parser);
4974 return error(
"Unknown AsmFlavor");
4976 if (parser.parseComma().failed())
4977 return expected(
",");
4979 auto parseValue = [&](
Value &v) {
4980 OpAsmParser::UnresolvedOperand op;
4982 if (parser.parseOperand(op) || parser.parseColon())
4983 return error(
"can't parse operand");
4986 if (parser.parseType(typ).failed())
4987 return error(
"can't parse operand type");
4989 if (parser.resolveOperand(op, typ, tmp))
4990 return error(
"can't resolve operand");
4992 return mlir::success();
4995 auto parseOperands = [&](llvm::StringRef
name) {
4996 if (parser.parseKeyword(name).failed())
4997 return error(
"expected " + name +
" operands here");
4998 if (parser.parseEqual().failed())
4999 return expected(
"=");
5000 if (parser.parseLSquare().failed())
5001 return expected(
"[");
5004 if (parser.parseOptionalRSquare().succeeded()) {
5005 operandsGroupSizes.push_back(size);
5006 if (parser.parseComma())
5007 return expected(
",");
5008 return mlir::success();
5011 auto parseOperand = [&]() {
5013 if (parseValue(val).succeeded()) {
5014 result.operands.push_back(val);
5017 if (parser.parseOptionalLParen().failed()) {
5018 operandAttrs.push_back(mlir::DictionaryAttr::get(ctxt));
5019 return mlir::success();
5022 if (parser.parseKeyword(
"maybe_memory").succeeded()) {
5023 operandAttrs.push_back(mlir::UnitAttr::get(ctxt));
5024 if (parser.parseRParen())
5025 return expected(
")");
5026 return mlir::success();
5028 return expected(
"maybe_memory");
5031 return mlir::failure();
5034 if (parser.parseCommaSeparatedList(parseOperand).failed())
5035 return mlir::failure();
5037 if (parser.parseRSquare().failed() || parser.parseComma().failed())
5038 return expected(
"]");
5039 operandsGroupSizes.push_back(size);
5040 return mlir::success();
5043 if (parseOperands(
"out").failed() || parseOperands(
"in").failed() ||
5044 parseOperands(
"in_out").failed())
5045 return error(
"failed to parse operands");
5047 if (parser.parseLBrace())
5048 return expected(
"{");
5049 if (parser.parseString(&asmString))
5050 return error(
"asm string parsing failed");
5051 if (parser.parseString(&constraints))
5052 return error(
"constraints string parsing failed");
5053 if (parser.parseRBrace())
5054 return expected(
"}");
5055 if (parser.parseRParen())
5056 return expected(
")");
5058 if (parser.parseOptionalKeyword(
"side_effects").succeeded())
5059 result.attributes.set(
"side_effects", UnitAttr::get(ctxt));
5061 if (parser.parseOptionalAttrDict(result.attributes).failed())
5062 return mlir::failure();
5064 if (parser.parseOptionalArrow().succeeded() &&
5065 parser.parseType(resType).failed())
5066 return mlir::failure();
5068 result.attributes.set(
"asm_flavor", AsmFlavorAttr::get(ctxt, *flavor));
5069 result.attributes.set(
"asm_string", StringAttr::get(ctxt, asmString));
5070 result.attributes.set(
"constraints", StringAttr::get(ctxt, constraints));
5071 result.attributes.set(
"operand_attrs", ArrayAttr::get(ctxt, operandAttrs));
5072 result.getOrAddProperties<InlineAsmOp::Properties>().operands_segments =
5073 parser.getBuilder().getDenseI32ArrayAttr(operandsGroupSizes);
5075 result.addTypes(TypeRange{resType});
5077 return mlir::success();
5080void InlineAsmOp::getEffects(
5084 if (getSideEffects()) {
5085 effects.emplace_back(mlir::MemoryEffects::Read::get());
5086 effects.emplace_back(mlir::MemoryEffects::Write::get());
5094template <
typename ThrowOpTy>
5097 return mlir::success();
5099 if (op.getNumOperands() != 0) {
5100 if (op.getTypeInfo())
5101 return mlir::success();
5102 return op.emitOpError() <<
"'type_info' symbol attribute missing";
5105 return mlir::failure();
5110mlir::LogicalResult cir::TryThrowOp::verify() {
5118LogicalResult cir::AtomicFetchOp::verify() {
5119 if (getBinop() != cir::AtomicFetchKind::Add &&
5120 getBinop() != cir::AtomicFetchKind::Sub &&
5121 getBinop() != cir::AtomicFetchKind::Max &&
5122 getBinop() != cir::AtomicFetchKind::Min &&
5123 getBinop() != cir::AtomicFetchKind::Maximum &&
5124 getBinop() != cir::AtomicFetchKind::Minimum &&
5125 getBinop() != cir::AtomicFetchKind::MaximumNum &&
5126 getBinop() != cir::AtomicFetchKind::MinimumNum &&
5127 !mlir::isa<cir::IntType>(getVal().
getType()))
5128 return emitError(
"only atomic add, sub, max, min, maximum, minimum, "
5129 "maximum_num, and minimum_num operation could operate on "
5130 "floating-point values");
5132 if ((getBinop() == cir::AtomicFetchKind::Maximum ||
5133 getBinop() == cir::AtomicFetchKind::Minimum ||
5134 getBinop() == cir::AtomicFetchKind::MaximumNum ||
5135 getBinop() == cir::AtomicFetchKind::MinimumNum) &&
5136 !cir::isFPOrVectorOfFPType(getVal().
getType()))
5137 return emitError(
"atomic maximum, minimum, maximum_num, and minimum_num "
5138 "operation could only operate on floating-point values");
5147LogicalResult cir::TypeInfoAttr::verify(
5148 ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
5149 ::mlir::Type type, ::mlir::ArrayAttr typeInfoData) {
5151 if (cir::ConstRecordAttr::verify(emitError, type, typeInfoData).failed())
5161void cir::TryOp::getSuccessorRegions(
5162 mlir::RegionBranchPoint point,
5164 if (point.isParent()) {
5165 regions.emplace_back(&getTryRegion());
5168 mlir::Operation *term = point.getTerminatorPredecessorOrNull();
5169 if (term->getParentRegion() != &getTryRegion()) {
5170 regions.emplace_back(getOperation());
5175 if (!isa<cir::ResumeOp>(term) || getHandlerRegions().empty())
5176 regions.emplace_back(getOperation());
5185 regions.reserve(regions.size() + getHandlerRegions().size());
5186 for (mlir::Region &handlerRegion : getHandlerRegions())
5187 regions.emplace_back(&handlerRegion);
5198 cir::ConstructCatchParamOp constructOp) {
5199 mlir::WalkResult result =
5200 handlerRegion.walk<mlir::WalkOrder::PreOrder>([&](mlir::Operation *op) {
5201 if (mlir::isa<cir::TryOp>(op))
5202 return mlir::WalkResult::skip();
5203 auto initOp = mlir::dyn_cast<cir::InitCatchParamOp>(op);
5205 return mlir::WalkResult::advance();
5207 cir::InitCatchKind
kind = initOp.getKind();
5209 constructOp && constructOp.getParamAddr() == initOp.getParamAddr();
5210 if (sameParam && constructOp.getKind() !=
kind) {
5211 initOp.emitOpError(
"kind '")
5212 << cir::stringifyInitCatchKind(
kind)
5213 <<
"' does not match the kind '"
5214 << cir::stringifyInitCatchKind(constructOp.getKind())
5215 <<
"' of the preceding 'cir.construct_catch_param'";
5216 return mlir::WalkResult::interrupt();
5218 if ((
kind == cir::InitCatchKind::ReferenceToPointer ||
5219 kind == cir::InitCatchKind::NonTrivialCopy) &&
5221 initOp.emitOpError(
"'")
5222 << cir::stringifyInitCatchKind(
kind)
5223 <<
"' requires a preceding 'cir.construct_catch_param' of the "
5224 "same kind on the same parameter";
5225 return mlir::WalkResult::interrupt();
5227 return mlir::WalkResult::advance();
5229 return failure(result.wasInterrupted());
5232LogicalResult cir::TryOp::verifyRegions() {
5233 mlir::ArrayAttr handlerTypes = getHandlerTypes();
5234 if (!handlerTypes) {
5235 if (!getHandlerRegions().empty())
5237 "handler regions must be empty when no handler types are present");
5241 mlir::MutableArrayRef<mlir::Region> handlerRegions = getHandlerRegions();
5245 if (handlerRegions.size() != handlerTypes.size())
5247 "number of handler regions and handler types must match");
5255 if (llvm::any_of(handlerTypes, [](mlir::Attribute typeAttr) {
5256 return mlir::isa<cir::EhFilterAttr, cir::EhUnexpectedAttr>(typeAttr);
5258 if (handlerTypes.size() != 2 ||
5259 !mlir::isa<cir::EhFilterAttr>(handlerTypes[0]) ||
5260 !mlir::isa<cir::EhUnexpectedAttr>(handlerTypes[1]))
5261 return emitOpError(
"a filter handler must be followed by an unexpected "
5262 "handler, and the two must be the only handlers");
5265 for (
const auto &[typeAttr, handlerRegion] :
5266 llvm::zip(handlerTypes, handlerRegions)) {
5268 mlir::Block &entryBlock = handlerRegion.front();
5269 if (entryBlock.getNumArguments() != 1 ||
5270 !mlir::isa<cir::EhTokenType>(entryBlock.getArgument(0).getType()))
5272 "handler region must have a single '!cir.eh_token' argument");
5276 if (mlir::isa<cir::UnwindAttr, cir::EhFilterAttr, cir::EhUnexpectedAttr>(
5280 if (entryBlock.empty())
5281 return emitOpError(
"catch handler region must not be empty");
5287 if (mlir::isa<cir::EhTerminateOp>(entryBlock.front())) {
5288 if (!mlir::isa<cir::CatchAllAttr>(typeAttr))
5289 return emitOpError(
"'cir.eh.terminate' is only allowed in a catch-all "
5308 mlir::Operation *firstOp = &entryBlock.front();
5309 if (mlir::isa<cir::LifetimeStartOp>(firstOp)) {
5310 mlir::Operation *next = firstOp->getNextNode();
5311 auto lifetimeScope = mlir::dyn_cast_if_present<cir::CleanupScopeOp>(next);
5313 return emitOpError(
"'cir.lifetime.start' in a catch handler region "
5314 "must be followed by the 'cir.cleanup.scope' of "
5315 "its lifetime-end cleanup");
5316 if (lifetimeScope.getBodyRegion().empty())
5318 "'cir.lifetime.start' in a catch handler region must be "
5319 "followed by the 'cir.cleanup.scope' of its lifetime-end "
5321 mlir::Block &scopeBody = lifetimeScope.getBodyRegion().front();
5322 firstOp = scopeBody.empty() ?
nullptr : &scopeBody.front();
5326 mlir::dyn_cast_if_present<cir::ConstructCatchParamOp>(firstOp);
5328 firstOp = firstOp->getNextNode();
5329 if (!mlir::isa_and_present<cir::BeginCatchOp>(firstOp))
5331 "catch handler region must start with 'cir.begin_catch'");
5341 mlir::OpAsmPrinter &printer, cir::TryOp op,
5342 mlir::MutableArrayRef<mlir::Region> handlerRegions,
5343 mlir::ArrayAttr handlerTypes) {
5347 for (
const auto [typeIdx, typeAttr] : llvm::enumerate(handlerTypes)) {
5351 if (mlir::isa<cir::CatchAllAttr>(typeAttr)) {
5352 printer <<
"catch all ";
5353 }
else if (mlir::isa<cir::UnwindAttr>(typeAttr)) {
5354 printer <<
"unwind ";
5355 }
else if (
auto filterAttr = mlir::dyn_cast<cir::EhFilterAttr>(typeAttr)) {
5356 printer <<
"filter [";
5357 llvm::interleaveComma(
5358 filterAttr.getPermittedTypes(), printer,
5359 [&](mlir::Attribute sym) { printer.printAttribute(sym); });
5361 }
else if (mlir::isa<cir::EhUnexpectedAttr>(typeAttr)) {
5362 printer <<
"unexpected ";
5364 printer <<
"catch [type ";
5365 printer.printAttribute(typeAttr);
5370 mlir::Region ®ion = handlerRegions[typeIdx];
5371 if (!region.empty() && region.front().getNumArguments() > 0) {
5373 printer.printRegionArgument(region.front().getArgument(0));
5377 printer.printRegion(region,
5384 mlir::OpAsmParser &parser,
5386 mlir::ArrayAttr &handlerTypes) {
5388 auto parseCheckedCatcherRegion = [&]() -> mlir::ParseResult {
5389 handlerRegions.emplace_back(
new mlir::Region);
5391 mlir::Region &currRegion = *handlerRegions.back();
5395 if (parser.parseLParen())
5397 mlir::OpAsmParser::Argument arg;
5398 if (parser.parseArgument(arg,
true))
5400 regionArgs.push_back(arg);
5401 if (parser.parseRParen())
5404 mlir::SMLoc regionLoc = parser.getCurrentLocation();
5405 if (parser.parseRegion(currRegion, regionArgs)) {
5406 handlerRegions.clear();
5410 if (currRegion.empty())
5411 return parser.emitError(regionLoc,
"handler region shall not be empty");
5413 if (!(currRegion.back().mightHaveTerminator() &&
5414 currRegion.back().getTerminator()))
5415 return parser.emitError(
5416 regionLoc,
"blocks are expected to be explicitly terminated");
5421 bool hasCatchAll =
false;
5423 while (parser.parseOptionalKeyword(
"catch").succeeded()) {
5424 bool hasLSquare = parser.parseOptionalLSquare().succeeded();
5426 llvm::StringRef attrStr;
5427 if (parser.parseOptionalKeyword(&attrStr, {
"all",
"type"}).failed())
5428 return parser.emitError(parser.getCurrentLocation(),
5429 "expected 'all' or 'type' keyword");
5431 bool isCatchAll = attrStr ==
"all";
5434 return parser.emitError(parser.getCurrentLocation(),
5435 "can't have more than one catch all");
5439 mlir::Attribute exceptionRTTIAttr;
5440 if (!isCatchAll && parser.parseAttribute(exceptionRTTIAttr).failed())
5441 return parser.emitError(parser.getCurrentLocation(),
5442 "expected valid RTTI info attribute");
5444 catcherAttrs.push_back(isCatchAll
5445 ? cir::CatchAllAttr::get(parser.getContext())
5446 : exceptionRTTIAttr);
5448 if (hasLSquare && isCatchAll)
5449 return parser.emitError(parser.getCurrentLocation(),
5450 "catch all dosen't need RTTI info attribute");
5452 if (hasLSquare && parser.parseRSquare().failed())
5453 return parser.emitError(parser.getCurrentLocation(),
5454 "expected `]` after RTTI info attribute");
5456 if (parseCheckedCatcherRegion().failed())
5457 return mlir::failure();
5463 if (parser.parseOptionalKeyword(
"filter").succeeded()) {
5464 mlir::SMLoc filterLoc = parser.getCurrentLocation();
5466 auto parsePermittedType = [&]() -> mlir::ParseResult {
5467 mlir::SMLoc typeLoc = parser.getCurrentLocation();
5468 mlir::Attribute rtti;
5469 if (parser.parseAttribute(rtti).failed())
5470 return mlir::failure();
5471 if (!mlir::isa<cir::GlobalViewAttr>(rtti))
5472 return parser.emitError(typeLoc,
"expected a type info symbol naming a "
5473 "permitted exception type");
5474 permittedTypes.push_back(rtti);
5475 return mlir::success();
5478 .parseCommaSeparatedList(mlir::OpAsmParser::Delimiter::Square,
5481 return mlir::failure();
5483 auto filterAttr = cir::EhFilterAttr::getChecked(
5484 [&]() {
return parser.emitError(filterLoc); }, parser.getContext(),
5485 parser.getBuilder().getArrayAttr(permittedTypes));
5487 return mlir::failure();
5488 catcherAttrs.push_back(filterAttr);
5489 if (parseCheckedCatcherRegion().failed())
5490 return mlir::failure();
5493 if (parser.parseOptionalKeyword(
"unexpected").succeeded()) {
5494 catcherAttrs.push_back(cir::EhUnexpectedAttr::get(parser.getContext()));
5495 if (parseCheckedCatcherRegion().failed())
5496 return mlir::failure();
5499 if (parser.parseOptionalKeyword(
"unwind").succeeded()) {
5501 return parser.emitError(parser.getCurrentLocation(),
5502 "unwind can't be used with catch all");
5504 catcherAttrs.push_back(cir::UnwindAttr::get(parser.getContext()));
5505 if (parseCheckedCatcherRegion().failed())
5506 return mlir::failure();
5509 handlerTypes = parser.getBuilder().getArrayAttr(catcherAttrs);
5510 return mlir::success();
5518cir::EhTypeIdOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
5519 Operation *op = symbolTable.lookupNearestSymbolFrom(*
this, getTypeSymAttr());
5520 if (!isa_and_nonnull<GlobalOp>(op))
5521 return emitOpError(
"'")
5522 << getTypeSym() <<
"' does not reference a valid cir.global";
5530LogicalResult cir::LifetimeStartOp::verify() {
5534LogicalResult cir::LifetimeEndOp::verify() {
5544 auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(attr);
5545 if (!intAttr || !intAttr.getType().isSignlessInteger(32))
5546 return std::nullopt;
5547 int64_t width = intAttr.getInt();
5550 return std::nullopt;
5551 return static_cast<unsigned>(width);
5554LogicalResult cir::MemChrOp::verify() {
5555 auto moduleOp = (*this)->getParentOfType<mlir::ModuleOp>();
5557 return emitOpError(
"expects an enclosing module");
5560 if (mlir::cast<cir::PointerType>(getSrc().
getType()).getAddrSpace())
5561 return emitOpError(
"src must be in the default address space");
5563 auto checkWidth = [&](cir::IntType type, llvm::StringRef operandName,
5564 llvm::StringRef attrName) -> LogicalResult {
5565 mlir::Attribute
attr = moduleOp->getAttr(attrName);
5567 return emitOpError(
"expects the module to record ") << attrName;
5570 return emitOpError(
"requires ")
5572 <<
" to be a signless i32 holding a fundamental integer width";
5573 if (type.getWidth() != *width)
5574 return emitOpError() << operandName <<
" must have the width recorded in "
5579 if (failed(checkWidth(getPattern().
getType(),
"pattern",
5580 cir::CIRDialect::getIntTypeWidthAttrName())))
5582 return checkWidth(getLen().
getType(),
"len",
5583 cir::CIRDialect::getSizeTypeWidthAttrName());
5594 cir::InitCatchKind
kind,
5595 cir::PointerType paramAddrType) {
5596 if (
kind != cir::InitCatchKind::ReferenceToPointer &&
5597 kind != cir::InitCatchKind::ReferenceToRecordPointer)
5600 auto refType = mlir::dyn_cast<cir::PointerType>(paramAddrType.getPointee());
5601 if (!refType || !mlir::isa<cir::PointerType>(refType.getPointee()))
5602 return op->emitOpError(
"'")
5603 << cir::stringifyInitCatchKind(
kind)
5604 <<
"' requires 'param_addr' to be the address of a reference to a "
5609LogicalResult cir::InitCatchParamOp::verify() {
5617LogicalResult cir::ConstructCatchParamOp::verify() {
5621LogicalResult cir::ConstructCatchParamOp::verifySymbolUses(
5622 SymbolTableCollection &symbolTable) {
5623 auto copyFnAttr = getCopyFnAttr();
5627 symbolTable.lookupNearestSymbolFrom<cir::FuncOp>(*
this, getCopyFnAttr());
5629 return emitOpError(
"'")
5630 << *getCopyFn() <<
"' does not reference a valid cir.func";
5632 if (!fn->hasAttr(cir::CIRDialect::getCatchCopyThunkAttrName()))
5633 return emitOpError(
"catch-init copy_fn must be tagged with the ")
5634 << cir::CIRDialect::getCatchCopyThunkAttrName() <<
" attribute";
5636 cir::FuncType fnType = fn.getFunctionType();
5637 if (fnType.getNumInputs() != 2 || !fnType.hasVoidReturn())
5638 return emitOpError(
"catch-init copy_fn must take two pointer arguments and "
5641 if (fnType.getInput(0) != getParamAddr().
getType())
5642 return emitOpError(
"first argument of catch-init copy_fn must match the "
5643 "type of 'param_addr'");
5645 if (fnType.getInput(1) != getParamAddr().
getType())
5647 "second argument of catch-init copy_fn must be a pointer "
5648 "to the catch type");
5657LogicalResult cir::EhDispatchOp::verify() {
5658 mlir::ArrayAttr handlerTypes = getCatchTypesAttr();
5662 bool hasFilter =
false;
5663 for (mlir::Attribute typeAttr : handlerTypes) {
5664 if (!mlir::isa<cir::EhFilterAttr>(typeAttr))
5667 return emitOpError(
"can't have more than one 'filter' handler");
5675 if (hasFilter && getDefaultIsCatchAll())
5677 "'filter' handler requires an 'unwind' default destination");
5683 OpAsmParser &parser, mlir::ArrayAttr &catchTypes,
5684 SmallVectorImpl<Block *> &catchDestinations, Block *&defaultDestination,
5685 mlir::UnitAttr &defaultIsCatchAll) {
5687 if (parser.parseLSquare())
5691 bool hasCatchAll =
false;
5692 bool hasUnwind =
false;
5695 auto parseHandler = [&]() -> ParseResult {
5697 if (succeeded(parser.parseOptionalKeyword(
"catch_all"))) {
5699 return parser.emitError(parser.getCurrentLocation(),
5700 "duplicate 'catch_all' handler");
5702 return parser.emitError(parser.getCurrentLocation(),
5703 "cannot have both 'catch_all' and 'unwind'");
5706 if (parser.parseColon().failed())
5709 if (parser.parseSuccessor(defaultDestination).failed())
5715 if (succeeded(parser.parseOptionalKeyword(
"unwind"))) {
5717 return parser.emitError(parser.getCurrentLocation(),
5718 "duplicate 'unwind' handler");
5720 return parser.emitError(parser.getCurrentLocation(),
5721 "cannot have both 'catch_all' and 'unwind'");
5724 if (parser.parseColon().failed())
5727 if (parser.parseSuccessor(defaultDestination).failed())
5735 if (succeeded(parser.parseOptionalKeyword(
"filter"))) {
5736 SMLoc filterLoc = parser.getCurrentLocation();
5738 auto parsePermittedType = [&]() -> ParseResult {
5739 mlir::SMLoc
typeLoc = parser.getCurrentLocation();
5740 mlir::Attribute rtti;
5741 if (parser.parseAttribute(rtti).failed())
5743 if (!mlir::isa<cir::GlobalViewAttr>(rtti))
5744 return parser.emitError(typeLoc,
5745 "expected a type info symbol naming a "
5746 "permitted exception type");
5747 permittedTypes.push_back(rtti);
5751 .parseCommaSeparatedList(OpAsmParser::Delimiter::Paren,
5756 auto filterAttr = cir::EhFilterAttr::getChecked(
5757 [&]() {
return parser.emitError(filterLoc); }, parser.getContext(),
5758 parser.getBuilder().getArrayAttr(permittedTypes));
5761 handlerTypes.push_back(filterAttr);
5763 if (parser.parseColon().failed())
5767 if (parser.parseSuccessor(dest).failed())
5769 catchDestinations.push_back(dest);
5776 if (parser.parseKeyword(
"catch").failed())
5779 if (parser.parseLParen().failed())
5782 mlir::Attribute catchTypeAttr;
5783 if (parser.parseAttribute(catchTypeAttr).failed())
5785 handlerTypes.push_back(catchTypeAttr);
5787 if (parser.parseRParen().failed())
5790 if (parser.parseColon().failed())
5794 if (parser.parseSuccessor(dest).failed())
5796 catchDestinations.push_back(dest);
5800 if (parser.parseCommaSeparatedList(parseHandler).failed())
5803 if (parser.parseRSquare().failed())
5807 if (!hasCatchAll && !hasUnwind)
5808 return parser.emitError(parser.getCurrentLocation(),
5809 "must have either 'catch_all' or 'unwind' handler");
5812 if (!handlerTypes.empty())
5813 catchTypes = parser.getBuilder().getArrayAttr(handlerTypes);
5816 defaultIsCatchAll = parser.getBuilder().getUnitAttr();
5822 mlir::ArrayAttr catchTypes,
5823 SuccessorRange catchDestinations,
5824 Block *defaultDestination,
5825 mlir::UnitAttr defaultIsCatchAll) {
5833 llvm::zip(catchTypes, catchDestinations),
5835 mlir::Attribute typeAttr = std::get<0>(i);
5836 if (
auto filterAttr = mlir::dyn_cast<cir::EhFilterAttr>(typeAttr)) {
5838 llvm::interleaveComma(
5839 filterAttr.getPermittedTypes(), p,
5840 [&](mlir::Attribute sym) { p.printAttribute(sym); });
5843 p.printAttribute(typeAttr);
5846 p.printSuccessor(std::get<1>(i));
5858 if (defaultIsCatchAll)
5859 p <<
" catch_all : ";
5862 p.printSuccessor(defaultDestination);
5872bool cir::StdFindOp::signatureMatches(mlir::TypeRange operands,
5873 mlir::TypeRange results) {
5874 if (operands.size() != getNumArgs() || results.size() != 1)
5876 mlir::Type iterTy = operands[0];
5877 return iterTy == operands[1] && iterTy == operands[2] && iterTy == results[0];
static StringRef bytes(const std::vector< T, Allocator > &v)
static LogicalResult verifyLoopCleanup(LoopOpTy op)
static LogicalResult verifyOpenCLCXXVersion(ModuleOp module, cir::OpenCLVersionAttr cxxVersion)
static LogicalResult verifyCatchParamPairing(mlir::Region &handlerRegion, cir::ConstructCatchParamOp constructOp)
Verify that each cir.init_catch_param in handlerRegion, outside any nested cir.try,...
static mlir::LogicalResult checkReturnAndFunction(cir::ReturnOp op, cir::FuncOp function)
static LogicalResult verifyOffloadContainer(mlir::Operation *op)
static std::optional< unsigned > getRecordedIntegerWidth(mlir::Attribute attr)
Reads a fundamental integer width from a signless i32 attribute.
static bool isCirFunctionPointerType(mlir::Type ty)
static LogicalResult verifyMemberPtrCast(Operation *op, mlir::Value src, mlir::Type resultTy)
static bool isFloatingPointCastKind(cir::CastKind kind)
static LogicalResult verifyOffloadKind(mlir::ModuleOp module, cir::OffloadKind expected)
static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, mlir::OperationState &result, bool hasDestinationBlocks=false)
static mlir::Type memberPointeeType(cir::RecordType recordTy, unsigned idx)
static bool isIntOrBoolCast(cir::CastOp op)
static LogicalResult verifyCatchParamAddr(mlir::Operation *op, cir::InitCatchKind kind, cir::PointerType paramAddrType)
For the reference_to_pointer and reference_to_record_pointer kinds, emit an error on op unless paramA...
static void printConstant(OpAsmPrinter &p, Attribute value)
static ParseResult checkEffectAttrKinds(mlir::OpAsmParser &parser, llvm::SMLoc loc, const mlir::NamedAttrList &attrs)
Reject an attribute in an explicit attribute dictionary whose value is not the attribute class expect...
static void printCallCommon(mlir::Operation *op, mlir::FlatSymbolRefAttr calleeSym, mlir::Value indirectCallee, mlir::OpAsmPrinter &printer, bool isNothrow, ArrayAttr argAttrs, ArrayAttr resAttrs, mlir::Block *normalDest=nullptr, mlir::Block *unwindDest=nullptr)
static bool areOpenCLVersionsCompatible(cir::OpenCLVersionAttr openCLVersion, cir::OpenCLVersionAttr cxxVersion)
static LogicalResult verifyOpenCLVersionAttrPlacement(Operation *op, NamedAttribute attr)
static bool isInVarCtorRegion(mlir::Operation *op)
Returns true if op is nested in the ctor region of a cir.global or cir.local_init without crossing a ...
ParseResult parseInlineKindAttr(OpAsmParser &parser, cir::InlineKindAttr &inlineKindAttr)
void printInlineKindAttr(OpAsmPrinter &p, cir::InlineKindAttr inlineKindAttr)
static LogicalResult verifyOpenCLVersionAttr(Operation *op, NamedAttribute attr)
static LogicalResult verifyCallCommInSymbolUses(mlir::Operation *op, SymbolTableCollection &symbolTable)
static bool isOpenCLVersionAttrName(StringRef attrName)
static LogicalResult ensureRegionTerm(OpAsmParser &parser, Region ®ion, SMLoc errLoc)
static OpFoldResult foldUnaryBitOp(mlir::Attribute inputAttr, llvm::function_ref< llvm::APInt(const llvm::APInt &)> func, bool poisonZero=false)
static llvm::StringRef getLinkageAttrNameString()
Returns the name used for the linkage attribute.
static RetTy parseOptionalCIRKeyword(AsmParser &parser, EnumTy defaultValue)
Parse an enum from the keyword, or default to the provided default value.
static LogicalResult verifyProducedBy(Operation *op, Value operand, StringRef operandName)
static mlir::ParseResult parseTryCallDestinations(mlir::OpAsmParser &parser, mlir::OperationState &result)
static void printComdatName(OpAsmPrinter &p, StringAttr comdat)
static ParseResult parseCIRKeyword(AsmParser &parser, RetTy &result)
Parse an enum from the keyword, return failure if the keyword is not found.
static Value tryFoldCastChain(cir::CastOp op)
static bool omitRegionTerm(mlir::Region &r)
static ParseResult parseConstantValue(OpAsmParser &parser, mlir::Attribute &valueAttr)
static LogicalResult verifyArrayCtorDtor(Op op)
static bool isFuncAttrInDict(llvm::StringRef name)
Declared cir.func attributes with no dedicated syntax, which print in and parse from the attribute di...
static bool isRedundantBeforeReturn(mlir::Region &cleanupRegion)
static mlir::LogicalResult verifyThrowOpImpl(ThrowOpTy op)
static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType, mlir::Attribute attrType)
#define REGISTER_ENUM_TYPE(Ty)
static int parseOptionalKeywordAlternative(AsmParser &parser, ArrayRef< llvm::StringRef > keywords)
llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> BuilderCallbackRef
llvm::function_ref< void( mlir::OpBuilder &, mlir::Location, mlir::OperationState &)> BuilderOpStateCallbackRef
static std::optional< NonLoc > getIndex(ProgramStateRef State, const ElementRegion *ER, CharKind CK)
static Decl::Kind getKind(const Decl *D)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a an optional score condition
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines the TargetCXXABI class, which abstracts details of the C++ ABI that we're targeting.
unsigned getProgramAddressSpace() const
C++ view class that accepts both !cir.struct and !cir.union types.
llvm::ArrayRef< mlir::Type > getMembers() const
static bool isSupportedCXXABI(const llvm::Triple &T, Kind Kind)
static bool isABI(StringRef Name)
Kind
The basic C++ ABI kind.
void addBytecodeInterface(CIRDialect *dialect)
Add the interfaces necessary for encoding the CIR dialect components in bytecode.
mlir::ParseResult parseEhDispatchDestinations(mlir::OpAsmParser &parser, mlir::ArrayAttr &catchTypes, llvm::SmallVectorImpl< mlir::Block * > &catchDestinations, mlir::Block *&defaultDestination, mlir::UnitAttr &defaultIsCatchAll)
mlir::ParseResult parseOmittedTerminatorRegion(mlir::OpAsmParser &parser, mlir::Region ®ion)
void printCopyTypes(mlir::OpAsmPrinter &printer, mlir::Operation *, mlir::Type srcType, mlir::Type dstType)
mlir::ParseResult parseCopyTypes(mlir::OpAsmParser &parser, mlir::Type &srcType, mlir::Type &dstType)
mlir::Type memberStorageType(mlir::Type memberTy)
The storage a member is stored as: the access unit for a bit-field member, and the member type itself...
void printComdatName(mlir::OpAsmPrinter &p, cir::GlobalOp op, mlir::StringAttr comdat)
mlir::ParseResult parseGlobalOpTypeAndInitialValue(mlir::OpAsmParser &parser, mlir::TypeAttr &typeAttr, mlir::Attribute &initialValueAttr, mlir::Region &ctorRegion, mlir::Region &dtorRegion)
mlir::ParseResult parseSwitchFlatOpCases(mlir::OpAsmParser &parser, mlir::Type flagType, mlir::ArrayAttr &caseValues, llvm::SmallVectorImpl< mlir::Block * > &caseDestinations, llvm::SmallVectorImpl< llvm::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &caseOperands, llvm::SmallVectorImpl< llvm::SmallVector< mlir::Type > > &caseOperandTypes)
bool isValidFundamentalIntWidth(unsigned width)
void buildTerminatedBody(mlir::OpBuilder &builder, mlir::Location loc)
mlir::ParseResult parseAssumeBundle(mlir::OpAsmParser &p, cir::AssumeBundleKindAttr &bundleKindAttr, llvm::SmallVector< mlir::OpAsmParser::UnresolvedOperand, 4 > &bundleArgs, llvm::SmallVector< mlir::Type, 1 > &bundleArgTypes)
mlir::ParseResult parseComdatName(mlir::OpAsmParser &parser, mlir::StringAttr &comdatAttr)
AllocaOp getUnderlyingAlloca(mlir::Value addr)
The alloca that defines addr, looking through casts that preserve the underlying storage.
void printOmittedTerminatorRegion(mlir::OpAsmPrinter &printer, cir::ScopeOp &op, mlir::Region ®ion)
void printTryHandlerRegions(mlir::OpAsmPrinter &printer, cir::TryOp op, mlir::MutableArrayRef< mlir::Region > handlerRegions, mlir::ArrayAttr handlerTypes)
mlir::ptr::MemorySpaceAttrInterface normalizeDefaultAddressSpace(mlir::ptr::MemorySpaceAttrInterface addrSpace)
Normalize LangAddressSpace::Default to null (empty attribute).
void printIndirectBrOpSucessors(mlir::OpAsmPrinter &p, cir::IndirectBrOp op, mlir::Type flagType, mlir::SuccessorRange succs, mlir::OperandRangeRange succOperands, const mlir::TypeRangeRange &succOperandsTypes)
mlir::ParseResult parseTryHandlerRegions(mlir::OpAsmParser &parser, llvm::SmallVectorImpl< std::unique_ptr< mlir::Region > > &handlerRegions, mlir::ArrayAttr &handlerTypes)
mlir::ParseResult parseIndirectBrOpSucessors(mlir::OpAsmParser &parser, mlir::Type &flagType, llvm::SmallVectorImpl< mlir::Block * > &succOperandBlocks, llvm::SmallVectorImpl< llvm::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &succOperands, llvm::SmallVectorImpl< llvm::SmallVector< mlir::Type > > &succOperandsTypes)
void printGlobalOpTypeAndInitialValue(mlir::OpAsmPrinter &p, cir::GlobalOp op, mlir::TypeAttr type, mlir::Attribute initAttr, mlir::Region &ctorRegion, mlir::Region &dtorRegion)
void printEhDispatchDestinations(mlir::OpAsmPrinter &p, cir::EhDispatchOp op, mlir::ArrayAttr catchTypes, mlir::SuccessorRange catchDestinations, mlir::Block *defaultDestination, mlir::UnitAttr defaultIsCatchAll)
void printAssumeBundle(mlir::OpAsmPrinter &p, cir::AssumeOp op, cir::AssumeBundleKindAttr kindAttr, mlir::OperandRange bundleArgs, mlir::TypeRange bundleArgTypes)
void printSwitchFlatOpCases(mlir::OpAsmPrinter &p, cir::SwitchFlatOp op, mlir::Type flagType, mlir::ArrayAttr caseValues, mlir::SuccessorRange caseDestinations, mlir::OperandRangeRange caseOperands, const mlir::TypeRangeRange &caseOperandTypes)
const AstTypeMatcher< BuiltinType > builtinType
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< TypeLoc > typeLoc
Matches TypeLocs in the clang AST.
const AstTypeMatcher< RecordType > recordType
StringRef getName(const HeaderType T)
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 int64_t
static bool memberFuncPtrCast()
static bool opCallCallConv()
static bool opScopeCleanupRegion()
static bool supportIFuncAttr()