19#include "mlir/IR/Attributes.h"
20#include "mlir/IR/BuiltinTypes.h"
21#include "mlir/IR/DialectImplementation.h"
22#include "mlir/IR/PatternMatch.h"
23#include "mlir/IR/Value.h"
24#include "mlir/Interfaces/ControlFlowInterfaces.h"
25#include "mlir/Interfaces/FunctionImplementation.h"
26#include "mlir/Support/LLVM.h"
28#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
29#include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc"
31#include "llvm/ADT/SetOperations.h"
32#include "llvm/ADT/SmallSet.h"
33#include "llvm/ADT/TypeSwitch.h"
34#include "llvm/Support/LogicalResult.h"
43struct CIROpAsmDialectInterface :
public OpAsmDialectInterface {
44 using OpAsmDialectInterface::OpAsmDialectInterface;
46 AliasResult getAlias(Type type, raw_ostream &os)
const final {
47 if (
auto recordType = dyn_cast<cir::RecordType>(type)) {
50 os <<
"rec_anon_" <<
recordType.getKindAsStr();
52 os <<
"rec_" << nameAttr.getValue();
53 return AliasResult::OverridableAlias;
55 if (
auto intType = dyn_cast<cir::IntType>(type)) {
58 unsigned width = intType.getWidth();
59 if (width < 8 || !llvm::isPowerOf2_32(width))
60 return AliasResult::NoAlias;
61 os << intType.getAlias();
62 return AliasResult::OverridableAlias;
64 if (
auto voidType = dyn_cast<cir::VoidType>(type)) {
65 os << voidType.getAlias();
66 return AliasResult::OverridableAlias;
69 return AliasResult::NoAlias;
72 AliasResult getAlias(Attribute attr, raw_ostream &os)
const final {
73 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr)) {
74 os << (boolAttr.getValue() ?
"true" :
"false");
75 return AliasResult::FinalAlias;
77 if (
auto bitfield = mlir::dyn_cast<cir::BitfieldInfoAttr>(attr)) {
78 os <<
"bfi_" << bitfield.getName().str();
79 return AliasResult::FinalAlias;
81 if (
auto dynCastInfoAttr = mlir::dyn_cast<cir::DynamicCastInfoAttr>(attr)) {
82 os << dynCastInfoAttr.getAlias();
83 return AliasResult::FinalAlias;
85 if (
auto cmpThreeWayInfoAttr =
86 mlir::dyn_cast<cir::CmpThreeWayInfoAttr>(attr)) {
87 os << cmpThreeWayInfoAttr.getAlias();
88 return AliasResult::FinalAlias;
90 return AliasResult::NoAlias;
95void cir::CIRDialect::initialize() {
100#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
102 addInterfaces<CIROpAsmDialectInterface>();
105Operation *cir::CIRDialect::materializeConstant(mlir::OpBuilder &builder,
106 mlir::Attribute value,
108 mlir::Location loc) {
109 return cir::ConstantOp::create(builder, loc, type,
110 mlir::cast<mlir::TypedAttr>(value));
122 for (
auto en : llvm::enumerate(keywords)) {
123 if (succeeded(parser.parseOptionalKeyword(en.value())))
130template <
typename Ty>
struct EnumTraits {};
132#define REGISTER_ENUM_TYPE(Ty) \
133 template <> struct EnumTraits<cir::Ty> { \
134 static llvm::StringRef stringify(cir::Ty value) { \
135 return stringify##Ty(value); \
137 static unsigned getMaxEnumVal() { return cir::getMaxEnumValFor##Ty(); } \
149template <
typename EnumTy,
typename RetTy = EnumTy>
152 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
153 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
157 return static_cast<RetTy
>(defaultValue);
158 return static_cast<RetTy
>(index);
162template <
typename EnumTy,
typename RetTy = EnumTy>
165 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
166 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
171 result =
static_cast<RetTy
>(index);
179 Location eLoc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
180 OpBuilder builder(parser.getBuilder().getContext());
185 builder.createBlock(®ion);
187 Block &block = region.back();
189 if (!block.empty() && block.back().hasTrait<OpTrait::IsTerminator>())
193 if (!region.hasOneBlock())
194 return parser.emitError(errLoc,
195 "multi-block region must not omit terminator");
198 builder.setInsertionPointToEnd(&block);
199 cir::YieldOp::create(builder, eLoc);
205 const auto singleNonEmptyBlock = r.hasOneBlock() && !r.back().empty();
206 const auto yieldsNothing = [&r]() {
207 auto y = dyn_cast<cir::YieldOp>(r.back().getTerminator());
208 return y && y.getArgs().empty();
210 return singleNonEmptyBlock && yieldsNothing();
215template <
typename ExpectedProducerOp>
217 StringRef operandName) {
218 Operation *producer = operand.getDefiningOp();
219 if (!producer || !isa<ExpectedProducerOp>(producer))
220 return op->emitOpError()
221 <<
"operand '" << operandName <<
"' must be produced by '"
222 << ExpectedProducerOp::getOperationName() <<
"'";
231 cir::InlineKindAttr &inlineKindAttr) {
233 static constexpr llvm::StringRef keywords[] = {
"no_inline",
"always_inline",
237 llvm::StringRef keyword;
238 if (parser.parseOptionalKeyword(&keyword, keywords).failed()) {
244 auto inlineKindResult = ::cir::symbolizeEnum<::cir::InlineKind>(keyword);
245 if (!inlineKindResult) {
246 return parser.emitError(parser.getCurrentLocation(),
"expected one of [")
248 <<
"] for inlineKind, got: " << keyword;
252 ::cir::InlineKindAttr::get(parser.getContext(), *inlineKindResult);
257 if (inlineKindAttr) {
258 p <<
" " << stringifyInlineKind(inlineKindAttr.getValue());
267 mlir::Region ®ion) {
268 auto regionLoc = parser.getCurrentLocation();
269 if (parser.parseRegion(region))
278 mlir::Region ®ion) {
279 printer.printRegion(region,
284mlir::OptionalParseResult
286 mlir::ptr::MemorySpaceAttrInterface &attr);
289 mlir::ptr::MemorySpaceAttrInterface attr);
295void cir::AllocaOp::build(mlir::OpBuilder &odsBuilder,
296 mlir::OperationState &odsState, mlir::Type addr,
297 llvm::StringRef name, mlir::IntegerAttr alignment) {
298 odsState.addAttribute(getNameAttrName(odsState.name),
299 odsBuilder.getStringAttr(name));
301 odsState.addAttribute(getAlignmentAttrName(odsState.name), alignment);
303 odsState.addTypes(addr);
311 auto ptrTy = mlir::cast<cir::PointerType>(op.getAddr().getType());
312 mlir::Type pointeeTy = ptrTy.getPointee();
314 mlir::Block &body = op.getBody().front();
315 if (body.getNumArguments() != 1)
316 return op.emitOpError(
"body must have exactly one block argument");
318 auto expectedEltPtrTy =
319 mlir::dyn_cast<cir::PointerType>(body.getArgument(0).getType());
320 if (!expectedEltPtrTy)
321 return op.emitOpError(
"block argument must be a !cir.ptr type");
323 if (op.getNumElements()) {
324 auto recTy = mlir::dyn_cast<cir::RecordType>(pointeeTy);
326 return op.emitOpError(
327 "when 'num_elements' is present, 'addr' must be a pointer to a "
328 "!cir.struct or !cir.union type");
330 if (expectedEltPtrTy != ptrTy)
331 return op.emitOpError(
"when 'num_elements' is present, 'addr' type must "
332 "match the block argument type");
334 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(pointeeTy);
336 return op.emitOpError(
337 "when 'num_elements' is absent, 'addr' must be a pointer to a "
340 mlir::Type innerEltTy = arrayTy.getElementType();
341 while (
auto nested = mlir::dyn_cast<cir::ArrayType>(innerEltTy))
342 innerEltTy = nested.getElementType();
344 auto recTy = mlir::dyn_cast<cir::RecordType>(innerEltTy);
346 return op.emitOpError(
"the block argument type must be a pointer to a "
347 "!cir.struct or !cir.union type");
349 if (expectedEltPtrTy.getPointee() != innerEltTy)
350 return op.emitOpError(
351 "block argument pointee type must match the innermost array "
358LogicalResult cir::ArrayCtor::verify() {
362 mlir::Region &partialDtor = getPartialDtor();
363 if (!partialDtor.empty()) {
364 mlir::Block &dtorBlock = partialDtor.front();
365 if (dtorBlock.getNumArguments() != 1)
366 return emitOpError(
"partial_dtor must have exactly one block argument");
368 auto bodyArgTy = getBody().front().getArgument(0).getType();
369 if (dtorBlock.getArgument(0).getType() != bodyArgTy)
370 return emitOpError(
"partial_dtor block argument type must match "
371 "the body block argument type");
381LogicalResult cir::DeleteArrayOp::verify() {
382 if (getDtorMayThrow() && !getElementDtorAttr())
384 "'dtor_may_throw' requires an 'element_dtor' to be present");
393 cir::AssumeBundleKindAttr kindAttr,
394 OperandRange bundleArgs,
395 TypeRange bundleArgTypes) {
396 cir::AssumeBundleKind
kind = kindAttr.getValue();
397 if (
kind == cir::AssumeBundleKind::None)
400 p <<
" " << cir::stringifyAssumeBundleKind(
kind);
401 if (bundleArgs.empty())
405 p.printOperands(bundleArgs);
407 llvm::interleaveComma(bundleArgTypes, p);
412 OpAsmParser &p, cir::AssumeBundleKindAttr &bundleKindAttr,
416 auto loc = p.getCurrentLocation();
417 if (failed(p.parseOptionalKeyword(&keyword))) {
418 bundleKindAttr = cir::AssumeBundleKindAttr::get(
419 p.getContext(), cir::AssumeBundleKind::None);
423 std::optional<cir::AssumeBundleKind> parsedKind =
424 cir::symbolizeAssumeBundleKind(keyword);
426 return p.emitError(loc,
"unknown assume bundle kind '") << keyword <<
"'";
428 bundleKindAttr = cir::AssumeBundleKindAttr::get(p.getContext(), *parsedKind);
430 if (p.parseOptionalLParen())
433 if (p.parseOperandList(bundleArgs) || p.parseColon() ||
434 p.parseTypeList(bundleArgTypes) || p.parseRParen())
440LogicalResult cir::AssumeOp::verify() {
441 cir::AssumeBundleKind
kind = getBundleKind();
442 size_t numArgs = getBundleArgs().size();
444 if (
kind == cir::AssumeBundleKind::None) {
446 return emitOpError(
"unexpected bundle operands for kind 'none'");
451 return emitOpError(
"expected bundle operands for kind '")
452 << cir::stringifyAssumeBundleKind(
kind) <<
"'";
455 case cir::AssumeBundleKind::Align:
456 if (numArgs != 2 && numArgs != 3)
457 return emitOpError(
"align bundle expects 2 or 3 operands");
459 case cir::AssumeBundleKind::SeparateStorage:
461 return emitOpError(
"separate_storage bundle expects 2 operands");
463 case cir::AssumeBundleKind::Dereferenceable:
465 return emitOpError(
"dereferenceable bundle expects 2 operands");
478cir::LocalInitOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
479 cir::GlobalOp global = getReferencedGlobal(symbolTable);
481 return emitOpError(
"'")
482 << getGlobalName() <<
"' does not reference a valid cir.global";
484 if (getTls() && !global.getTlsModel())
485 return emitOpError(
"access to global not marked thread local");
487 if (!global.getStaticLocalGuard().has_value())
488 return emitOpError(
"static_local attribute mismatch");
501void cir::ConditionOp::getSuccessorRegions(
508 if (
auto loopOp = dyn_cast<LoopOpInterface>(getOperation()->getParentOp())) {
509 regions.emplace_back(&loopOp.getBody());
510 if (mlir::Region *cleanup = loopOp.maybeGetCleanup())
511 regions.emplace_back(cleanup);
513 regions.emplace_back(getOperation());
518 auto await = cast<AwaitOp>(getOperation()->getParentOp());
519 regions.emplace_back(&await.getResume());
520 regions.emplace_back(&await.getSuspend());
524cir::ConditionOp::getMutableSuccessorOperands(RegionSuccessor point) {
526 return MutableOperandRange(getOperation(), 0, 0);
530cir::ResumeOp::getMutableSuccessorOperands(RegionSuccessor point) {
532 return MutableOperandRange(getOperation(), 0, 0);
535LogicalResult cir::ConditionOp::verify() {
536 if (!isa<LoopOpInterface, AwaitOp>(getOperation()->getParentOp()))
537 return emitOpError(
"condition must be within a conditional region");
545template <
typename LoopOpTy>
547 std::optional<cir::CleanupKind> cleanupKind = op.getCleanupKind();
551 if (cleanupKind.has_value() == op.getCleanup().empty())
552 return op.emitOpError(
"cleanup kind must be present if and only if the "
553 "cleanup region is non-empty");
558 if (cleanupKind == cir::CleanupKind::EH)
559 return op.emitOpError(
"loop cleanup kind must be 'normal' or 'all', "
574 mlir::Attribute attrType) {
575 if (isa<cir::ConstPtrAttr>(attrType)) {
576 if (!mlir::isa<cir::PointerType>(opType))
577 return op->emitOpError(
578 "pointer constant initializing a non-pointer type");
582 if (isa<cir::DataMemberAttr, cir::DataMemberOffsetAttr, cir::MethodAttr>(
589 if (isa<cir::ZeroAttr>(attrType)) {
590 if (isa<cir::RecordType, cir::ArrayType, cir::VectorType, cir::ComplexType>(
593 return op->emitOpError(
594 "zero expects struct, array, vector, or complex type");
597 if (mlir::isa<cir::UndefAttr>(attrType)) {
598 if (!mlir::isa<cir::VoidType>(opType))
600 return op->emitOpError(
"undef expects non-void type");
603 if (mlir::isa<cir::BoolAttr>(attrType)) {
604 if (!mlir::isa<cir::BoolType>(opType))
605 return op->emitOpError(
"result type (")
606 << opType <<
") must be '!cir.bool' for '" << attrType <<
"'";
610 if (mlir::isa<cir::IntAttr, cir::FPAttr>(attrType)) {
611 auto at = cast<TypedAttr>(attrType);
612 if (at.getType() != opType) {
613 return op->emitOpError(
"result type (")
614 << opType <<
") does not match value type (" << at.getType()
620 if (mlir::isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr,
621 cir::ConstArrayAttr, cir::ConstVectorAttr,
622 cir::ConstComplexAttr, cir::ConstRecordAttr,
623 cir::GlobalViewAttr, cir::PoisonAttr, cir::TypeInfoAttr,
624 cir::VTableAttr>(attrType))
627 assert(isa<TypedAttr>(attrType) &&
"What else could we be looking at here?");
628 return op->emitOpError(
"global with type ")
629 << cast<TypedAttr>(attrType).getType() <<
" not yet supported";
632LogicalResult cir::ConstantOp::verify() {
639OpFoldResult cir::ConstantOp::fold(FoldAdaptor ) {
649 case cir::CastKind::floating:
650 case cir::CastKind::int_to_float:
651 case cir::CastKind::float_to_int:
652 case cir::CastKind::float_to_bool:
653 case cir::CastKind::bool_to_float:
654 case cir::CastKind::float_to_complex:
655 case cir::CastKind::float_complex_to_real:
656 case cir::CastKind::float_complex_to_bool:
657 case cir::CastKind::float_complex:
658 case cir::CastKind::float_complex_to_int_complex:
659 case cir::CastKind::int_complex_to_float_complex:
666LogicalResult cir::CastOp::verify() {
667 mlir::Type resType =
getType();
668 mlir::Type srcType = getSrc().getType();
673 <<
"'fenv' is only valid for floating-point cast kinds";
677 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
678 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
679 if (srcPtrTy && resPtrTy && (
kind != cir::CastKind::address_space))
680 if (srcPtrTy.getAddrSpace() != resPtrTy.getAddrSpace()) {
681 return emitOpError() <<
"result type address space does not match the "
682 "address space of the operand";
685 auto srcVTy = mlir::dyn_cast<cir::VectorType>(srcType);
686 auto resVTy = mlir::dyn_cast<cir::VectorType>(resType);
687 if (srcVTy && resVTy) {
688 if ((
kind == cir::CastKind::int_to_float ||
689 kind == cir::CastKind::float_to_int) &&
690 srcVTy.getSize() != resVTy.getSize()) {
692 <<
"vector float-to-int and int-to-float casts require "
693 "source and destination vectors to have the same number of "
698 srcType = srcVTy.getElementType();
699 resType = resVTy.getElementType();
703 case cir::CastKind::int_to_bool: {
704 if (!mlir::isa<cir::BoolType>(resType))
705 return emitOpError() <<
"requires !cir.bool type for result";
706 if (!mlir::isa<cir::IntType>(srcType))
707 return emitOpError() <<
"requires !cir.int type for source";
710 case cir::CastKind::ptr_to_bool: {
711 if (!mlir::isa<cir::BoolType>(resType))
712 return emitOpError() <<
"requires !cir.bool type for result";
713 if (!mlir::isa<cir::PointerType>(srcType))
714 return emitOpError() <<
"requires !cir.ptr type for source";
717 case cir::CastKind::integral: {
718 if (!mlir::isa<cir::IntType>(resType))
719 return emitOpError() <<
"requires !cir.int type for result";
720 if (!mlir::isa<cir::IntType>(srcType))
721 return emitOpError() <<
"requires !cir.int type for source";
724 case cir::CastKind::array_to_ptrdecay: {
725 const auto arrayPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
726 const auto flatPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
727 if (!arrayPtrTy || !flatPtrTy)
728 return emitOpError() <<
"requires !cir.ptr type for source and result";
733 case cir::CastKind::bitcast: {
735 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
736 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
738 if (srcPtrTy && resPtrTy) {
744 case cir::CastKind::floating: {
745 if (!mlir::isa<cir::FPTypeInterface>(srcType) ||
746 !mlir::isa<cir::FPTypeInterface>(resType))
747 return emitOpError() <<
"requires !cir.float type for source and result";
750 case cir::CastKind::float_to_int: {
751 if (!mlir::isa<cir::FPTypeInterface>(srcType))
752 return emitOpError() <<
"requires !cir.float type for source";
753 if (!mlir::dyn_cast<cir::IntType>(resType))
754 return emitOpError() <<
"requires !cir.int type for result";
757 case cir::CastKind::int_to_ptr: {
758 if (!mlir::dyn_cast<cir::IntType>(srcType))
759 return emitOpError() <<
"requires !cir.int type for source";
760 if (!mlir::dyn_cast<cir::PointerType>(resType))
761 return emitOpError() <<
"requires !cir.ptr type for result";
764 case cir::CastKind::ptr_to_int: {
765 if (!mlir::dyn_cast<cir::PointerType>(srcType))
766 return emitOpError() <<
"requires !cir.ptr type for source";
767 if (!mlir::dyn_cast<cir::IntType>(resType))
768 return emitOpError() <<
"requires !cir.int type for result";
771 case cir::CastKind::float_to_bool: {
772 if (!mlir::isa<cir::FPTypeInterface>(srcType))
773 return emitOpError() <<
"requires !cir.float type for source";
774 if (!mlir::isa<cir::BoolType>(resType))
775 return emitOpError() <<
"requires !cir.bool type for result";
778 case cir::CastKind::bool_to_int: {
779 if (!mlir::isa<cir::BoolType>(srcType))
780 return emitOpError() <<
"requires !cir.bool type for source";
781 if (!mlir::isa<cir::IntType>(resType))
782 return emitOpError() <<
"requires !cir.int type for result";
785 case cir::CastKind::int_to_float: {
786 if (!mlir::isa<cir::IntType>(srcType))
787 return emitOpError() <<
"requires !cir.int type for source";
788 if (!mlir::isa<cir::FPTypeInterface>(resType))
789 return emitOpError() <<
"requires !cir.float type for result";
792 case cir::CastKind::bool_to_float: {
793 if (!mlir::isa<cir::BoolType>(srcType))
794 return emitOpError() <<
"requires !cir.bool type for source";
795 if (!mlir::isa<cir::FPTypeInterface>(resType))
796 return emitOpError() <<
"requires !cir.float type for result";
799 case cir::CastKind::address_space: {
800 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
801 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
802 if (!srcPtrTy || !resPtrTy)
803 return emitOpError() <<
"requires !cir.ptr type for source and result";
804 if (srcPtrTy.getPointee() != resPtrTy.getPointee())
805 return emitOpError() <<
"requires two types differ in addrspace only";
808 case cir::CastKind::float_to_complex: {
809 if (!mlir::isa<cir::FPTypeInterface>(srcType))
810 return emitOpError() <<
"requires !cir.float type for source";
811 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
813 return emitOpError() <<
"requires !cir.complex type for result";
814 if (srcType != resComplexTy.getElementType())
815 return emitOpError() <<
"requires source type match result element type";
818 case cir::CastKind::int_to_complex: {
819 if (!mlir::isa<cir::IntType>(srcType))
820 return emitOpError() <<
"requires !cir.int type for source";
821 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
823 return emitOpError() <<
"requires !cir.complex type for result";
824 if (srcType != resComplexTy.getElementType())
825 return emitOpError() <<
"requires source type match result element type";
828 case cir::CastKind::float_complex_to_real: {
829 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
831 return emitOpError() <<
"requires !cir.complex type for source";
832 if (!mlir::isa<cir::FPTypeInterface>(resType))
833 return emitOpError() <<
"requires !cir.float type for result";
834 if (srcComplexTy.getElementType() != resType)
835 return emitOpError() <<
"requires source element type match result type";
838 case cir::CastKind::int_complex_to_real: {
839 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
841 return emitOpError() <<
"requires !cir.complex type for source";
842 if (!mlir::isa<cir::IntType>(resType))
843 return emitOpError() <<
"requires !cir.int type for result";
844 if (srcComplexTy.getElementType() != resType)
845 return emitOpError() <<
"requires source element type match result type";
848 case cir::CastKind::float_complex_to_bool: {
849 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
850 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
852 <<
"requires floating point !cir.complex type for source";
853 if (!mlir::isa<cir::BoolType>(resType))
854 return emitOpError() <<
"requires !cir.bool type for result";
857 case cir::CastKind::int_complex_to_bool: {
858 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
859 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
861 <<
"requires floating point !cir.complex type for source";
862 if (!mlir::isa<cir::BoolType>(resType))
863 return emitOpError() <<
"requires !cir.bool type for result";
866 case cir::CastKind::float_complex: {
867 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
868 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
870 <<
"requires floating point !cir.complex type for source";
871 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
872 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
874 <<
"requires floating point !cir.complex type for result";
877 case cir::CastKind::float_complex_to_int_complex: {
878 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
879 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
881 <<
"requires floating point !cir.complex type for source";
882 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
883 if (!resComplexTy || !resComplexTy.isIntegerComplex())
884 return emitOpError() <<
"requires integer !cir.complex type for result";
887 case cir::CastKind::int_complex: {
888 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
889 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
890 return emitOpError() <<
"requires integer !cir.complex type for source";
891 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
892 if (!resComplexTy || !resComplexTy.isIntegerComplex())
893 return emitOpError() <<
"requires integer !cir.complex type for result";
896 case cir::CastKind::int_complex_to_float_complex: {
897 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
898 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
899 return emitOpError() <<
"requires integer !cir.complex type for source";
900 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
901 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
903 <<
"requires floating point !cir.complex type for result";
906 case cir::CastKind::member_ptr_to_bool: {
907 if (!mlir::isa<cir::DataMemberType, cir::MethodType>(srcType))
909 <<
"requires !cir.data_member or !cir.method type for source";
910 if (!mlir::isa<cir::BoolType>(resType))
911 return emitOpError() <<
"requires !cir.bool type for result";
915 llvm_unreachable(
"Unknown CastOp kind?");
919 auto kind = op.getKind();
920 return kind == cir::CastKind::bool_to_int ||
921 kind == cir::CastKind::int_to_bool ||
kind == cir::CastKind::integral;
925 const auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty);
926 return ptrTy && mlir::isa<cir::FuncType>(ptrTy.getPointee());
930 cir::CastOp head = op, tail = op;
936 op = head.getSrc().getDefiningOp<cir::CastOp>();
942 if (head.getKind() == cir::CastKind::bool_to_int &&
943 tail.getKind() == cir::CastKind::int_to_bool)
944 return head.getSrc();
949 if (head.getKind() == cir::CastKind::int_to_bool &&
950 tail.getKind() == cir::CastKind::int_to_bool)
951 return head.getResult();
959 if (tail.getKind() == cir::CastKind::bitcast) {
960 auto *inner = tail.getSrc().getDefiningOp();
962 auto innerCast = mlir::dyn_cast<cir::CastOp>(inner);
963 if (innerCast && innerCast.getKind() == cir::CastKind::bitcast &&
964 innerCast.getSrc().getType() == tail.getType() &&
965 innerCast.getType() == tail.getSrc().getType()) {
966 return innerCast.getSrc();
974OpFoldResult cir::CastOp::fold(FoldAdaptor adaptor) {
975 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getSrc())) {
977 return cir::PoisonAttr::get(getContext(),
getType());
981 if (mlir::isa_and_present<cir::UndefAttr>(adaptor.getSrc()))
982 return cir::UndefAttr::get(
getType());
986 case cir::CastKind::integral: {
988 auto foldOrder = getSrc().getDefiningOp()->fold(foldResults);
989 if (foldOrder.succeeded() && mlir::isa<mlir::Attribute>(foldResults[0]))
990 return mlir::cast<mlir::Attribute>(foldResults[0]);
993 case cir::CastKind::bitcast:
994 case cir::CastKind::address_space:
995 case cir::CastKind::float_complex:
996 case cir::CastKind::int_complex: {
1010 if (
auto srcConst = getSrc().getDefiningOp<cir::ConstantOp>()) {
1012 case cir::CastKind::integral: {
1013 mlir::Type srcTy = getSrc().getType();
1015 assert(mlir::isa<cir::VectorType>(srcTy) ==
1016 mlir::isa<cir::VectorType>(
getType()));
1017 if (mlir::isa<cir::VectorType>(srcTy))
1020 auto srcIntTy = mlir::cast<cir::IntType>(srcTy);
1021 auto dstIntTy = mlir::cast<cir::IntType>(
getType());
1022 auto constIntAttr = srcConst.getValueAttr<cir::IntAttr>();
1026 APInt srcValue = constIntAttr.getValue();
1027 APInt newVal = srcIntTy.isSigned()
1028 ? srcValue.sextOrTrunc(dstIntTy.getWidth())
1029 : srcValue.zextOrTrunc(dstIntTy.getWidth());
1030 return cir::IntAttr::get(dstIntTy, newVal);
1043LogicalResult cir::BuiltinIntCastOp::verify() {
1044 mlir::Type srcType = getSrc().getType();
1045 mlir::Type resType =
getType();
1047 auto srcCirInt = mlir::dyn_cast<cir::IntType>(srcType);
1048 auto resCirInt = mlir::dyn_cast<cir::IntType>(resType);
1052 if (
static_cast<bool>(srcCirInt) ==
static_cast<bool>(resCirInt))
1053 return emitOpError()
1054 <<
"requires exactly one '!cir.int' operand or result; the other "
1055 "must be a builtin integer or 'index' type";
1057 mlir::Type
builtinType = srcCirInt ? resType : srcType;
1058 if (!mlir::isa<mlir::IntegerType, mlir::IndexType>(builtinType))
1059 return emitOpError() <<
"requires a builtin integer or 'index' type on the "
1064 if (
auto builtinInt = mlir::dyn_cast<mlir::IntegerType>(builtinType)) {
1065 cir::IntType cirInt = srcCirInt ? srcCirInt : resCirInt;
1066 if (cirInt.getWidth() != builtinInt.getWidth())
1067 return emitOpError()
1068 <<
"requires the CIR and builtin integer types to have the same "
1069 "width; use 'cir.cast' for width conversions";
1075OpFoldResult cir::BuiltinIntCastOp::fold(FoldAdaptor adaptor) {
1078 if (
auto inner = getSrc().getDefiningOp<cir::BuiltinIntCastOp>())
1079 if (inner.getSrc().getType() ==
getType())
1080 return inner.getSrc();
1088mlir::OperandRange cir::CallOp::getArgOperands() {
1090 return getArgs().drop_front(1);
1094mlir::MutableOperandRange cir::CallOp::getArgOperandsMutable() {
1095 mlir::MutableOperandRange args = getArgsMutable();
1097 return args.slice(1, args.size() - 1);
1101mlir::Value cir::CallOp::getIndirectCall() {
1102 assert(isIndirect());
1103 return getOperand(0);
1107Value cir::CallOp::getArgOperand(
unsigned i) {
1110 return getOperand(i);
1114unsigned cir::CallOp::getNumArgOperands() {
1116 return this->getOperation()->getNumOperands() - 1;
1117 return this->getOperation()->getNumOperands();
1120static mlir::ParseResult
1122 mlir::OperationState &result) {
1123 mlir::Block *normalDestSuccessor;
1124 if (parser.parseSuccessor(normalDestSuccessor))
1125 return mlir::failure();
1127 if (parser.parseComma())
1128 return mlir::failure();
1130 mlir::Block *unwindDestSuccessor;
1131 if (parser.parseSuccessor(unwindDestSuccessor))
1132 return mlir::failure();
1134 result.addSuccessors(normalDestSuccessor);
1135 result.addSuccessors(unwindDestSuccessor);
1136 return mlir::success();
1140 mlir::OperationState &result,
1141 bool hasDestinationBlocks =
false) {
1144 mlir::FlatSymbolRefAttr calleeAttr;
1148 .parseOptionalAttribute(calleeAttr, CIRDialect::getCalleeAttrName(),
1151 OpAsmParser::UnresolvedOperand indirectVal;
1153 if (parser.parseOperand(indirectVal).failed())
1155 ops.push_back(indirectVal);
1158 if (parser.parseLParen())
1159 return mlir::failure();
1161 opsLoc = parser.getCurrentLocation();
1162 if (parser.parseOperandList(ops))
1163 return mlir::failure();
1164 if (parser.parseRParen())
1165 return mlir::failure();
1167 if (hasDestinationBlocks &&
1169 return ::mlir::failure();
1172 if (parser.parseOptionalKeyword(
"musttail").succeeded())
1173 result.addAttribute(CIRDialect::getMustTailAttrName(),
1174 mlir::UnitAttr::get(parser.getContext()));
1176 if (parser.parseOptionalKeyword(
"nothrow").succeeded())
1177 result.addAttribute(CIRDialect::getNoThrowAttrName(),
1178 mlir::UnitAttr::get(parser.getContext()));
1180 if (parser.parseOptionalKeyword(
"side_effect").succeeded()) {
1181 if (parser.parseLParen().failed())
1183 cir::SideEffect sideEffect;
1186 if (parser.parseRParen().failed())
1188 auto attr = cir::SideEffectAttr::get(parser.getContext(), sideEffect);
1189 result.addAttribute(CIRDialect::getSideEffectAttrName(), attr);
1192 if (parser.parseOptionalAttrDict(result.attributes))
1193 return ::mlir::failure();
1195 if (parser.parseColon())
1196 return ::mlir::failure();
1202 if (call_interface_impl::parseFunctionSignature(parser, argTypes, argAttrs,
1203 resultTypes, resultAttrs))
1204 return mlir::failure();
1206 if (resultTypes.size() > 1 || resultAttrs.size() > 1)
1207 return parser.emitError(
1208 parser.getCurrentLocation(),
1209 "functions with multiple return types are not supported");
1211 result.addTypes(resultTypes);
1213 if (parser.resolveOperands(ops, argTypes, opsLoc, result.operands))
1214 return mlir::failure();
1216 if (!resultAttrs.empty() && resultAttrs[0])
1217 result.addAttribute(
1218 CIRDialect::getResAttrsAttrName(),
1219 mlir::ArrayAttr::get(parser.getContext(), {resultAttrs[0]}));
1224 bool argAttrsEmpty =
true;
1226 llvm::transform(argAttrs, std::back_inserter(convertedArgAttrs),
1227 [&](DictionaryAttr da) -> mlir::Attribute {
1229 argAttrsEmpty =
false;
1233 if (!argAttrsEmpty) {
1238 argAttrsRef = argAttrsRef.drop_front();
1240 result.addAttribute(CIRDialect::getArgAttrsAttrName(),
1241 mlir::ArrayAttr::get(parser.getContext(), argAttrsRef));
1244 return mlir::success();
1249 mlir::Value indirectCallee, mlir::OpAsmPrinter &printer,
1250 bool isNothrow, cir::SideEffect sideEffect, ArrayAttr argAttrs,
1251 ArrayAttr resAttrs, mlir::Block *normalDest =
nullptr,
1252 mlir::Block *unwindDest =
nullptr) {
1255 auto callLikeOp = mlir::cast<cir::CIRCallOpInterface>(op);
1256 auto ops = callLikeOp.getArgOperands();
1260 printer.printAttributeWithoutType(calleeSym);
1263 assert(indirectCallee);
1264 printer << indirectCallee;
1267 printer <<
"(" << ops <<
")";
1270 assert(unwindDest &&
"expected two successors");
1271 auto tryCall = cast<cir::TryCallOp>(op);
1272 printer <<
' ' << tryCall.getNormalDest();
1275 printer << tryCall.getUnwindDest();
1278 if (op->hasAttr(CIRDialect::getMustTailAttrName()))
1279 printer <<
" musttail";
1282 printer <<
" nothrow";
1284 if (sideEffect != cir::SideEffect::All) {
1285 printer <<
" side_effect(";
1286 printer << stringifySideEffect(sideEffect);
1291 CIRDialect::getCalleeAttrName(),
1292 CIRDialect::getMustTailAttrName(),
1293 CIRDialect::getNoThrowAttrName(),
1294 CIRDialect::getSideEffectAttrName(),
1295 CIRDialect::getOperandSegmentSizesAttrName(),
1296 llvm::StringRef(
"res_attrs"),
1297 llvm::StringRef(
"arg_attrs")};
1298 printer.printOptionalAttrDict(op->getAttrs(), elidedAttrs);
1300 if (calleeSym || !argAttrs) {
1301 call_interface_impl::printFunctionSignature(
1302 printer, op->getOperands().getTypes(), argAttrs,
1303 false, op->getResultTypes(), resAttrs);
1311 shimmedArgAttrs.push_back(mlir::DictionaryAttr::get(op->getContext(), {}));
1312 shimmedArgAttrs.append(argAttrs.begin(), argAttrs.end());
1313 call_interface_impl::printFunctionSignature(
1314 printer, op->getOperands().getTypes(),
1315 mlir::ArrayAttr::get(op->getContext(), shimmedArgAttrs),
1316 false, op->getResultTypes(), resAttrs);
1320mlir::ParseResult cir::CallOp::parse(mlir::OpAsmParser &parser,
1321 mlir::OperationState &result) {
1325void cir::CallOp::print(mlir::OpAsmPrinter &p) {
1326 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
1327 cir::SideEffect sideEffect = getSideEffect();
1328 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
1329 sideEffect, getArgAttrsAttr(), getResAttrsAttr());
1334 SymbolTableCollection &symbolTable) {
1336 op->getAttrOfType<FlatSymbolRefAttr>(CIRDialect::getCalleeAttrName());
1339 return mlir::success();
1342 auto fn = symbolTable.lookupNearestSymbolFrom<cir::FuncOp>(op, fnAttr);
1344 return op->emitOpError() <<
"'" << fnAttr.getValue()
1345 <<
"' does not reference a valid function";
1347 auto callIf = dyn_cast<cir::CIRCallOpInterface>(op);
1348 assert(callIf &&
"expected CIR call interface to be always available");
1352 auto fnType = fn.getFunctionType();
1353 if (!fn.getNoProto()) {
1354 unsigned numCallOperands = callIf.getNumArgOperands();
1355 unsigned numFnOpOperands = fnType.getNumInputs();
1357 if (!fnType.isVarArg() && numCallOperands != numFnOpOperands)
1358 return op->emitOpError(
"incorrect number of operands for callee");
1359 if (fnType.isVarArg() && numCallOperands < numFnOpOperands)
1360 return op->emitOpError(
"too few operands for callee");
1362 for (
unsigned i = 0, e = numFnOpOperands; i != e; ++i)
1363 if (callIf.getArgOperand(i).getType() != fnType.getInput(i))
1364 return op->emitOpError(
"operand type mismatch: expected operand type ")
1365 << fnType.getInput(i) <<
", but provided "
1366 << op->getOperand(i).getType() <<
" for operand number " << i;
1372 if (fnType.hasVoidReturn() && op->getNumResults() != 0)
1373 return op->emitOpError(
"callee returns void but call has results");
1376 if (!fnType.hasVoidReturn() && op->getNumResults() != 1)
1377 return op->emitOpError(
"incorrect number of results for callee");
1380 if (!fnType.hasVoidReturn() &&
1381 op->getResultTypes().front() != fnType.getReturnType()) {
1382 return op->emitOpError(
"result type mismatch: expected ")
1383 << fnType.getReturnType() <<
", but provided "
1384 << op->getResult(0).getType();
1387 return mlir::success();
1391cir::CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1399mlir::OperandRange cir::TryCallOp::getArgOperands() {
1401 return getArgs().drop_front(1);
1405mlir::MutableOperandRange cir::TryCallOp::getArgOperandsMutable() {
1406 mlir::MutableOperandRange args = getArgsMutable();
1408 return args.slice(1, args.size() - 1);
1412mlir::Value cir::TryCallOp::getIndirectCall() {
1413 assert(isIndirect());
1414 return getOperand(0);
1418Value cir::TryCallOp::getArgOperand(
unsigned i) {
1421 return getOperand(i);
1425unsigned cir::TryCallOp::getNumArgOperands() {
1427 return this->getOperation()->getNumOperands() - 1;
1428 return this->getOperation()->getNumOperands();
1432cir::TryCallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1436mlir::ParseResult cir::TryCallOp::parse(mlir::OpAsmParser &parser,
1437 mlir::OperationState &result) {
1441void cir::TryCallOp::print(::mlir::OpAsmPrinter &p) {
1442 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
1443 cir::SideEffect sideEffect = getSideEffect();
1444 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
1445 sideEffect, getArgAttrsAttr(), getResAttrsAttr(),
1446 getNormalDest(), getUnwindDest());
1454 cir::FuncOp function) {
1456 if (op.getNumOperands() > 1)
1457 return op.emitOpError() <<
"expects at most 1 return operand";
1460 auto expectedTy = function.getFunctionType().getReturnType();
1462 (op.getNumOperands() == 0 ? cir::VoidType::get(op.getContext())
1463 : op.getOperand(0).getType());
1464 if (actualTy != expectedTy)
1465 return op.emitOpError() <<
"returns " << actualTy
1466 <<
" but enclosing function returns " << expectedTy;
1468 return mlir::success();
1471mlir::LogicalResult cir::ReturnOp::verify() {
1474 auto *fnOp = getOperation()->getParentOp();
1475 while (!isa<cir::FuncOp>(fnOp))
1476 fnOp = fnOp->getParentOp();
1489ParseResult cir::IfOp::parse(OpAsmParser &parser, OperationState &result) {
1491 result.regions.reserve(2);
1492 Region *thenRegion = result.addRegion();
1493 Region *elseRegion = result.addRegion();
1495 mlir::Builder &builder = parser.getBuilder();
1496 OpAsmParser::UnresolvedOperand cond;
1497 Type boolType = cir::BoolType::get(builder.getContext());
1499 if (parser.parseOperand(cond) ||
1500 parser.resolveOperand(cond, boolType, result.operands))
1504 mlir::SMLoc parseThenLoc = parser.getCurrentLocation();
1505 if (parser.parseRegion(*thenRegion, {}, {}))
1512 if (!parser.parseOptionalKeyword(
"else")) {
1513 mlir::SMLoc parseElseLoc = parser.getCurrentLocation();
1514 if (parser.parseRegion(*elseRegion, {}, {}))
1521 if (parser.parseOptionalAttrDict(result.attributes))
1526void cir::IfOp::print(OpAsmPrinter &p) {
1527 p <<
" " << getCondition() <<
" ";
1528 mlir::Region &thenRegion = this->getThenRegion();
1529 p.printRegion(thenRegion,
1534 mlir::Region &elseRegion = this->getElseRegion();
1535 if (!elseRegion.empty()) {
1537 p.printRegion(elseRegion,
1542 p.printOptionalAttrDict(getOperation()->getAttrs());
1548 cir::YieldOp::create(builder, loc);
1556void cir::IfOp::getSuccessorRegions(mlir::RegionBranchPoint point,
1557 SmallVectorImpl<RegionSuccessor> ®ions) {
1559 if (!point.isParent()) {
1560 regions.emplace_back(getOperation());
1565 Region *elseRegion = &this->getElseRegion();
1566 if (elseRegion->empty())
1567 elseRegion =
nullptr;
1570 regions.push_back(RegionSuccessor(&getThenRegion()));
1572 regions.push_back(RegionSuccessor(elseRegion));
1574 regions.emplace_back(getOperation());
1577mlir::ValueRange cir::IfOp::getSuccessorInputs(RegionSuccessor successor) {
1578 return successor.isOperation() ? ValueRange(getOperation()->getResults())
1582void cir::IfOp::build(OpBuilder &builder, OperationState &result,
Value cond,
1585 assert(thenBuilder &&
"the builder callback for 'then' must be present");
1586 result.addOperands(cond);
1588 OpBuilder::InsertionGuard guard(builder);
1589 Region *thenRegion = result.addRegion();
1590 builder.createBlock(thenRegion);
1591 thenBuilder(builder, result.location);
1593 Region *elseRegion = result.addRegion();
1594 if (!withElseRegion)
1597 builder.createBlock(elseRegion);
1598 elseBuilder(builder, result.location);
1610void cir::ScopeOp::getSuccessorRegions(
1611 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1613 if (!point.isParent()) {
1614 regions.emplace_back(getOperation());
1619 regions.push_back(RegionSuccessor(&getScopeRegion()));
1622mlir::ValueRange cir::ScopeOp::getSuccessorInputs(RegionSuccessor successor) {
1623 return successor.isOperation() ? ValueRange(getOperation()->getResults())
1627void cir::ScopeOp::build(
1628 OpBuilder &builder, OperationState &result,
1629 function_ref<
void(OpBuilder &, Type &, Location)> scopeBuilder) {
1630 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1632 OpBuilder::InsertionGuard guard(builder);
1633 Region *scopeRegion = result.addRegion();
1634 builder.createBlock(scopeRegion);
1638 scopeBuilder(builder, yieldTy, result.location);
1641 result.addTypes(TypeRange{yieldTy});
1644void cir::ScopeOp::build(
1645 OpBuilder &builder, OperationState &result,
1646 function_ref<
void(OpBuilder &, Location)> scopeBuilder) {
1647 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1648 OpBuilder::InsertionGuard guard(builder);
1649 Region *scopeRegion = result.addRegion();
1650 builder.createBlock(scopeRegion);
1652 scopeBuilder(builder, result.location);
1655LogicalResult cir::ScopeOp::verify() {
1657 return emitOpError() <<
"cir.scope must not be empty since it should "
1658 "include at least an implicit cir.yield ";
1661 mlir::Block &lastBlock =
getRegion().back();
1662 if (lastBlock.empty() || !lastBlock.mightHaveTerminator() ||
1663 !lastBlock.getTerminator()->hasTrait<OpTrait::IsTerminator>())
1664 return emitOpError() <<
"last block of cir.scope must be terminated";
1668LogicalResult cir::ScopeOp::fold(FoldAdaptor ,
1669 SmallVectorImpl<OpFoldResult> &results) {
1674 if (block.getOperations().size() != 1)
1677 auto yield = dyn_cast<cir::YieldOp>(block.front());
1682 if (getNumResults() != 1 || yield.getNumOperands() != 1)
1685 results.push_back(yield.getOperand(0));
1693void cir::CleanupScopeOp::getSuccessorRegions(
1694 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1695 if (!point.isParent()) {
1696 regions.emplace_back(getOperation());
1701 regions.push_back(RegionSuccessor(&getBodyRegion()));
1702 regions.push_back(RegionSuccessor(&getCleanupRegion()));
1706cir::CleanupScopeOp::getSuccessorInputs(RegionSuccessor successor) {
1707 return ValueRange();
1710LogicalResult cir::CleanupScopeOp::canonicalize(CleanupScopeOp op,
1711 PatternRewriter &rewriter) {
1712 auto isRegionTrivial = [](Region ®ion) {
1713 assert(!region.empty() &&
"CleanupScopeOp regions must not be empty");
1714 if (!region.hasOneBlock())
1716 Block &block = llvm::getSingleElement(region);
1717 return llvm::hasSingleElement(block) &&
1718 isa<cir::YieldOp>(llvm::getSingleElement(block));
1721 Region &body = op.getBodyRegion();
1722 Region &
cleanup = op.getCleanupRegion();
1726 if (op.getCleanupKind() == CleanupKind::EH && isRegionTrivial(body)) {
1727 rewriter.eraseOp(op);
1733 if (!isRegionTrivial(cleanup) || !body.hasOneBlock())
1736 Block &bodyBlock = body.front();
1737 if (!isa<cir::YieldOp>(bodyBlock.getTerminator()))
1740 Operation *yield = bodyBlock.getTerminator();
1741 rewriter.inlineBlockBefore(&bodyBlock, op);
1742 rewriter.eraseOp(yield);
1743 rewriter.eraseOp(op);
1747void cir::CleanupScopeOp::build(
1748 OpBuilder &builder, OperationState &result, CleanupKind cleanupKind,
1749 function_ref<
void(OpBuilder &, Location)> bodyBuilder,
1750 function_ref<
void(OpBuilder &, Location)> cleanupBuilder) {
1751 result.addAttribute(getCleanupKindAttrName(result.name),
1752 CleanupKindAttr::get(builder.getContext(), cleanupKind));
1754 OpBuilder::InsertionGuard guard(builder);
1757 Region *bodyRegion = result.addRegion();
1758 builder.createBlock(bodyRegion);
1760 bodyBuilder(builder, result.location);
1763 Region *cleanupRegion = result.addRegion();
1764 builder.createBlock(cleanupRegion);
1766 cleanupBuilder(builder, result.location);
1781LogicalResult cir::BrOp::canonicalize(BrOp op, PatternRewriter &rewriter) {
1782 Block *src = op->getBlock();
1783 Block *dst = op.getDest();
1790 if (src->getNumSuccessors() != 1 || dst->getSinglePredecessor() != src)
1795 if (isa<cir::LabelOp, cir::IndirectBrOp>(dst->front()))
1798 auto operands = op.getDestOperands();
1799 rewriter.eraseOp(op);
1800 rewriter.mergeBlocks(dst, src, operands);
1804mlir::SuccessorOperands cir::BrOp::getSuccessorOperands(
unsigned index) {
1805 assert(index == 0 &&
"invalid successor index");
1806 return mlir::SuccessorOperands(getDestOperandsMutable());
1817mlir::SuccessorOperands
1818cir::IndirectBrOp::getSuccessorOperands(
unsigned index) {
1819 assert(index < getNumSuccessors() &&
"invalid successor index");
1820 return mlir::SuccessorOperands(getSuccOperandsMutable()[index]);
1824 OpAsmParser &parser, Type &flagType,
1825 SmallVectorImpl<Block *> &succOperandBlocks,
1828 if (failed(parser.parseCommaSeparatedList(
1829 OpAsmParser::Delimiter::Square,
1831 Block *destination = nullptr;
1832 SmallVector<OpAsmParser::UnresolvedOperand> operands;
1833 SmallVector<Type> operandTypes;
1835 if (parser.parseSuccessor(destination).failed())
1838 if (succeeded(parser.parseOptionalLParen())) {
1839 if (failed(parser.parseOperandList(
1840 operands, OpAsmParser::Delimiter::None)) ||
1841 failed(parser.parseColonTypeList(operandTypes)) ||
1842 failed(parser.parseRParen()))
1845 succOperandBlocks.push_back(destination);
1846 succOperands.emplace_back(operands);
1847 succOperandsTypes.emplace_back(operandTypes);
1850 "successor blocks")))
1856 Type flagType, SuccessorRange succs,
1857 OperandRangeRange succOperands,
1858 const TypeRangeRange &succOperandsTypes) {
1861 llvm::zip(succs, succOperands),
1864 p.printSuccessorAndUseList(std::get<0>(i), std::get<1>(i));
1867 if (!succOperands.empty())
1876mlir::SuccessorOperands cir::BrCondOp::getSuccessorOperands(
unsigned index) {
1877 assert(index < getNumSuccessors() &&
"invalid successor index");
1878 return SuccessorOperands(index == 0 ? getDestOperandsTrueMutable()
1879 : getDestOperandsFalseMutable());
1883 if (IntegerAttr condAttr = dyn_cast_if_present<IntegerAttr>(operands.front()))
1884 return condAttr.getValue().isOne() ? getDestTrue() : getDestFalse();
1892void cir::CaseOp::getSuccessorRegions(
1893 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1894 if (!point.isParent()) {
1895 regions.emplace_back(getOperation());
1898 regions.push_back(RegionSuccessor(&getCaseRegion()));
1901mlir::ValueRange cir::CaseOp::getSuccessorInputs(RegionSuccessor successor) {
1902 return successor.isOperation() ? ValueRange(getOperation()->getResults())
1906void cir::CaseOp::build(OpBuilder &builder, OperationState &result,
1907 ArrayAttr value, CaseOpKind
kind,
1908 OpBuilder::InsertPoint &insertPoint) {
1909 OpBuilder::InsertionGuard guardSwitch(builder);
1910 result.addAttribute(
"value", value);
1911 result.getOrAddProperties<Properties>().
kind =
1912 cir::CaseOpKindAttr::get(builder.getContext(),
kind);
1913 Region *caseRegion = result.addRegion();
1914 builder.createBlock(caseRegion);
1916 insertPoint = builder.saveInsertionPoint();
1923void cir::SwitchOp::getSuccessorRegions(
1924 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ion) {
1925 if (!point.isParent()) {
1926 region.emplace_back(getOperation());
1930 region.push_back(RegionSuccessor(&getBody()));
1933mlir::ValueRange cir::SwitchOp::getSuccessorInputs(RegionSuccessor successor) {
1934 return successor.isOperation() ? ValueRange(getOperation()->getResults())
1938void cir::SwitchOp::build(OpBuilder &builder, OperationState &result,
1940 assert(switchBuilder &&
"the builder callback for regions must be present");
1941 OpBuilder::InsertionGuard guardSwitch(builder);
1942 Region *switchRegion = result.addRegion();
1943 builder.createBlock(switchRegion);
1944 result.addOperands({cond});
1945 switchBuilder(builder, result.location, result);
1949 walk<mlir::WalkOrder::PreOrder>([&](mlir::Operation *op) {
1951 if (isa<cir::SwitchOp>(op) && op != *
this)
1952 return WalkResult::skip();
1954 if (
auto caseOp = dyn_cast<cir::CaseOp>(op))
1955 cases.push_back(caseOp);
1957 return WalkResult::advance();
1962 collectCases(cases);
1964 if (getBody().empty())
1967 if (!isa<YieldOp>(getBody().front().back()))
1970 if (!llvm::all_of(getBody().front(),
1971 [](Operation &op) {
return isa<CaseOp, YieldOp>(op); }))
1974 return llvm::all_of(cases, [
this](CaseOp op) {
1975 return op->getParentOfType<SwitchOp>() == *
this;
1983void cir::SwitchFlatOp::build(OpBuilder &builder, OperationState &result,
1984 Value value, Block *defaultDestination,
1985 ValueRange defaultOperands,
1987 BlockRange caseDestinations,
1990 std::vector<mlir::Attribute> caseValuesAttrs;
1991 for (
const APInt &val : caseValues)
1992 caseValuesAttrs.push_back(cir::IntAttr::get(value.getType(), val));
1993 mlir::ArrayAttr attrs = ArrayAttr::get(builder.getContext(), caseValuesAttrs);
1995 build(builder, result, value, defaultOperands, caseOperands, attrs,
1996 defaultDestination, caseDestinations);
2002 OpAsmParser &parser, Type flagType, mlir::ArrayAttr &caseValues,
2003 SmallVectorImpl<Block *> &caseDestinations,
2007 if (failed(parser.parseLSquare()))
2009 if (succeeded(parser.parseOptionalRSquare()))
2013 auto parseCase = [&]() {
2015 if (failed(parser.parseInteger(value)))
2018 values.push_back(cir::IntAttr::get(flagType, value));
2023 if (parser.parseColon() || parser.parseSuccessor(destination))
2025 if (!parser.parseOptionalLParen()) {
2026 if (parser.parseOperandList(operands, OpAsmParser::Delimiter::None,
2028 parser.parseColonTypeList(operandTypes) || parser.parseRParen())
2031 caseDestinations.push_back(destination);
2032 caseOperands.emplace_back(operands);
2033 caseOperandTypes.emplace_back(operandTypes);
2036 if (failed(parser.parseCommaSeparatedList(parseCase)))
2039 caseValues = ArrayAttr::get(flagType.getContext(), values);
2041 return parser.parseRSquare();
2045 Type flagType, mlir::ArrayAttr caseValues,
2046 SuccessorRange caseDestinations,
2047 OperandRangeRange caseOperands,
2048 const TypeRangeRange &caseOperandTypes) {
2058 llvm::zip(caseValues, caseDestinations),
2061 mlir::Attribute a = std::get<0>(i);
2062 p << mlir::cast<cir::IntAttr>(a).getValue();
2064 p.printSuccessorAndUseList(std::get<1>(i), caseOperands[index++]);
2079 mlir::Attribute &valueAttr) {
2081 return parser.parseAttribute(valueAttr,
"value", attr);
2085 p.printAttribute(value);
2088mlir::LogicalResult cir::GlobalOp::verify() {
2091 if (mlir::isa<cir::FuncType>(getSymType()))
2092 return emitOpError(
"global type cannot be a function type");
2096 if (getInitialValue().has_value()) {
2102 if ((getStaticLocalGuard().has_value()) &&
2103 (!getCtorRegion().empty() || !getDtorRegion().empty()))
2105 "Cannot have a static-local global-op with a constructor or "
2106 "destructor, they require in-function initialization via LocalInitOp");
2109 if (getStaticLocalGuard().has_value())
2110 return emitOpError(
"cannot have both static local and tls references");
2112 return emitOpError(
"'tls_refs' only valid for tls");
2115 if (getAliasee().has_value()) {
2116 if (getInitialValue().has_value() || !getCtorRegion().empty() ||
2117 !getDtorRegion().empty())
2118 return emitOpError(
"global alias shall not have an initializer or "
2119 "constructor/destructor regions");
2128void cir::GlobalOp::build(
2129 OpBuilder &odsBuilder, OperationState &odsState, llvm::StringRef sym_name,
2130 mlir::Type sym_type,
bool isConstant,
2131 mlir::ptr::MemorySpaceAttrInterface addrSpace,
2132 cir::GlobalLinkageKind linkage,
2133 function_ref<
void(OpBuilder &, Location)> ctorBuilder,
2134 function_ref<
void(OpBuilder &, Location)> dtorBuilder) {
2135 odsState.addAttribute(getSymNameAttrName(odsState.name),
2136 odsBuilder.getStringAttr(sym_name));
2137 odsState.addAttribute(getSymTypeAttrName(odsState.name),
2138 mlir::TypeAttr::get(sym_type));
2139 auto &properties = odsState.getOrAddProperties<cir::GlobalOp::Properties>();
2140 properties.setConstant(isConstant);
2144 odsState.addAttribute(getAddrSpaceAttrName(odsState.name), addrSpace);
2146 cir::GlobalLinkageKindAttr linkageAttr =
2147 cir::GlobalLinkageKindAttr::get(odsBuilder.getContext(), linkage);
2148 odsState.addAttribute(getLinkageAttrName(odsState.name), linkageAttr);
2150 Region *ctorRegion = odsState.addRegion();
2152 odsBuilder.createBlock(ctorRegion);
2153 ctorBuilder(odsBuilder, odsState.location);
2156 Region *dtorRegion = odsState.addRegion();
2158 odsBuilder.createBlock(dtorRegion);
2159 dtorBuilder(odsBuilder, odsState.location);
2168void cir::GlobalOp::getSuccessorRegions(
2169 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
2171 if (!point.isParent()) {
2172 regions.emplace_back(getOperation());
2177 Region *ctorRegion = &this->getCtorRegion();
2178 if (ctorRegion->empty())
2179 ctorRegion =
nullptr;
2182 Region *dtorRegion = &this->getDtorRegion();
2183 if (dtorRegion->empty())
2184 dtorRegion =
nullptr;
2188 regions.push_back(RegionSuccessor(ctorRegion));
2190 regions.push_back(RegionSuccessor(dtorRegion));
2193mlir::ValueRange cir::GlobalOp::getSuccessorInputs(RegionSuccessor successor) {
2194 return successor.isOperation() ? ValueRange(getOperation()->getResults())
2199 TypeAttr type, Attribute initAttr,
2200 mlir::Region &ctorRegion,
2201 mlir::Region &dtorRegion) {
2202 auto printType = [&]() { p <<
": " << type; };
2205 if (op.isDeclaration() || op.getAliasee()) {
2211 if (!ctorRegion.empty()) {
2215 p.printRegion(ctorRegion,
2224 if (!dtorRegion.empty()) {
2226 p.printRegion(dtorRegion,
2234 Attribute &initialValueAttr,
2235 mlir::Region &ctorRegion,
2236 mlir::Region &dtorRegion) {
2238 if (parser.parseOptionalEqual().failed()) {
2241 if (parser.parseColonType(opTy))
2246 if (!parser.parseOptionalKeyword(
"ctor")) {
2247 if (parser.parseColonType(opTy))
2249 auto parseLoc = parser.getCurrentLocation();
2250 if (parser.parseRegion(ctorRegion, {}, {}))
2261 assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
2262 "Non-typed attrs shouldn't appear here.");
2263 opTy = mlir::cast<mlir::TypedAttr>(initialValueAttr).getType();
2268 if (!parser.parseOptionalKeyword(
"dtor")) {
2269 auto parseLoc = parser.getCurrentLocation();
2270 if (parser.parseRegion(dtorRegion, {}, {}))
2277 typeAttr = TypeAttr::get(opTy);
2286cir::GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2289 mlir::Operation *op =
2290 symbolTable.lookupNearestSymbolFrom(*
this, getNameAttr());
2291 if (op ==
nullptr || !(isa<GlobalOp>(op) || isa<FuncOp>(op)))
2292 return emitOpError(
"'")
2294 <<
"' does not reference a valid cir.global or cir.func";
2297 mlir::ptr::MemorySpaceAttrInterface symAddrSpaceAttr{};
2298 if (
auto g = dyn_cast<GlobalOp>(op)) {
2299 symTy = g.getSymType();
2300 symAddrSpaceAttr = g.getAddrSpaceAttr();
2303 if (getTls() && !g.getTlsModel())
2304 return emitOpError(
"access to global not marked thread local");
2309 bool getGlobalIsStaticLocal = getStaticLocal();
2310 bool globalIsStaticLocal = g.getStaticLocalGuard().has_value();
2311 if (getGlobalIsStaticLocal != globalIsStaticLocal &&
2312 !getOperation()->getParentOfType<cir::GlobalOp>())
2313 return emitOpError(
"static_local attribute mismatch");
2314 }
else if (
auto f = dyn_cast<FuncOp>(op)) {
2315 symTy = f.getFunctionType();
2317 llvm_unreachable(
"Unexpected operation for GetGlobalOp");
2320 auto resultType = dyn_cast<PointerType>(getAddr().
getType());
2321 if (!resultType || symTy != resultType.getPointee())
2322 return emitOpError(
"result type pointee type '")
2323 << resultType.getPointee() <<
"' does not match type " << symTy
2324 <<
" of the global @" <<
getName();
2326 if (symAddrSpaceAttr != resultType.getAddrSpace()) {
2327 return emitOpError()
2328 <<
"result type address space does not match the address "
2329 "space of the global @"
2341cir::VTableAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2347 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
2349 return emitOpError(
"'")
2350 <<
name <<
"' does not reference a valid cir.global";
2351 std::optional<mlir::Attribute> init = op.getInitialValue();
2354 if (!isa<cir::VTableAttr>(*init))
2355 return emitOpError(
"Expected #cir.vtable in initializer for global '")
2365cir::VTTAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2374 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
2376 return emitOpError(
"'")
2377 <<
name <<
"' does not reference a valid cir.global";
2378 std::optional<mlir::Attribute> init = op.getInitialValue();
2381 if (!isa<cir::ConstArrayAttr>(*init))
2383 "Expected constant array in initializer for global VTT '")
2388LogicalResult cir::VTTAddrPointOp::verify() {
2390 if (
getName() && getSymAddr())
2391 return emitOpError(
"should use either a symbol or value, but not both");
2397 mlir::Type resultType = getAddr().getType();
2398 mlir::Type resTy = cir::PointerType::get(
2399 cir::PointerType::get(cir::VoidType::get(getContext())));
2401 if (resultType != resTy)
2402 return emitOpError(
"result type must be ")
2403 << resTy <<
", but provided result type is " << resultType;
2415void cir::FuncOp::build(OpBuilder &builder, OperationState &result,
2416 StringRef name, FuncType type,
2417 GlobalLinkageKind linkage, CallingConv callingConv) {
2419 result.addAttribute(SymbolTable::getSymbolAttrName(),
2420 builder.getStringAttr(name));
2421 result.addAttribute(getFunctionTypeAttrName(result.name),
2422 TypeAttr::get(type));
2423 result.addAttribute(
2425 GlobalLinkageKindAttr::get(builder.getContext(), linkage));
2426 result.addAttribute(getCallingConvAttrName(result.name),
2427 CallingConvAttr::get(builder.getContext(), callingConv));
2435cir::AnnotationAttr::verify(function_ref<InFlightDiagnostic()> emitError,
2436 mlir::StringAttr name, mlir::ArrayAttr args) {
2439 for (mlir::Attribute arg : args) {
2440 if (!isa<mlir::StringAttr, mlir::IntegerAttr>(arg))
2441 return emitError() <<
"annotation args must be StringAttr or IntegerAttr,"
2447ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
2448 llvm::SMLoc loc = parser.getCurrentLocation();
2449 mlir::Builder &builder = parser.getBuilder();
2451 mlir::StringAttr builtinNameAttr = getBuiltinAttrName(state.name);
2452 mlir::StringAttr coroutineNameAttr = getCoroutineAttrName(state.name);
2453 mlir::StringAttr inlineKindNameAttr = getInlineKindAttrName(state.name);
2454 mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
2455 mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
2456 mlir::StringAttr comdatNameAttr = getComdatAttrName(state.name);
2457 mlir::StringAttr visNameAttr = getSymVisibilityAttrName(state.name);
2458 mlir::StringAttr dsoLocalNameAttr = getDsoLocalAttrName(state.name);
2459 mlir::StringAttr funcInfoNameAttr = getFuncInfoAttrName(state.name);
2461 if (::mlir::succeeded(parser.parseOptionalKeyword(builtinNameAttr.strref())))
2462 state.addAttribute(builtinNameAttr, parser.getBuilder().getUnitAttr());
2463 if (::mlir::succeeded(
2464 parser.parseOptionalKeyword(coroutineNameAttr.strref())))
2465 state.addAttribute(coroutineNameAttr, parser.getBuilder().getUnitAttr());
2468 cir::InlineKindAttr inlineKindAttr;
2472 state.addAttribute(inlineKindNameAttr, inlineKindAttr);
2474 if (::mlir::succeeded(parser.parseOptionalKeyword(lambdaNameAttr.strref())))
2475 state.addAttribute(lambdaNameAttr, parser.getBuilder().getUnitAttr());
2476 if (parser.parseOptionalKeyword(noProtoNameAttr).succeeded())
2477 state.addAttribute(noProtoNameAttr, parser.getBuilder().getUnitAttr());
2479 if (parser.parseOptionalKeyword(comdatNameAttr).succeeded())
2480 state.addAttribute(comdatNameAttr, parser.getBuilder().getUnitAttr());
2484 GlobalLinkageKindAttr::get(
2485 parser.getContext(),
2487 parser, GlobalLinkageKind::ExternalLinkage)));
2489 ::llvm::StringRef visAttrStr;
2490 if (parser.parseOptionalKeyword(&visAttrStr, {
"private",
"public",
"nested"})
2492 state.addAttribute(visNameAttr,
2493 parser.getBuilder().getStringAttr(visAttrStr));
2496 state.getOrAddProperties<cir::FuncOp::Properties>().global_visibility =
2499 if (parser.parseOptionalKeyword(dsoLocalNameAttr).succeeded())
2500 state.addAttribute(dsoLocalNameAttr, parser.getBuilder().getUnitAttr());
2502 StringAttr nameAttr;
2503 if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
2509 bool isVariadic =
false;
2510 if (function_interface_impl::parseFunctionSignatureWithArguments(
2511 parser,
true, arguments, isVariadic, resultTypes,
2516 bool argAttrsEmpty =
true;
2517 for (OpAsmParser::Argument &arg : arguments) {
2518 argTypes.push_back(
arg.type);
2522 argAttrs.push_back(
arg.attrs);
2524 argAttrsEmpty =
false;
2528 if (resultTypes.size() > 1 || resultAttrs.size() > 1)
2529 return parser.emitError(
2530 loc,
"functions with multiple return types are not supported");
2532 mlir::Type returnType =
2533 (resultTypes.empty() ? cir::VoidType::get(builder.getContext())
2534 : resultTypes.front());
2536 cir::FuncType fnType = cir::FuncType::get(argTypes, returnType, isVariadic);
2540 state.addAttribute(getFunctionTypeAttrName(state.name),
2541 TypeAttr::get(fnType));
2543 if (!resultAttrs.empty() && resultAttrs[0])
2545 getResAttrsAttrName(state.name),
2546 mlir::ArrayAttr::get(parser.getContext(), {resultAttrs[0]}));
2549 state.addAttribute(getArgAttrsAttrName(state.name),
2550 mlir::ArrayAttr::get(parser.getContext(), argAttrs));
2552 bool hasAlias =
false;
2553 mlir::StringAttr aliaseeNameAttr = getAliaseeAttrName(state.name);
2554 if (parser.parseOptionalKeyword(
"alias").succeeded()) {
2555 if (parser.parseLParen().failed())
2557 mlir::StringAttr aliaseeAttr;
2558 if (parser.parseOptionalSymbolName(aliaseeAttr).failed())
2560 state.addAttribute(aliaseeNameAttr, FlatSymbolRefAttr::get(aliaseeAttr));
2561 if (parser.parseRParen().failed())
2566 mlir::StringAttr personalityNameAttr = getPersonalityAttrName(state.name);
2567 if (parser.parseOptionalKeyword(
"personality").succeeded()) {
2568 if (parser.parseLParen().failed())
2570 mlir::StringAttr personalityAttr;
2571 if (parser.parseOptionalSymbolName(personalityAttr).failed())
2573 state.addAttribute(personalityNameAttr,
2574 FlatSymbolRefAttr::get(personalityAttr));
2575 if (parser.parseRParen().failed())
2580 mlir::StringAttr callConvNameAttr = getCallingConvAttrName(state.name);
2581 cir::CallingConv callConv = cir::CallingConv::C;
2582 if (parser.parseOptionalKeyword(
"cc").succeeded()) {
2583 if (parser.parseLParen().failed())
2586 return parser.emitError(loc) <<
"unknown calling convention";
2587 if (parser.parseRParen().failed())
2590 state.addAttribute(callConvNameAttr,
2591 cir::CallingConvAttr::get(parser.getContext(), callConv));
2593 auto parseGlobalDtorCtor =
2594 [&](StringRef keyword,
2595 llvm::function_ref<void(std::optional<int> prio)> createAttr)
2596 -> mlir::LogicalResult {
2597 if (mlir::succeeded(parser.parseOptionalKeyword(keyword))) {
2598 std::optional<int> priority;
2599 if (mlir::succeeded(parser.parseOptionalLParen())) {
2600 auto parsedPriority = mlir::FieldParser<int>::parse(parser);
2601 if (mlir::failed(parsedPriority))
2602 return parser.emitError(parser.getCurrentLocation(),
2603 "failed to parse 'priority', of type 'int'");
2604 priority = parsedPriority.value_or(
int());
2606 if (parser.parseRParen())
2609 createAttr(priority);
2615 if (parser.parseOptionalKeyword(
"func_info").succeeded()) {
2616 if (parser.parseLess().failed())
2619 llvm::SMLoc attrLoc = parser.getCurrentLocation();
2620 mlir::Attribute
attr;
2621 if (parser.parseAttribute(attr).failed())
2623 if (!mlir::isa<cir::CXXCtorAttr, cir::CXXDtorAttr, cir::CXXAssignAttr,
2624 cir::FuncIdentityAttr>(attr))
2625 return parser.emitError(attrLoc,
2626 "expected a function info attribute, got ")
2628 state.addAttribute(funcInfoNameAttr, attr);
2630 if (parser.parseGreater().failed())
2634 if (parseGlobalDtorCtor(
"global_ctor", [&](std::optional<int> priority) {
2635 mlir::IntegerAttr globalCtorPriorityAttr =
2636 builder.getI32IntegerAttr(priority.value_or(65535));
2637 state.addAttribute(getGlobalCtorPriorityAttrName(state.name),
2638 globalCtorPriorityAttr);
2642 if (parseGlobalDtorCtor(
"global_dtor", [&](std::optional<int> priority) {
2643 mlir::IntegerAttr globalDtorPriorityAttr =
2644 builder.getI32IntegerAttr(priority.value_or(65535));
2645 state.addAttribute(getGlobalDtorPriorityAttrName(state.name),
2646 globalDtorPriorityAttr);
2650 if (parser.parseOptionalKeyword(
"side_effect").succeeded()) {
2651 cir::SideEffect sideEffect;
2653 if (parser.parseLParen().failed() ||
2655 parser.parseRParen().failed())
2658 auto attr = cir::SideEffectAttr::get(parser.getContext(), sideEffect);
2659 state.addAttribute(CIRDialect::getSideEffectAttrName(), attr);
2663 mlir::StringAttr annotationsNameAttr = getAnnotationsAttrName(state.name);
2664 mlir::ArrayAttr annotationsAttr;
2665 if (parser.parseOptionalAttribute(annotationsAttr).has_value() &&
2667 state.addAttribute(annotationsNameAttr, annotationsAttr);
2670 NamedAttrList parsedAttrs;
2671 if (parser.parseOptionalAttrDictWithKeyword(parsedAttrs))
2674 for (StringRef disallowed : cir::FuncOp::getAttributeNames()) {
2675 if (parsedAttrs.get(disallowed))
2676 return parser.emitError(loc,
"attribute '")
2678 <<
"' should not be specified in the explicit attribute list";
2681 state.attributes.append(parsedAttrs);
2684 auto *body = state.addRegion();
2685 OptionalParseResult parseResult = parser.parseOptionalRegion(
2686 *body, arguments,
false);
2687 if (parseResult.has_value()) {
2689 return parser.emitError(loc,
"function alias shall not have a body");
2690 if (failed(*parseResult))
2694 return parser.emitError(loc,
"expected non-empty function body");
2703bool cir::FuncOp::isDeclaration() {
2706 std::optional<StringRef> aliasee = getAliasee();
2708 return getFunctionBody().empty();
2714bool cir::FuncOp::isCXXSpecialMemberFunction() {
2717 mlir::Attribute
attr = getFuncInfoAttr();
2718 return attr && mlir::isa<CXXCtorAttr, CXXDtorAttr, CXXAssignAttr>(attr);
2721bool cir::FuncOp::isCxxConstructor() {
2722 auto attr = getFuncInfoAttr();
2723 return attr && dyn_cast<CXXCtorAttr>(attr);
2726bool cir::FuncOp::isCxxDestructor() {
2727 auto attr = getFuncInfoAttr();
2728 return attr && dyn_cast<CXXDtorAttr>(attr);
2731bool cir::FuncOp::isCxxSpecialAssignment() {
2732 auto attr = getFuncInfoAttr();
2733 return attr && dyn_cast<CXXAssignAttr>(attr);
2736std::optional<CtorKind> cir::FuncOp::getCxxConstructorKind() {
2737 mlir::Attribute
attr = getFuncInfoAttr();
2739 if (
auto ctor = dyn_cast<CXXCtorAttr>(attr))
2740 return ctor.getCtorKind();
2742 return std::nullopt;
2745std::optional<AssignKind> cir::FuncOp::getCxxSpecialAssignKind() {
2746 mlir::Attribute
attr = getFuncInfoAttr();
2748 if (
auto assign = dyn_cast<CXXAssignAttr>(attr))
2749 return assign.getAssignKind();
2751 return std::nullopt;
2754bool cir::FuncOp::isCxxTrivialMemberFunction() {
2755 mlir::Attribute
attr = getFuncInfoAttr();
2757 if (
auto ctor = dyn_cast<CXXCtorAttr>(attr))
2758 return ctor.getIsTrivial();
2759 if (
auto dtor = dyn_cast<CXXDtorAttr>(attr))
2760 return dtor.getIsTrivial();
2761 if (
auto assign = dyn_cast<CXXAssignAttr>(attr))
2762 return assign.getIsTrivial();
2767mlir::Region *cir::FuncOp::getCallableRegion() {
2773void cir::FuncOp::print(OpAsmPrinter &p) {
2791 if (getLinkage() != GlobalLinkageKind::ExternalLinkage)
2792 p <<
' ' << stringifyGlobalLinkageKind(getLinkage());
2794 mlir::SymbolTable::Visibility vis = getVisibility();
2795 if (vis != mlir::SymbolTable::Visibility::Public)
2798 if (getGlobalVisibility() != cir::VisibilityKind::Default)
2799 p <<
' ' << stringifyVisibilityKind(getGlobalVisibility());
2805 p.printSymbolName(getSymName());
2806 cir::FuncType fnType = getFunctionType();
2807 function_interface_impl::printFunctionSignature(
2808 p, *
this, fnType.getInputs(), fnType.isVarArg(), fnType.getReturnTypes());
2810 if (std::optional<StringRef> aliaseeName = getAliasee()) {
2812 p.printSymbolName(*aliaseeName);
2816 if (getCallingConv() != cir::CallingConv::C) {
2818 p << stringifyCallingConv(getCallingConv());
2822 if (std::optional<StringRef> personalityName = getPersonality()) {
2823 p <<
" personality(";
2824 p.printSymbolName(*personalityName);
2828 if (mlir::Attribute funcInfo = getFuncInfoAttr()) {
2830 p.printAttribute(funcInfo);
2834 if (
auto globalCtorPriority = getGlobalCtorPriority()) {
2835 p <<
" global_ctor";
2836 if (globalCtorPriority.value() != 65535)
2837 p <<
"(" << globalCtorPriority.value() <<
")";
2840 if (
auto globalDtorPriority = getGlobalDtorPriority()) {
2841 p <<
" global_dtor";
2842 if (globalDtorPriority.value() != 65535)
2843 p <<
"(" << globalDtorPriority.value() <<
")";
2846 if (std::optional<cir::SideEffect> sideEffect = getSideEffect();
2847 sideEffect && *sideEffect != cir::SideEffect::All) {
2848 p <<
" side_effect(";
2849 p << stringifySideEffect(*sideEffect);
2853 if (mlir::ArrayAttr annotations = getAnnotationsAttr()) {
2855 p.printAttribute(annotations);
2858 function_interface_impl::printFunctionAttributes(
2859 p, *
this, cir::FuncOp::getAttributeNames());
2862 Region &body = getOperation()->getRegion(0);
2863 if (!body.empty()) {
2865 p.printRegion(body,
false,
2870mlir::LogicalResult cir::FuncOp::verify() {
2872 if (!isDeclaration() && getCoroutine()) {
2873 bool foundAwait =
false;
2874 int coroBodyCount = 0;
2875 this->walk([&](Operation *op) {
2876 if (
auto await = dyn_cast<AwaitOp>(op)) {
2878 }
else if (isa<CoroBodyOp>(op)) {
2880 if (coroBodyCount > 1) {
2881 return mlir::WalkResult::interrupt();
2884 return mlir::WalkResult::advance();
2887 return emitOpError()
2888 <<
"coroutine body must use at least one cir.await op";
2889 if (coroBodyCount != 1)
2890 return emitOpError()
2891 <<
"coroutine function must have exactly one cir.body op";
2894 llvm::SmallSet<llvm::StringRef, 16> labels;
2895 llvm::SmallSet<llvm::StringRef, 16> gotos;
2896 llvm::SmallSet<llvm::StringRef, 16> blockAddresses;
2897 bool invalidBlockAddress =
false;
2898 getOperation()->walk([&](mlir::Operation *op) {
2899 if (
auto lab = dyn_cast<cir::LabelOp>(op)) {
2900 labels.insert(lab.getLabel());
2901 }
else if (
auto goTo = dyn_cast<cir::GotoOp>(op)) {
2902 gotos.insert(goTo.getLabel());
2903 }
else if (
auto blkAdd = dyn_cast<cir::BlockAddressOp>(op)) {
2904 if (blkAdd.getBlockAddrInfoAttr().getFunc().getAttr() != getSymName()) {
2906 invalidBlockAddress =
true;
2907 return mlir::WalkResult::interrupt();
2909 blockAddresses.insert(blkAdd.getBlockAddrInfoAttr().getLabel());
2911 return mlir::WalkResult::advance();
2914 if (invalidBlockAddress)
2915 return emitOpError() <<
"blockaddress references a different function";
2917 llvm::SmallSet<llvm::StringRef, 16> mismatched;
2918 if (!labels.empty() || !gotos.empty()) {
2919 mismatched = llvm::set_difference(gotos, labels);
2921 if (!mismatched.empty())
2922 return emitOpError() <<
"goto/label mismatch";
2927 if (!labels.empty() || !blockAddresses.empty()) {
2928 mismatched = llvm::set_difference(blockAddresses, labels);
2930 if (!mismatched.empty())
2931 return emitOpError()
2932 <<
"expects an existing label target in the referenced function";
2946LogicalResult cir::AddOp::verify() {
2947 if (getSaturated() && (getNoSignedWrap() || getNoUnsignedWrap()))
2948 return emitOpError()
2949 <<
"the nsw/nuw flags and the saturated flag are mutually exclusive";
2950 return mlir::success();
2953LogicalResult cir::SubOp::verify() {
2954 if (getSaturated() && (getNoSignedWrap() || getNoUnsignedWrap()))
2955 return emitOpError()
2956 <<
"the nsw/nuw flags and the saturated flag are mutually exclusive";
2957 return mlir::success();
2969void cir::TernaryOp::getSuccessorRegions(
2970 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
2972 if (!point.isParent()) {
2973 regions.emplace_back(getOperation());
2979 regions.push_back(RegionSuccessor(&getTrueRegion()));
2980 regions.push_back(RegionSuccessor(&getFalseRegion()));
2983mlir::ValueRange cir::TernaryOp::getSuccessorInputs(RegionSuccessor successor) {
2984 return successor.isOperation() ? ValueRange(getOperation()->getResults())
2988void cir::TernaryOp::build(
2989 OpBuilder &builder, OperationState &result,
Value cond,
2990 function_ref<
void(OpBuilder &, Location)> trueBuilder,
2991 function_ref<
void(OpBuilder &, Location)> falseBuilder) {
2992 result.addOperands(cond);
2993 OpBuilder::InsertionGuard guard(builder);
2994 Region *trueRegion = result.addRegion();
2995 builder.createBlock(trueRegion);
2996 trueBuilder(builder, result.location);
2997 Region *falseRegion = result.addRegion();
2998 builder.createBlock(falseRegion);
2999 falseBuilder(builder, result.location);
3004 if (trueRegion->back().mightHaveTerminator())
3005 yield = dyn_cast_or_null<cir::YieldOp>(trueRegion->back().getTerminator());
3006 if (!yield && falseRegion->back().mightHaveTerminator())
3007 yield = dyn_cast_or_null<cir::YieldOp>(falseRegion->back().getTerminator());
3009 assert((!yield || yield.getNumOperands() <= 1) &&
3010 "expected zero or one result type");
3011 if (yield && yield.getNumOperands() == 1)
3012 result.addTypes(TypeRange{yield.getOperandTypes().front()});
3019OpFoldResult cir::SelectOp::fold(FoldAdaptor adaptor) {
3020 mlir::Attribute
condition = adaptor.getCondition();
3022 bool conditionValue = mlir::cast<cir::BoolAttr>(
condition).getValue();
3023 return conditionValue ? getTrueValue() : getFalseValue();
3027 mlir::Attribute trueValue = adaptor.getTrueValue();
3028 mlir::Attribute falseValue = adaptor.getFalseValue();
3029 if (trueValue == falseValue)
3031 if (getTrueValue() == getFalseValue())
3032 return getTrueValue();
3037LogicalResult cir::SelectOp::verify() {
3039 auto condTy = dyn_cast<cir::VectorType>(getCondition().
getType());
3046 if (!isa<cir::VectorType>(getTrueValue().
getType()) ||
3047 !isa<cir::VectorType>(getFalseValue().
getType())) {
3048 return emitOpError()
3049 <<
"expected both true and false operands to be vector types "
3050 "when the condition is a vector boolean type";
3059LogicalResult cir::ShiftOp::verify() {
3060 mlir::Operation *op = getOperation();
3061 auto op0VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(0).getType());
3062 auto op1VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(1).getType());
3063 if (!op0VecTy ^ !op1VecTy)
3064 return emitOpError() <<
"input types cannot be one vector and one scalar";
3067 if (op0VecTy.getSize() != op1VecTy.getSize())
3068 return emitOpError() <<
"input vector types must have the same size";
3070 auto opResultTy = mlir::dyn_cast<cir::VectorType>(
getType());
3072 return emitOpError() <<
"the type of the result must be a vector "
3073 <<
"if it is vector shift";
3075 auto op0VecEleTy = mlir::cast<cir::IntType>(op0VecTy.getElementType());
3076 auto op1VecEleTy = mlir::cast<cir::IntType>(op1VecTy.getElementType());
3077 if (op0VecEleTy.getWidth() != op1VecEleTy.getWidth())
3078 return emitOpError()
3079 <<
"vector operands do not have the same elements sizes";
3081 auto resVecEleTy = mlir::cast<cir::IntType>(opResultTy.getElementType());
3082 if (op0VecEleTy.getWidth() != resVecEleTy.getWidth())
3083 return emitOpError() <<
"vector operands and result type do not have the "
3084 "same elements sizes";
3087 return mlir::success();
3094LogicalResult cir::LabelOp::verify() {
3095 mlir::Operation *op = getOperation();
3096 mlir::Block *blk = op->getBlock();
3097 if (&blk->front() != op)
3098 return emitError() <<
"must be the first operation in a block";
3100 return mlir::success();
3107OpFoldResult cir::IncOp::fold(FoldAdaptor adaptor) {
3108 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3109 return adaptor.getInput();
3117OpFoldResult cir::DecOp::fold(FoldAdaptor adaptor) {
3118 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3119 return adaptor.getInput();
3127OpFoldResult cir::MinusOp::fold(FoldAdaptor adaptor) {
3128 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3129 return adaptor.getInput();
3134 mlir::dyn_cast_if_present<cir::IntAttr>(adaptor.getInput())) {
3135 APInt val = intAttr.getValue();
3137 return cir::IntAttr::get(
getType(), val);
3147OpFoldResult cir::FNegOp::fold(FoldAdaptor adaptor) {
3148 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3149 return adaptor.getInput();
3153 mlir::dyn_cast_if_present<cir::FPAttr>(adaptor.getInput())) {
3154 APFloat val = fpAttr.getValue();
3156 return cir::FPAttr::get(
getType(), val);
3166OpFoldResult cir::NotOp::fold(FoldAdaptor adaptor) {
3167 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3168 return adaptor.getInput();
3173 if (mlir::Attribute attr = adaptor.getInput()) {
3174 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr)) {
3175 APInt val = intAttr.getValue();
3177 return cir::IntAttr::get(
getType(), val);
3179 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr))
3180 return cir::BoolAttr::get(getContext(), !boolAttr.getValue());
3191 mlir::Type resultTy) {
3194 mlir::Type inputMemberTy;
3195 mlir::Type resultMemberTy;
3196 if (mlir::isa<cir::DataMemberType>(src.getType())) {
3198 mlir::cast<cir::DataMemberType>(src.getType()).getMemberTy();
3199 resultMemberTy = mlir::cast<cir::DataMemberType>(resultTy).getMemberTy();
3202 if (inputMemberTy != resultMemberTy)
3203 return op->emitOpError()
3204 <<
"member types of the operand and the result do not match";
3206 return mlir::success();
3209LogicalResult cir::BaseDataMemberOp::verify() {
3213LogicalResult cir::DerivedDataMemberOp::verify() {
3221LogicalResult cir::BaseMethodOp::verify() {
3225LogicalResult cir::DerivedMethodOp::verify() {
3233void cir::AwaitOp::build(OpBuilder &builder, OperationState &result,
3237 result.addAttribute(getKindAttrName(result.name),
3238 cir::AwaitKindAttr::get(builder.getContext(),
kind));
3240 OpBuilder::InsertionGuard guard(builder);
3241 Region *readyRegion = result.addRegion();
3242 builder.createBlock(readyRegion);
3243 readyBuilder(builder, result.location);
3247 OpBuilder::InsertionGuard guard(builder);
3248 Region *suspendRegion = result.addRegion();
3249 builder.createBlock(suspendRegion);
3250 suspendBuilder(builder, result.location);
3254 OpBuilder::InsertionGuard guard(builder);
3255 Region *resumeRegion = result.addRegion();
3256 builder.createBlock(resumeRegion);
3257 resumeBuilder(builder, result.location);
3261void cir::AwaitOp::getSuccessorRegions(
3262 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
3265 if (!point.isParent()) {
3266 regions.emplace_back(getOperation());
3273 regions.push_back(RegionSuccessor(&this->getReady()));
3274 regions.push_back(RegionSuccessor(&this->getSuspend()));
3275 regions.push_back(RegionSuccessor(&this->getResume()));
3278mlir::ValueRange cir::AwaitOp::getSuccessorInputs(RegionSuccessor successor) {
3279 if (successor.isOperation())
3280 return getOperation()->getResults();
3281 if (successor == &getReady())
3282 return getReady().getArguments();
3283 if (successor == &getSuspend())
3284 return getSuspend().getArguments();
3285 if (successor == &getResume())
3286 return getResume().getArguments();
3287 llvm_unreachable(
"invalid region successor");
3290LogicalResult cir::AwaitOp::verify() {
3291 if (!isa<ConditionOp>(this->getReady().back().getTerminator()))
3292 return emitOpError(
"ready region must end with cir.condition");
3300void cir::CoroBodyOp::getSuccessorRegions(
3301 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
3302 if (!point.isParent()) {
3303 regions.emplace_back(getOperation());
3307 regions.push_back(RegionSuccessor(&getBody()));
3311cir::CoroBodyOp::getSuccessorInputs(RegionSuccessor successor) {
3312 return ValueRange();
3315LogicalResult cir::CoroBodyOp::verify() {
3316 if (!getOperation()->getParentOfType<FuncOp>().getCoroutine())
3317 return emitOpError(
"enclosing function must be a coroutine");
3321void cir::CoroBodyOp::build(OpBuilder &builder, OperationState &result,
3323 assert(bodyBuilder &&
3324 "the builder callback for 'CoroBodyOp' must be present");
3325 OpBuilder::InsertionGuard guard(builder);
3327 Region *bodyRegion = result.addRegion();
3328 builder.createBlock(bodyRegion);
3329 bodyBuilder(builder, result.location);
3340 mlir::Type srcType, mlir::Type dstType) {
3341 printer.printType(srcType);
3342 if (srcType != dstType) {
3344 printer.printType(dstType);
3349 mlir::Type &srcType,
3350 mlir::Type &dstType) {
3351 if (parser.parseType(srcType))
3352 return mlir::failure();
3353 if (parser.parseOptionalComma().succeeded()) {
3354 if (parser.parseType(dstType))
3355 return mlir::failure();
3359 return mlir::success();
3362LogicalResult cir::CopyOp::verify() {
3367 if (!
getType().getPointee().hasTrait<DataLayoutTypeInterface::Trait>())
3368 return emitError() <<
"missing data layout for pointee type";
3370 if (getSkipTailPadding() &&
3371 !mlir::isa<cir::RecordType>(
getType().getPointee()))
3373 <<
"skip_tail_padding is only valid for record pointee types";
3375 return mlir::success();
3382LogicalResult cir::GetRuntimeMemberOp::verify() {
3383 cir::DataMemberType memberPtrTy = getMember().getType();
3385 if (getAddr().
getType().getPointee() != memberPtrTy.getClassTy())
3386 return emitError() <<
"record type does not match the member pointer type";
3387 if (
getType().getPointee() != memberPtrTy.getMemberTy())
3388 return emitError() <<
"result type does not match the member pointer type";
3389 return mlir::success();
3396LogicalResult cir::GetMethodOp::verify() {
3397 cir::MethodType methodTy = getMethod().getType();
3400 cir::PointerType objectPtrTy = getObject().getType();
3401 mlir::Type objectTy = objectPtrTy.getPointee();
3403 if (methodTy.getClassTy() != objectTy)
3404 return emitError() <<
"method class type and object type do not match";
3407 auto calleeTy = mlir::cast<cir::FuncType>(getCallee().
getType().getPointee());
3408 cir::FuncType methodFuncTy = methodTy.getMemberFuncTy();
3415 if (methodFuncTy.getReturnType() != calleeTy.getReturnType())
3417 <<
"method return type and callee return type do not match";
3422 if (calleeArgsTy.empty())
3423 return emitError() <<
"callee parameter list lacks receiver object ptr";
3425 auto calleeThisArgPtrTy = mlir::dyn_cast<cir::PointerType>(calleeArgsTy[0]);
3426 if (!calleeThisArgPtrTy ||
3427 !mlir::isa<cir::VoidType>(calleeThisArgPtrTy.getPointee())) {
3429 <<
"the first parameter of callee must be a void pointer";
3432 if (calleeArgsTy.size() != methodFuncArgsTy.size())
3433 return emitError() <<
"callee and method parameter counts do not match";
3435 if (calleeArgsTy.size() > 1 &&
3436 calleeArgsTy.slice(1) != methodFuncArgsTy.slice(1))
3438 <<
"callee parameters and method parameters do not match";
3440 return mlir::success();
3447LogicalResult cir::GetMemberOp::verify() {
3448 const auto recordTy = dyn_cast<RecordType>(getAddrTy().getPointee());
3450 return emitError() <<
"expected pointer to a record type";
3452 if (recordTy.getMembers().size() <=
getIndex())
3453 return emitError() <<
"member index out of bounds";
3456 return emitError() <<
"member type mismatch";
3458 return mlir::success();
3465LogicalResult cir::ExtractMemberOp::verify() {
3466 if (mlir::isa<cir::UnionType>(getRecord().
getType()))
3468 <<
"cir.extract_member currently does not support unions";
3469 auto structTy = mlir::cast<cir::StructType>(getRecord().
getType());
3470 if (structTy.getMembers().size() <=
getIndex())
3471 return emitError() <<
"member index out of bounds";
3473 return emitError() <<
"member type mismatch";
3474 return mlir::success();
3481LogicalResult cir::InsertMemberOp::verify() {
3482 if (mlir::isa<cir::UnionType>(getRecord().
getType()))
3483 return emitError() <<
"cir.insert_member currently does not support unions";
3484 auto structTy = mlir::cast<cir::StructType>(getRecord().
getType());
3485 if (structTy.getMembers().size() <=
getIndex())
3486 return emitError() <<
"member index out of bounds";
3488 return emitError() <<
"member type mismatch";
3490 return mlir::success();
3497OpFoldResult cir::VecCreateOp::fold(FoldAdaptor adaptor) {
3498 if (llvm::any_of(getElements(), [](mlir::Value value) {
3499 return !value.getDefiningOp<cir::ConstantOp>();
3503 return cir::ConstVectorAttr::get(
3504 getType(), mlir::ArrayAttr::get(getContext(), adaptor.getElements()));
3507LogicalResult cir::VecCreateOp::verify() {
3511 const cir::VectorType vecTy =
getType();
3512 if (getElements().size() != vecTy.getSize()) {
3513 return emitOpError() <<
"operand count of " << getElements().size()
3514 <<
" doesn't match vector type " << vecTy
3515 <<
" element count of " << vecTy.getSize();
3518 const mlir::Type elementType = vecTy.getElementType();
3519 for (
const mlir::Value element : getElements()) {
3520 if (element.getType() != elementType) {
3521 return emitOpError() <<
"operand type " << element.getType()
3522 <<
" doesn't match vector element type "
3534OpFoldResult cir::VecExtractOp::fold(FoldAdaptor adaptor) {
3535 const auto vectorAttr =
3536 llvm::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec());
3540 const auto indexAttr =
3541 llvm::dyn_cast_if_present<cir::IntAttr>(adaptor.getIndex());
3545 const mlir::ArrayAttr elements = vectorAttr.getElts();
3546 const uint64_t index = indexAttr.getUInt();
3547 if (index >= elements.size())
3550 return elements[index];
3557LogicalResult cir::CmpOp::verify() {
3558 if (getFenvAttr() && !cir::isAnyFloatingPointType(getLhs().
getType()))
3559 return emitOpError()
3560 <<
"'fenv' is only valid for floating-point comparisons";
3568LogicalResult cir::VecCmpOp::verify() {
3569 if (getFenvAttr() && !cir::isFPOrVectorOfFPType(getLhs().
getType()))
3570 return emitOpError()
3571 <<
"'fenv' is only valid for floating-point comparisons";
3575OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
3585 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getLhs());
3587 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getRhs());
3588 if (!lhsVecAttr || !rhsVecAttr)
3591 mlir::Type inputElemTy =
3592 mlir::cast<cir::VectorType>(lhsVecAttr.getType()).getElementType();
3593 if (!isAnyIntegerOrFloatingPointType(inputElemTy))
3596 cir::CmpOpKind opKind = adaptor.getKind();
3597 mlir::ArrayAttr lhsVecElhs = lhsVecAttr.getElts();
3598 mlir::ArrayAttr rhsVecElhs = rhsVecAttr.getElts();
3599 uint64_t vecSize = lhsVecElhs.size();
3602 bool isIntAttr = vecSize && mlir::isa<cir::IntAttr>(lhsVecElhs[0]);
3603 bool isUnsignedInt =
3604 isIntAttr && mlir::cast<cir::IntType>(inputElemTy).isUnsigned();
3605 for (uint64_t i = 0; i < vecSize; i++) {
3606 mlir::Attribute lhsAttr = lhsVecElhs[i];
3607 mlir::Attribute rhsAttr = rhsVecElhs[i];
3608 bool cmpResult =
false;
3610 case cir::CmpOpKind::lt: {
3613 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() <
3614 mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
3616 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <
3617 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3619 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <
3620 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3624 case cir::CmpOpKind::le: {
3627 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() <=
3628 mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
3630 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <=
3631 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3633 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <=
3634 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3638 case cir::CmpOpKind::gt: {
3641 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() >
3642 mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
3644 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >
3645 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3647 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >
3648 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3652 case cir::CmpOpKind::ge: {
3655 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() >=
3656 mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
3658 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >=
3659 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3661 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >=
3662 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3666 case cir::CmpOpKind::eq: {
3668 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() ==
3669 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3671 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() ==
3672 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3676 case cir::CmpOpKind::ne: {
3678 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() !=
3679 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3681 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() !=
3682 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3686 case cir::CmpOpKind::one: {
3687 llvm::APFloat::cmpResult cr =
3688 mlir::cast<cir::FPAttr>(lhsAttr).getValue().compare(
3689 mlir::cast<cir::FPAttr>(rhsAttr).getValue());
3691 cr != llvm::APFloat::cmpUnordered && cr != llvm::APFloat::cmpEqual;
3694 case cir::CmpOpKind::uno: {
3695 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue().compare(
3696 mlir::cast<cir::FPAttr>(rhsAttr).getValue()) ==
3697 llvm::APFloat::cmpUnordered;
3706 cir::IntAttr::get(
getType().getElementType(), cmpResult ? -1LL : 0LL);
3709 return cir::ConstVectorAttr::get(
3710 getType(), mlir::ArrayAttr::get(getContext(), elements));
3717OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor adaptor) {
3719 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec1());
3721 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec2());
3722 if (!vec1Attr || !vec2Attr)
3725 mlir::Type vec1ElemTy =
3726 mlir::cast<cir::VectorType>(vec1Attr.getType()).getElementType();
3728 mlir::ArrayAttr vec1Elts = vec1Attr.getElts();
3729 mlir::ArrayAttr vec2Elts = vec2Attr.getElts();
3730 mlir::ArrayAttr indicesElts = adaptor.getIndices();
3733 elements.reserve(indicesElts.size());
3735 uint64_t vec1Size = vec1Elts.size();
3736 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
3737 if (idxAttr.getSInt() == -1) {
3738 elements.push_back(cir::UndefAttr::get(vec1ElemTy));
3742 uint64_t idxValue = idxAttr.getUInt();
3743 elements.push_back(idxValue < vec1Size ? vec1Elts[idxValue]
3744 : vec2Elts[idxValue - vec1Size]);
3747 return cir::ConstVectorAttr::get(
3748 getType(), mlir::ArrayAttr::get(getContext(), elements));
3751LogicalResult cir::VecShuffleOp::verify() {
3754 if (getIndices().size() != getResult().
getType().getSize()) {
3755 return emitOpError() <<
": the number of elements in " << getIndices()
3756 <<
" and " << getResult().getType() <<
" don't match";
3761 if (getVec1().
getType().getElementType() !=
3762 getResult().
getType().getElementType()) {
3763 return emitOpError() <<
": element types of " << getVec1().getType()
3764 <<
" and " << getResult().getType() <<
" don't match";
3767 const uint64_t maxValidIndex =
3768 getVec1().getType().getSize() + getVec2().getType().getSize() - 1;
3770 getIndices().getAsRange<cir::IntAttr>(), [&](cir::IntAttr idxAttr) {
3771 return idxAttr.getSInt() != -1 && idxAttr.getUInt() > maxValidIndex;
3773 return emitOpError() <<
": index for __builtin_shufflevector must be "
3774 "less than the total number of vector elements";
3783OpFoldResult cir::VecShuffleDynamicOp::fold(FoldAdaptor adaptor) {
3784 mlir::Attribute vec = adaptor.getVec();
3785 mlir::Attribute indices = adaptor.getIndices();
3786 if (mlir::isa_and_nonnull<cir::ConstVectorAttr>(vec) &&
3787 mlir::isa_and_nonnull<cir::ConstVectorAttr>(indices)) {
3788 auto vecAttr = mlir::cast<cir::ConstVectorAttr>(vec);
3789 auto indicesAttr = mlir::cast<cir::ConstVectorAttr>(indices);
3791 mlir::ArrayAttr vecElts = vecAttr.getElts();
3792 mlir::ArrayAttr indicesElts = indicesAttr.getElts();
3794 const uint64_t numElements = vecElts.size();
3797 elements.reserve(numElements);
3799 const uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
3800 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
3801 uint64_t idxValue = idxAttr.getUInt();
3802 uint64_t newIdx = idxValue & maskBits;
3803 elements.push_back(vecElts[newIdx]);
3806 return cir::ConstVectorAttr::get(
3807 getType(), mlir::ArrayAttr::get(getContext(), elements));
3813LogicalResult cir::VecShuffleDynamicOp::verify() {
3815 if (getVec().
getType().getSize() !=
3816 mlir::cast<cir::VectorType>(getIndices().
getType()).getSize()) {
3817 return emitOpError() <<
": the number of elements in " << getVec().getType()
3818 <<
" and " << getIndices().getType() <<
" don't match";
3827LogicalResult cir::VecTernaryOp::verify() {
3832 if (getCond().
getType().getSize() != getLhs().
getType().getSize()) {
3833 return emitOpError() <<
": the number of elements in "
3834 << getCond().getType() <<
" and " << getLhs().getType()
3840OpFoldResult cir::VecTernaryOp::fold(FoldAdaptor adaptor) {
3841 mlir::Attribute cond = adaptor.getCond();
3842 mlir::Attribute lhs = adaptor.getLhs();
3843 mlir::Attribute rhs = adaptor.getRhs();
3845 if (!mlir::isa_and_nonnull<cir::ConstVectorAttr>(cond) ||
3846 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(lhs) ||
3847 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(rhs))
3849 auto condVec = mlir::cast<cir::ConstVectorAttr>(cond);
3850 auto lhsVec = mlir::cast<cir::ConstVectorAttr>(lhs);
3851 auto rhsVec = mlir::cast<cir::ConstVectorAttr>(rhs);
3853 mlir::ArrayAttr condElts = condVec.getElts();
3856 elements.reserve(condElts.size());
3858 for (
const auto &[idx, condAttr] :
3859 llvm::enumerate(condElts.getAsRange<cir::IntAttr>())) {
3860 if (condAttr.getSInt()) {
3861 elements.push_back(lhsVec.getElts()[idx]);
3863 elements.push_back(rhsVec.getElts()[idx]);
3867 cir::VectorType vecTy = getLhs().getType();
3868 return cir::ConstVectorAttr::get(
3869 vecTy, mlir::ArrayAttr::get(getContext(), elements));
3876LogicalResult cir::ComplexCreateOp::verify() {
3879 <<
"operand type of cir.complex.create does not match its result type";
3886OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) {
3887 mlir::Attribute real = adaptor.getReal();
3888 mlir::Attribute imag = adaptor.getImag();
3894 auto realAttr = mlir::cast<mlir::TypedAttr>(real);
3895 auto imagAttr = mlir::cast<mlir::TypedAttr>(imag);
3896 return cir::ConstComplexAttr::get(realAttr, imagAttr);
3903LogicalResult cir::ComplexRealOp::verify() {
3904 mlir::Type operandTy = getOperand().getType();
3905 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
3906 operandTy = complexOperandTy.getElementType();
3909 emitOpError() <<
": result type does not match operand type";
3916OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) {
3917 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
3920 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
3921 return complexCreateOp.getOperand(0);
3924 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
3925 return complex ? complex.getReal() :
nullptr;
3932LogicalResult cir::ComplexImagOp::verify() {
3933 mlir::Type operandTy = getOperand().getType();
3934 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
3935 operandTy = complexOperandTy.getElementType();
3938 emitOpError() <<
": result type does not match operand type";
3945OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) {
3946 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
3949 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
3950 return complexCreateOp.getOperand(1);
3953 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
3954 return complex ? complex.getImag() :
nullptr;
3961LogicalResult cir::ComplexRealPtrOp::verify() {
3962 mlir::Type resultPointeeTy =
getType().getPointee();
3963 cir::PointerType operandPtrTy = getOperand().getType();
3964 auto operandPointeeTy =
3965 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
3967 if (resultPointeeTy != operandPointeeTy.getElementType()) {
3968 return emitOpError() <<
": result type does not match operand type";
3978LogicalResult cir::ComplexImagPtrOp::verify() {
3979 mlir::Type resultPointeeTy =
getType().getPointee();
3980 cir::PointerType operandPtrTy = getOperand().getType();
3981 auto operandPointeeTy =
3982 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
3984 if (resultPointeeTy != operandPointeeTy.getElementType()) {
3985 return emitOpError()
3986 <<
"cir.complex.imag_ptr result type does not match operand type";
3997 llvm::function_ref<llvm::APInt(
const llvm::APInt &)> func,
3998 bool poisonZero =
false) {
3999 if (mlir::isa_and_present<cir::PoisonAttr>(inputAttr)) {
4004 auto input = mlir::dyn_cast_if_present<IntAttr>(inputAttr);
4008 llvm::APInt inputValue = input.getValue();
4009 if (poisonZero && inputValue.isZero())
4010 return cir::PoisonAttr::get(input.getType());
4012 llvm::APInt resultValue = func(inputValue);
4013 return IntAttr::get(input.getType(), resultValue);
4016OpFoldResult BitClrsbOp::fold(FoldAdaptor adaptor) {
4017 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4018 unsigned resultValue =
4019 inputValue.getBitWidth() - inputValue.getSignificantBits();
4020 return llvm::APInt(inputValue.getBitWidth(), resultValue);
4024OpFoldResult BitClzOp::fold(FoldAdaptor adaptor) {
4027 [](
const llvm::APInt &inputValue) {
4028 unsigned resultValue = inputValue.countLeadingZeros();
4029 return llvm::APInt(inputValue.getBitWidth(), resultValue);
4034OpFoldResult BitCtzOp::fold(FoldAdaptor adaptor) {
4037 [](
const llvm::APInt &inputValue) {
4038 return llvm::APInt(inputValue.getBitWidth(),
4039 inputValue.countTrailingZeros());
4044OpFoldResult BitFfsOp::fold(FoldAdaptor adaptor) {
4045 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4046 unsigned trailingZeros = inputValue.countTrailingZeros();
4048 trailingZeros == inputValue.getBitWidth() ? 0 : trailingZeros + 1;
4049 return llvm::APInt(inputValue.getBitWidth(), result);
4053OpFoldResult BitParityOp::fold(FoldAdaptor adaptor) {
4054 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4055 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount() % 2);
4059OpFoldResult BitPopcountOp::fold(FoldAdaptor adaptor) {
4060 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4061 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount());
4065OpFoldResult BitReverseOp::fold(FoldAdaptor adaptor) {
4066 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4067 return inputValue.reverseBits();
4071OpFoldResult ByteSwapOp::fold(FoldAdaptor adaptor) {
4072 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4073 return inputValue.byteSwap();
4077OpFoldResult RotateOp::fold(FoldAdaptor adaptor) {
4078 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()) ||
4079 mlir::isa_and_present<cir::PoisonAttr>(adaptor.getAmount())) {
4081 return cir::PoisonAttr::get(
getType());
4084 auto input = mlir::dyn_cast_if_present<IntAttr>(adaptor.getInput());
4085 auto amount = mlir::dyn_cast_if_present<IntAttr>(adaptor.getAmount());
4086 if (!input && !amount)
4095 llvm::APInt inputValue;
4097 inputValue = input.getValue();
4098 if (inputValue.isZero() || inputValue.isAllOnes()) {
4104 uint64_t amountValue;
4106 amountValue = amount.getValue().urem(getInput().
getType().getWidth());
4107 if (amountValue == 0) {
4113 if (!input || !amount)
4116 assert(inputValue.getBitWidth() == getInput().
getType().getWidth() &&
4117 "input value must have the same bit width as the input type");
4119 llvm::APInt resultValue;
4121 resultValue = inputValue.rotl(amountValue);
4123 resultValue = inputValue.rotr(amountValue);
4125 return IntAttr::get(input.getContext(), input.getType(), resultValue);
4132void cir::InlineAsmOp::print(OpAsmPrinter &p) {
4133 p <<
'(' << getAsmFlavor() <<
", ";
4138 auto *nameIt = names.begin();
4139 auto *attrIt = getOperandAttrs().begin();
4141 for (mlir::OperandRange ops : getAsmOperands()) {
4142 p << *nameIt <<
" = ";
4145 llvm::interleaveComma(llvm::make_range(ops.begin(), ops.end()), p,
4147 p.printOperand(value);
4148 p <<
" : " << value.getType();
4149 if (mlir::isa<mlir::UnitAttr>(*attrIt))
4150 p <<
" (maybe_memory)";
4159 p.printString(getAsmString());
4161 p.printString(getConstraints());
4165 if (getSideEffects())
4166 p <<
" side_effects";
4168 std::array elidedAttrs{
4169 llvm::StringRef(
"asm_flavor"), llvm::StringRef(
"asm_string"),
4170 llvm::StringRef(
"constraints"), llvm::StringRef(
"operand_attrs"),
4171 llvm::StringRef(
"operands_segments"), llvm::StringRef(
"side_effects")};
4172 p.printOptionalAttrDict(getOperation()->getAttrs(), elidedAttrs);
4174 if (
auto v = getRes())
4175 p <<
" -> " << v.getType();
4178void cir::InlineAsmOp::build(OpBuilder &odsBuilder, OperationState &odsState,
4180 StringRef asmString, StringRef constraints,
4181 bool sideEffects, cir::AsmFlavor asmFlavor,
4185 for (
auto operandRange : asmOperands) {
4186 segments.push_back(operandRange.size());
4187 odsState.addOperands(operandRange);
4190 odsState.addAttribute(
4191 "operands_segments",
4192 DenseI32ArrayAttr::get(odsBuilder.getContext(), segments));
4193 odsState.addAttribute(
"asm_string", odsBuilder.getStringAttr(asmString));
4194 odsState.addAttribute(
"constraints", odsBuilder.getStringAttr(constraints));
4195 odsState.addAttribute(
"asm_flavor",
4196 AsmFlavorAttr::get(odsBuilder.getContext(), asmFlavor));
4199 odsState.addAttribute(
"side_effects", odsBuilder.getUnitAttr());
4201 odsState.addAttribute(
"operand_attrs", odsBuilder.getArrayAttr(operandAttrs));
4204ParseResult cir::InlineAsmOp::parse(OpAsmParser &parser,
4205 OperationState &result) {
4208 std::string asmString, constraints;
4210 MLIRContext *ctxt = parser.getBuilder().getContext();
4212 auto error = [&](
const Twine &msg) -> LogicalResult {
4213 return parser.emitError(parser.getCurrentLocation(), msg);
4216 auto expected = [&](
const std::string &c) {
4217 return error(
"expected '" + c +
"'");
4220 if (parser.parseLParen().failed())
4221 return expected(
"(");
4223 auto flavor = FieldParser<AsmFlavor, AsmFlavor>::parse(parser);
4225 return error(
"Unknown AsmFlavor");
4227 if (parser.parseComma().failed())
4228 return expected(
",");
4230 auto parseValue = [&](
Value &v) {
4231 OpAsmParser::UnresolvedOperand op;
4233 if (parser.parseOperand(op) || parser.parseColon())
4234 return error(
"can't parse operand");
4237 if (parser.parseType(typ).failed())
4238 return error(
"can't parse operand type");
4240 if (parser.resolveOperand(op, typ, tmp))
4241 return error(
"can't resolve operand");
4243 return mlir::success();
4246 auto parseOperands = [&](llvm::StringRef
name) {
4247 if (parser.parseKeyword(name).failed())
4248 return error(
"expected " + name +
" operands here");
4249 if (parser.parseEqual().failed())
4250 return expected(
"=");
4251 if (parser.parseLSquare().failed())
4252 return expected(
"[");
4255 if (parser.parseOptionalRSquare().succeeded()) {
4256 operandsGroupSizes.push_back(size);
4257 if (parser.parseComma())
4258 return expected(
",");
4259 return mlir::success();
4262 auto parseOperand = [&]() {
4264 if (parseValue(val).succeeded()) {
4265 result.operands.push_back(val);
4268 if (parser.parseOptionalLParen().failed()) {
4269 operandAttrs.push_back(mlir::DictionaryAttr::get(ctxt));
4270 return mlir::success();
4273 if (parser.parseKeyword(
"maybe_memory").succeeded()) {
4274 operandAttrs.push_back(mlir::UnitAttr::get(ctxt));
4275 if (parser.parseRParen())
4276 return expected(
")");
4277 return mlir::success();
4279 return expected(
"maybe_memory");
4282 return mlir::failure();
4285 if (parser.parseCommaSeparatedList(parseOperand).failed())
4286 return mlir::failure();
4288 if (parser.parseRSquare().failed() || parser.parseComma().failed())
4289 return expected(
"]");
4290 operandsGroupSizes.push_back(size);
4291 return mlir::success();
4294 if (parseOperands(
"out").failed() || parseOperands(
"in").failed() ||
4295 parseOperands(
"in_out").failed())
4296 return error(
"failed to parse operands");
4298 if (parser.parseLBrace())
4299 return expected(
"{");
4300 if (parser.parseString(&asmString))
4301 return error(
"asm string parsing failed");
4302 if (parser.parseString(&constraints))
4303 return error(
"constraints string parsing failed");
4304 if (parser.parseRBrace())
4305 return expected(
"}");
4306 if (parser.parseRParen())
4307 return expected(
")");
4309 if (parser.parseOptionalKeyword(
"side_effects").succeeded())
4310 result.attributes.set(
"side_effects", UnitAttr::get(ctxt));
4312 if (parser.parseOptionalAttrDict(result.attributes).failed())
4313 return mlir::failure();
4315 if (parser.parseOptionalArrow().succeeded() &&
4316 parser.parseType(resType).failed())
4317 return mlir::failure();
4319 result.attributes.set(
"asm_flavor", AsmFlavorAttr::get(ctxt, *flavor));
4320 result.attributes.set(
"asm_string", StringAttr::get(ctxt, asmString));
4321 result.attributes.set(
"constraints", StringAttr::get(ctxt, constraints));
4322 result.attributes.set(
"operand_attrs", ArrayAttr::get(ctxt, operandAttrs));
4323 result.getOrAddProperties<InlineAsmOp::Properties>().operands_segments =
4324 parser.getBuilder().getDenseI32ArrayAttr(operandsGroupSizes);
4326 result.addTypes(TypeRange{resType});
4328 return mlir::success();
4335template <
typename ThrowOpTy>
4338 return mlir::success();
4340 if (op.getNumOperands() != 0) {
4341 if (op.getTypeInfo())
4342 return mlir::success();
4343 return op.emitOpError() <<
"'type_info' symbol attribute missing";
4346 return mlir::failure();
4351mlir::LogicalResult cir::TryThrowOp::verify() {
4359LogicalResult cir::AtomicFetchOp::verify() {
4360 if (getBinop() != cir::AtomicFetchKind::Add &&
4361 getBinop() != cir::AtomicFetchKind::Sub &&
4362 getBinop() != cir::AtomicFetchKind::Max &&
4363 getBinop() != cir::AtomicFetchKind::Min &&
4364 getBinop() != cir::AtomicFetchKind::Maximum &&
4365 getBinop() != cir::AtomicFetchKind::Minimum &&
4366 getBinop() != cir::AtomicFetchKind::MaximumNum &&
4367 getBinop() != cir::AtomicFetchKind::MinimumNum &&
4368 !mlir::isa<cir::IntType>(getVal().
getType()))
4369 return emitError(
"only atomic add, sub, max, min, maximum, minimum, "
4370 "maximum_num, and minimum_num operation could operate on "
4371 "floating-point values");
4373 if ((getBinop() == cir::AtomicFetchKind::Maximum ||
4374 getBinop() == cir::AtomicFetchKind::Minimum ||
4375 getBinop() == cir::AtomicFetchKind::MaximumNum ||
4376 getBinop() == cir::AtomicFetchKind::MinimumNum) &&
4377 !mlir::isa<cir::FPTypeInterface>(getVal().
getType()))
4378 return emitError(
"atomic maximum, minimum, maximum_num, and minimum_num "
4379 "operation could only operate on floating-point values");
4388LogicalResult cir::TypeInfoAttr::verify(
4389 ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
4390 ::mlir::Type type, ::mlir::ArrayAttr typeInfoData) {
4392 if (cir::ConstRecordAttr::verify(emitError, type, typeInfoData).failed())
4402void cir::TryOp::getSuccessorRegions(
4403 mlir::RegionBranchPoint point,
4406 if (!point.isParent()) {
4407 regions.emplace_back(getOperation());
4411 regions.push_back(mlir::RegionSuccessor(&getTryRegion()));
4415 for (mlir::Region &handlerRegion : this->getHandlerRegions())
4416 regions.push_back(mlir::RegionSuccessor(&handlerRegion));
4419mlir::ValueRange cir::TryOp::getSuccessorInputs(RegionSuccessor successor) {
4420 return successor.isOperation() ? ValueRange(getOperation()->getResults())
4424LogicalResult cir::TryOp::verify() {
4425 mlir::ArrayAttr handlerTypes = getHandlerTypes();
4426 if (!handlerTypes) {
4427 if (!getHandlerRegions().empty())
4429 "handler regions must be empty when no handler types are present");
4433 mlir::MutableArrayRef<mlir::Region> handlerRegions = getHandlerRegions();
4437 if (handlerRegions.size() != handlerTypes.size())
4439 "number of handler regions and handler types must match");
4441 for (
const auto &[typeAttr, handlerRegion] :
4442 llvm::zip(handlerTypes, handlerRegions)) {
4444 mlir::Block &entryBlock = handlerRegion.front();
4445 if (entryBlock.getNumArguments() != 1 ||
4446 !mlir::isa<cir::EhTokenType>(entryBlock.getArgument(0).getType()))
4448 "handler region must have a single '!cir.eh_token' argument");
4451 if (mlir::isa<cir::UnwindAttr>(typeAttr))
4457 if (entryBlock.empty())
4458 return emitOpError(
"catch handler region must not be empty");
4459 mlir::Operation *firstOp = &entryBlock.front();
4460 if (mlir::isa_and_present<cir::ConstructCatchParamOp>(firstOp))
4461 firstOp = firstOp->getNextNode();
4462 if (!firstOp || !mlir::isa<cir::BeginCatchOp>(firstOp))
4464 "catch handler region must start with 'cir.begin_catch'");
4472 mlir::MutableArrayRef<mlir::Region> handlerRegions,
4473 mlir::ArrayAttr handlerTypes) {
4477 for (
const auto [typeIdx, typeAttr] : llvm::enumerate(handlerTypes)) {
4481 if (mlir::isa<cir::CatchAllAttr>(typeAttr)) {
4482 printer <<
"catch all ";
4483 }
else if (mlir::isa<cir::UnwindAttr>(typeAttr)) {
4484 printer <<
"unwind ";
4486 printer <<
"catch [type ";
4487 printer.printAttribute(typeAttr);
4492 mlir::Region ®ion = handlerRegions[typeIdx];
4493 if (!region.empty() && region.front().getNumArguments() > 0) {
4495 printer.printRegionArgument(region.front().getArgument(0));
4499 printer.printRegion(region,
4506 mlir::OpAsmParser &parser,
4508 mlir::ArrayAttr &handlerTypes) {
4510 auto parseCheckedCatcherRegion = [&]() -> mlir::ParseResult {
4511 handlerRegions.emplace_back(
new mlir::Region);
4513 mlir::Region &currRegion = *handlerRegions.back();
4517 if (parser.parseLParen())
4519 mlir::OpAsmParser::Argument arg;
4520 if (parser.parseArgument(arg,
true))
4522 regionArgs.push_back(arg);
4523 if (parser.parseRParen())
4526 mlir::SMLoc regionLoc = parser.getCurrentLocation();
4527 if (parser.parseRegion(currRegion, regionArgs)) {
4528 handlerRegions.clear();
4532 if (currRegion.empty())
4533 return parser.emitError(regionLoc,
"handler region shall not be empty");
4535 if (!(currRegion.back().mightHaveTerminator() &&
4536 currRegion.back().getTerminator()))
4537 return parser.emitError(
4538 regionLoc,
"blocks are expected to be explicitly terminated");
4543 bool hasCatchAll =
false;
4545 while (parser.parseOptionalKeyword(
"catch").succeeded()) {
4546 bool hasLSquare = parser.parseOptionalLSquare().succeeded();
4548 llvm::StringRef attrStr;
4549 if (parser.parseOptionalKeyword(&attrStr, {
"all",
"type"}).failed())
4550 return parser.emitError(parser.getCurrentLocation(),
4551 "expected 'all' or 'type' keyword");
4553 bool isCatchAll = attrStr ==
"all";
4556 return parser.emitError(parser.getCurrentLocation(),
4557 "can't have more than one catch all");
4561 mlir::Attribute exceptionRTTIAttr;
4562 if (!isCatchAll && parser.parseAttribute(exceptionRTTIAttr).failed())
4563 return parser.emitError(parser.getCurrentLocation(),
4564 "expected valid RTTI info attribute");
4566 catcherAttrs.push_back(isCatchAll
4567 ? cir::CatchAllAttr::get(parser.getContext())
4568 : exceptionRTTIAttr);
4570 if (hasLSquare && isCatchAll)
4571 return parser.emitError(parser.getCurrentLocation(),
4572 "catch all dosen't need RTTI info attribute");
4574 if (hasLSquare && parser.parseRSquare().failed())
4575 return parser.emitError(parser.getCurrentLocation(),
4576 "expected `]` after RTTI info attribute");
4578 if (parseCheckedCatcherRegion().failed())
4579 return mlir::failure();
4582 if (parser.parseOptionalKeyword(
"unwind").succeeded()) {
4584 return parser.emitError(parser.getCurrentLocation(),
4585 "unwind can't be used with catch all");
4587 catcherAttrs.push_back(cir::UnwindAttr::get(parser.getContext()));
4588 if (parseCheckedCatcherRegion().failed())
4589 return mlir::failure();
4592 handlerTypes = parser.getBuilder().getArrayAttr(catcherAttrs);
4593 return mlir::success();
4601cir::EhTypeIdOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
4602 Operation *op = symbolTable.lookupNearestSymbolFrom(*
this, getTypeSymAttr());
4603 if (!isa_and_nonnull<GlobalOp>(op))
4604 return emitOpError(
"'")
4605 << getTypeSym() <<
"' does not reference a valid cir.global";
4613LogicalResult cir::LifetimeStartOp::verify() {
4617LogicalResult cir::LifetimeEndOp::verify() {
4625LogicalResult cir::ConstructCatchParamOp::verifySymbolUses(
4626 SymbolTableCollection &symbolTable) {
4627 auto copyFnAttr = getCopyFnAttr();
4631 symbolTable.lookupNearestSymbolFrom<cir::FuncOp>(*
this, getCopyFnAttr());
4633 return emitOpError(
"'")
4634 << *getCopyFn() <<
"' does not reference a valid cir.func";
4636 if (!fn->hasAttr(cir::CIRDialect::getCatchCopyThunkAttrName()))
4637 return emitOpError(
"catch-init copy_fn must be tagged with the ")
4638 << cir::CIRDialect::getCatchCopyThunkAttrName() <<
" attribute";
4640 cir::FuncType fnType = fn.getFunctionType();
4641 if (fnType.getNumInputs() != 2 || !fnType.hasVoidReturn())
4642 return emitOpError(
"catch-init copy_fn must take two pointer arguments and "
4645 if (fnType.getInput(0) != getParamAddr().
getType())
4646 return emitOpError(
"first argument of catch-init copy_fn must match the "
4647 "type of 'param_addr'");
4649 if (fnType.getInput(1) != getParamAddr().
getType())
4651 "second argument of catch-init copy_fn must be a pointer "
4652 "to the catch type");
4663 SmallVectorImpl<Block *> &catchDestinations,
4664 Block *&defaultDestination,
4665 mlir::UnitAttr &defaultIsCatchAll) {
4667 if (parser.parseLSquare())
4671 bool hasCatchAll =
false;
4672 bool hasUnwind =
false;
4675 auto parseHandler = [&]() -> ParseResult {
4677 if (succeeded(parser.parseOptionalKeyword(
"catch_all"))) {
4679 return parser.emitError(parser.getCurrentLocation(),
4680 "duplicate 'catch_all' handler");
4682 return parser.emitError(parser.getCurrentLocation(),
4683 "cannot have both 'catch_all' and 'unwind'");
4686 if (parser.parseColon().failed())
4689 if (parser.parseSuccessor(defaultDestination).failed())
4695 if (succeeded(parser.parseOptionalKeyword(
"unwind"))) {
4697 return parser.emitError(parser.getCurrentLocation(),
4698 "duplicate 'unwind' handler");
4700 return parser.emitError(parser.getCurrentLocation(),
4701 "cannot have both 'catch_all' and 'unwind'");
4704 if (parser.parseColon().failed())
4707 if (parser.parseSuccessor(defaultDestination).failed())
4715 if (parser.parseKeyword(
"catch").failed())
4718 if (parser.parseLParen().failed())
4721 mlir::Attribute catchTypeAttr;
4722 if (parser.parseAttribute(catchTypeAttr).failed())
4724 handlerTypes.push_back(catchTypeAttr);
4726 if (parser.parseRParen().failed())
4729 if (parser.parseColon().failed())
4733 if (parser.parseSuccessor(dest).failed())
4735 catchDestinations.push_back(dest);
4739 if (parser.parseCommaSeparatedList(parseHandler).failed())
4742 if (parser.parseRSquare().failed())
4746 if (!hasCatchAll && !hasUnwind)
4747 return parser.emitError(parser.getCurrentLocation(),
4748 "must have either 'catch_all' or 'unwind' handler");
4751 if (!handlerTypes.empty())
4752 catchTypes = parser.getBuilder().getArrayAttr(handlerTypes);
4755 defaultIsCatchAll = parser.getBuilder().getUnitAttr();
4761 mlir::ArrayAttr catchTypes,
4762 SuccessorRange catchDestinations,
4763 Block *defaultDestination,
4764 mlir::UnitAttr defaultIsCatchAll) {
4772 llvm::zip(catchTypes, catchDestinations),
4775 p.printAttribute(std::get<0>(i));
4777 p.printSuccessor(std::get<1>(i));
4789 if (defaultIsCatchAll)
4790 p <<
" catch_all : ";
4793 p.printSuccessor(defaultDestination);
4803bool cir::StdFindOp::signatureMatches(mlir::TypeRange operands,
4804 mlir::TypeRange results) {
4805 if (operands.size() != getNumArgs() || results.size() != 1)
4807 mlir::Type iterTy = operands[0];
4808 return iterTy == operands[1] && iterTy == operands[2] && iterTy == results[0];
4815#define GET_OP_CLASSES
4816#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)
static LogicalResult verifyLoopCleanup(LoopOpTy op)
static void printEhDispatchDestinations(OpAsmPrinter &p, cir::EhDispatchOp op, mlir::ArrayAttr catchTypes, SuccessorRange catchDestinations, Block *defaultDestination, mlir::UnitAttr defaultIsCatchAll)
static mlir::LogicalResult checkReturnAndFunction(cir::ReturnOp op, cir::FuncOp function)
static void printCopyTypes(mlir::OpAsmPrinter &printer, mlir::Operation *, mlir::Type srcType, mlir::Type dstType)
static bool isCirFunctionPointerType(mlir::Type ty)
static LogicalResult verifyMemberPtrCast(Operation *op, mlir::Value src, mlir::Type resultTy)
static bool isFloatingPointCastKind(cir::CastKind kind)
static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, mlir::OperationState &result, bool hasDestinationBlocks=false)
static bool isIntOrBoolCast(cir::CastOp op)
static ParseResult parseAssumeBundle(OpAsmParser &p, cir::AssumeBundleKindAttr &bundleKindAttr, llvm::SmallVector< mlir::OpAsmParser::UnresolvedOperand, 4 > &bundleArgs, llvm::SmallVector< mlir::Type, 1 > &bundleArgTypes)
static ParseResult parseEhDispatchDestinations(OpAsmParser &parser, mlir::ArrayAttr &catchTypes, SmallVectorImpl< Block * > &catchDestinations, Block *&defaultDestination, mlir::UnitAttr &defaultIsCatchAll)
static void printConstant(OpAsmPrinter &p, Attribute value)
static mlir::ParseResult parseOmittedTerminatorRegion(mlir::OpAsmParser &parser, mlir::Region ®ion)
static void printAssumeBundle(OpAsmPrinter &p, cir::AssumeOp op, cir::AssumeBundleKindAttr kindAttr, OperandRange bundleArgs, TypeRange bundleArgTypes)
ParseResult parseInlineKindAttr(OpAsmParser &parser, cir::InlineKindAttr &inlineKindAttr)
void printInlineKindAttr(OpAsmPrinter &p, cir::InlineKindAttr inlineKindAttr)
static ParseResult parseSwitchFlatOpCases(OpAsmParser &parser, Type flagType, mlir::ArrayAttr &caseValues, SmallVectorImpl< Block * > &caseDestinations, SmallVectorImpl< llvm::SmallVector< OpAsmParser::UnresolvedOperand > > &caseOperands, SmallVectorImpl< llvm::SmallVector< Type > > &caseOperandTypes)
<cases> ::= [ (case (, case )* )?
void printGlobalAddressSpaceValue(mlir::AsmPrinter &printer, cir::GlobalOp op, mlir::ptr::MemorySpaceAttrInterface attr)
static void printCallCommon(mlir::Operation *op, mlir::FlatSymbolRefAttr calleeSym, mlir::Value indirectCallee, mlir::OpAsmPrinter &printer, bool isNothrow, cir::SideEffect sideEffect, ArrayAttr argAttrs, ArrayAttr resAttrs, mlir::Block *normalDest=nullptr, mlir::Block *unwindDest=nullptr)
static LogicalResult verifyCallCommInSymbolUses(mlir::Operation *op, SymbolTableCollection &symbolTable)
static LogicalResult ensureRegionTerm(OpAsmParser &parser, Region ®ion, SMLoc errLoc)
static ParseResult parseGlobalOpTypeAndInitialValue(OpAsmParser &parser, TypeAttr &typeAttr, Attribute &initialValueAttr, mlir::Region &ctorRegion, mlir::Region &dtorRegion)
void printIndirectBrOpSucessors(OpAsmPrinter &p, cir::IndirectBrOp op, Type flagType, SuccessorRange succs, OperandRangeRange succOperands, const TypeRangeRange &succOperandsTypes)
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.
mlir::OptionalParseResult parseGlobalAddressSpaceValue(mlir::AsmParser &p, mlir::ptr::MemorySpaceAttrInterface &attr)
static void printSwitchFlatOpCases(OpAsmPrinter &p, cir::SwitchFlatOp op, Type flagType, mlir::ArrayAttr caseValues, SuccessorRange caseDestinations, OperandRangeRange caseOperands, const TypeRangeRange &caseOperandTypes)
static LogicalResult verifyProducedBy(Operation *op, Value operand, StringRef operandName)
static mlir::ParseResult parseTryCallDestinations(mlir::OpAsmParser &parser, mlir::OperationState &result)
static void printGlobalOpTypeAndInitialValue(OpAsmPrinter &p, cir::GlobalOp op, TypeAttr type, Attribute initAttr, mlir::Region &ctorRegion, mlir::Region &dtorRegion)
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 void printTryHandlerRegions(mlir::OpAsmPrinter &printer, cir::TryOp op, mlir::MutableArrayRef< mlir::Region > handlerRegions, mlir::ArrayAttr handlerTypes)
ParseResult parseIndirectBrOpSucessors(OpAsmParser &parser, Type &flagType, SmallVectorImpl< Block * > &succOperandBlocks, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand > > &succOperands, SmallVectorImpl< SmallVector< Type > > &succOperandsTypes)
static bool omitRegionTerm(mlir::Region &r)
static mlir::ParseResult parseCopyTypes(mlir::OpAsmParser &parser, mlir::Type &srcType, mlir::Type &dstType)
static void printOmittedTerminatorRegion(mlir::OpAsmPrinter &printer, cir::ScopeOp &op, mlir::Region ®ion)
static ParseResult parseConstantValue(OpAsmParser &parser, mlir::Attribute &valueAttr)
static LogicalResult verifyArrayCtorDtor(Op op)
static mlir::LogicalResult verifyThrowOpImpl(ThrowOpTy op)
static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType, mlir::Attribute attrType)
static mlir::ParseResult parseTryHandlerRegions(mlir::OpAsmParser &parser, llvm::SmallVectorImpl< std::unique_ptr< mlir::Region > > &handlerRegions, mlir::ArrayAttr &handlerTypes)
#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
void buildTerminatedBody(mlir::OpBuilder &builder, mlir::Location loc)
mlir::ptr::MemorySpaceAttrInterface normalizeDefaultAddressSpace(mlir::ptr::MemorySpaceAttrInterface addrSpace)
Normalize LangAddressSpace::Default to null (empty attribute).
const AstTypeMatcher< BuiltinType > builtinType
const internal::VariadicAllOfMatcher< Attr > attr
const AstTypeMatcher< RecordType > recordType
StringRef getName(const HeaderType T)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
static bool memberFuncPtrCast()
static bool opCallCallConv()
static bool opScopeCleanupRegion()
static bool supportIFuncAttr()