19#include "mlir/IR/Attributes.h"
20#include "mlir/IR/DialectImplementation.h"
21#include "mlir/IR/PatternMatch.h"
22#include "mlir/Interfaces/ControlFlowInterfaces.h"
23#include "mlir/Interfaces/FunctionImplementation.h"
24#include "mlir/Support/LLVM.h"
26#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
27#include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc"
29#include "llvm/ADT/SetOperations.h"
30#include "llvm/ADT/SmallSet.h"
31#include "llvm/ADT/TypeSwitch.h"
32#include "llvm/Support/LogicalResult.h"
41struct CIROpAsmDialectInterface :
public OpAsmDialectInterface {
42 using OpAsmDialectInterface::OpAsmDialectInterface;
44 AliasResult getAlias(Type type, raw_ostream &os)
const final {
45 if (
auto recordType = dyn_cast<cir::RecordType>(type)) {
48 os <<
"rec_anon_" <<
recordType.getKindAsStr();
50 os <<
"rec_" << nameAttr.getValue();
51 return AliasResult::OverridableAlias;
53 if (
auto intType = dyn_cast<cir::IntType>(type)) {
56 unsigned width = intType.getWidth();
57 if (width < 8 || !llvm::isPowerOf2_32(width))
58 return AliasResult::NoAlias;
59 os << intType.getAlias();
60 return AliasResult::OverridableAlias;
62 if (
auto voidType = dyn_cast<cir::VoidType>(type)) {
63 os << voidType.getAlias();
64 return AliasResult::OverridableAlias;
67 return AliasResult::NoAlias;
70 AliasResult getAlias(Attribute attr, raw_ostream &os)
const final {
71 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr)) {
72 os << (boolAttr.getValue() ?
"true" :
"false");
73 return AliasResult::FinalAlias;
75 if (
auto bitfield = mlir::dyn_cast<cir::BitfieldInfoAttr>(attr)) {
76 os <<
"bfi_" << bitfield.getName().str();
77 return AliasResult::FinalAlias;
79 if (
auto dynCastInfoAttr = mlir::dyn_cast<cir::DynamicCastInfoAttr>(attr)) {
80 os << dynCastInfoAttr.getAlias();
81 return AliasResult::FinalAlias;
83 if (
auto cmpThreeWayInfoAttr =
84 mlir::dyn_cast<cir::CmpThreeWayInfoAttr>(attr)) {
85 os << cmpThreeWayInfoAttr.getAlias();
86 return AliasResult::FinalAlias;
88 return AliasResult::NoAlias;
93void cir::CIRDialect::initialize() {
98#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
100 addInterfaces<CIROpAsmDialectInterface>();
103Operation *cir::CIRDialect::materializeConstant(mlir::OpBuilder &builder,
104 mlir::Attribute value,
106 mlir::Location loc) {
107 return cir::ConstantOp::create(builder, loc, type,
108 mlir::cast<mlir::TypedAttr>(value));
120 for (
auto en : llvm::enumerate(keywords)) {
121 if (succeeded(parser.parseOptionalKeyword(en.value())))
128template <
typename Ty>
struct EnumTraits {};
130#define REGISTER_ENUM_TYPE(Ty) \
131 template <> struct EnumTraits<cir::Ty> { \
132 static llvm::StringRef stringify(cir::Ty value) { \
133 return stringify##Ty(value); \
135 static unsigned getMaxEnumVal() { return cir::getMaxEnumValFor##Ty(); } \
146template <
typename EnumTy,
typename RetTy = EnumTy>
149 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
150 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
154 return static_cast<RetTy
>(defaultValue);
155 return static_cast<RetTy
>(index);
159template <
typename EnumTy,
typename RetTy = EnumTy>
162 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
163 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
168 result =
static_cast<RetTy
>(index);
176 Location eLoc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
177 OpBuilder builder(parser.getBuilder().getContext());
182 builder.createBlock(®ion);
184 Block &block = region.back();
186 if (!block.empty() && block.back().hasTrait<OpTrait::IsTerminator>())
190 if (!region.hasOneBlock())
191 return parser.emitError(errLoc,
192 "multi-block region must not omit terminator");
195 builder.setInsertionPointToEnd(&block);
196 cir::YieldOp::create(builder, eLoc);
202 const auto singleNonEmptyBlock = r.hasOneBlock() && !r.back().empty();
203 const auto yieldsNothing = [&r]() {
204 auto y = dyn_cast<cir::YieldOp>(r.back().getTerminator());
205 return y && y.getArgs().empty();
207 return singleNonEmptyBlock && yieldsNothing();
215 cir::InlineKindAttr &inlineKindAttr) {
217 static constexpr llvm::StringRef keywords[] = {
"no_inline",
"always_inline",
221 llvm::StringRef keyword;
222 if (parser.parseOptionalKeyword(&keyword, keywords).failed()) {
228 auto inlineKindResult = ::cir::symbolizeEnum<::cir::InlineKind>(keyword);
229 if (!inlineKindResult) {
230 return parser.emitError(parser.getCurrentLocation(),
"expected one of [")
232 <<
"] for inlineKind, got: " << keyword;
236 ::cir::InlineKindAttr::get(parser.getContext(), *inlineKindResult);
241 if (inlineKindAttr) {
242 p <<
" " << stringifyInlineKind(inlineKindAttr.getValue());
250 mlir::Region ®ion) {
251 auto regionLoc = parser.getCurrentLocation();
252 if (parser.parseRegion(region))
261 mlir::Region ®ion) {
262 printer.printRegion(region,
267mlir::OptionalParseResult
269 mlir::ptr::MemorySpaceAttrInterface &attr);
272 mlir::ptr::MemorySpaceAttrInterface attr);
278void cir::AllocaOp::build(mlir::OpBuilder &odsBuilder,
279 mlir::OperationState &odsState, mlir::Type addr,
280 mlir::Type allocaType, llvm::StringRef name,
281 mlir::IntegerAttr alignment) {
282 odsState.addAttribute(getAllocaTypeAttrName(odsState.name),
283 mlir::TypeAttr::get(allocaType));
284 odsState.addAttribute(getNameAttrName(odsState.name),
285 odsBuilder.getStringAttr(name));
287 odsState.addAttribute(getAlignmentAttrName(odsState.name), alignment);
289 odsState.addTypes(addr);
297 auto ptrTy = mlir::cast<cir::PointerType>(op.getAddr().getType());
298 mlir::Type pointeeTy = ptrTy.getPointee();
300 mlir::Block &body = op.getBody().front();
301 if (body.getNumArguments() != 1)
302 return op.emitOpError(
"body must have exactly one block argument");
304 auto expectedEltPtrTy =
305 mlir::dyn_cast<cir::PointerType>(body.getArgument(0).getType());
306 if (!expectedEltPtrTy)
307 return op.emitOpError(
"block argument must be a !cir.ptr type");
309 if (op.getNumElements()) {
310 auto recTy = mlir::dyn_cast<cir::RecordType>(pointeeTy);
312 return op.emitOpError(
313 "when 'num_elements' is present, 'addr' must be a pointer to a "
316 if (expectedEltPtrTy != ptrTy)
317 return op.emitOpError(
"when 'num_elements' is present, 'addr' type must "
318 "match the block argument type");
320 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(pointeeTy);
322 return op.emitOpError(
323 "when 'num_elements' is absent, 'addr' must be a pointer to a "
326 mlir::Type innerEltTy = arrayTy.getElementType();
327 while (
auto nested = mlir::dyn_cast<cir::ArrayType>(innerEltTy))
328 innerEltTy = nested.getElementType();
330 auto recTy = mlir::dyn_cast<cir::RecordType>(innerEltTy);
332 return op.emitOpError(
333 "the block argument type must be a pointer to a !cir.record type");
335 if (expectedEltPtrTy.getPointee() != innerEltTy)
336 return op.emitOpError(
337 "block argument pointee type must match the innermost array "
344LogicalResult cir::ArrayCtor::verify() {
348 mlir::Region &partialDtor = getPartialDtor();
349 if (!partialDtor.empty()) {
350 mlir::Block &dtorBlock = partialDtor.front();
351 if (dtorBlock.getNumArguments() != 1)
352 return emitOpError(
"partial_dtor must have exactly one block argument");
354 auto bodyArgTy = getBody().front().getArgument(0).getType();
355 if (dtorBlock.getArgument(0).getType() != bodyArgTy)
356 return emitOpError(
"partial_dtor block argument type must match "
357 "the body block argument type");
367LogicalResult cir::BreakOp::verify() {
368 if (!getOperation()->getParentOfType<LoopOpInterface>() &&
369 !getOperation()->getParentOfType<SwitchOp>())
370 return emitOpError(
"must be within a loop");
382void cir::ConditionOp::getSuccessorRegions(
388 if (
auto loopOp = dyn_cast<LoopOpInterface>(getOperation()->getParentOp())) {
389 regions.emplace_back(&loopOp.getBody());
390 regions.push_back(RegionSuccessor::parent());
394 auto await = cast<AwaitOp>(getOperation()->getParentOp());
395 regions.emplace_back(&await.getResume());
396 regions.emplace_back(&await.getSuspend());
400cir::ConditionOp::getMutableSuccessorOperands(RegionSuccessor point) {
402 return MutableOperandRange(getOperation(), 0, 0);
406cir::ResumeOp::getMutableSuccessorOperands(RegionSuccessor point) {
408 return MutableOperandRange(getOperation(), 0, 0);
411LogicalResult cir::ConditionOp::verify() {
412 if (!isa<LoopOpInterface, AwaitOp>(getOperation()->getParentOp()))
413 return emitOpError(
"condition must be within a conditional region");
422 mlir::Attribute attrType) {
423 if (isa<cir::ConstPtrAttr>(attrType)) {
424 if (!mlir::isa<cir::PointerType>(opType))
425 return op->emitOpError(
426 "pointer constant initializing a non-pointer type");
430 if (isa<cir::DataMemberAttr, cir::MethodAttr>(attrType)) {
436 if (isa<cir::ZeroAttr>(attrType)) {
437 if (isa<cir::RecordType, cir::ArrayType, cir::VectorType, cir::ComplexType>(
440 return op->emitOpError(
441 "zero expects struct, array, vector, or complex type");
444 if (mlir::isa<cir::UndefAttr>(attrType)) {
445 if (!mlir::isa<cir::VoidType>(opType))
447 return op->emitOpError(
"undef expects non-void type");
450 if (mlir::isa<cir::BoolAttr>(attrType)) {
451 if (!mlir::isa<cir::BoolType>(opType))
452 return op->emitOpError(
"result type (")
453 << opType <<
") must be '!cir.bool' for '" << attrType <<
"'";
457 if (mlir::isa<cir::IntAttr, cir::FPAttr>(attrType)) {
458 auto at = cast<TypedAttr>(attrType);
459 if (at.getType() != opType) {
460 return op->emitOpError(
"result type (")
461 << opType <<
") does not match value type (" << at.getType()
467 if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
468 cir::ConstComplexAttr, cir::ConstRecordAttr,
469 cir::GlobalViewAttr, cir::PoisonAttr, cir::TypeInfoAttr,
470 cir::VTableAttr>(attrType))
473 assert(isa<TypedAttr>(attrType) &&
"What else could we be looking at here?");
474 return op->emitOpError(
"global with type ")
475 << cast<TypedAttr>(attrType).getType() <<
" not yet supported";
478LogicalResult cir::ConstantOp::verify() {
485OpFoldResult cir::ConstantOp::fold(FoldAdaptor ) {
493LogicalResult cir::ContinueOp::verify() {
494 if (!getOperation()->getParentOfType<LoopOpInterface>())
495 return emitOpError(
"must be within a loop");
503LogicalResult cir::CastOp::verify() {
504 mlir::Type resType =
getType();
505 mlir::Type srcType = getSrc().getType();
509 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
510 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
511 if (srcPtrTy && resPtrTy && (
getKind() != cir::CastKind::address_space))
512 if (srcPtrTy.getAddrSpace() != resPtrTy.getAddrSpace()) {
513 return emitOpError() <<
"result type address space does not match the "
514 "address space of the operand";
517 if (mlir::isa<cir::VectorType>(srcType) &&
518 mlir::isa<cir::VectorType>(resType)) {
521 srcType = mlir::dyn_cast<cir::VectorType>(srcType).getElementType();
522 resType = mlir::dyn_cast<cir::VectorType>(resType).getElementType();
526 case cir::CastKind::int_to_bool: {
527 if (!mlir::isa<cir::BoolType>(resType))
528 return emitOpError() <<
"requires !cir.bool type for result";
529 if (!mlir::isa<cir::IntType>(srcType))
530 return emitOpError() <<
"requires !cir.int type for source";
533 case cir::CastKind::ptr_to_bool: {
534 if (!mlir::isa<cir::BoolType>(resType))
535 return emitOpError() <<
"requires !cir.bool type for result";
536 if (!mlir::isa<cir::PointerType>(srcType))
537 return emitOpError() <<
"requires !cir.ptr type for source";
540 case cir::CastKind::integral: {
541 if (!mlir::isa<cir::IntType>(resType))
542 return emitOpError() <<
"requires !cir.int type for result";
543 if (!mlir::isa<cir::IntType>(srcType))
544 return emitOpError() <<
"requires !cir.int type for source";
547 case cir::CastKind::array_to_ptrdecay: {
548 const auto arrayPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
549 const auto flatPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
550 if (!arrayPtrTy || !flatPtrTy)
551 return emitOpError() <<
"requires !cir.ptr type for source and result";
556 case cir::CastKind::bitcast: {
558 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
559 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
561 if (srcPtrTy && resPtrTy) {
567 case cir::CastKind::floating: {
568 if (!mlir::isa<cir::FPTypeInterface>(srcType) ||
569 !mlir::isa<cir::FPTypeInterface>(resType))
570 return emitOpError() <<
"requires !cir.float type for source and result";
573 case cir::CastKind::float_to_int: {
574 if (!mlir::isa<cir::FPTypeInterface>(srcType))
575 return emitOpError() <<
"requires !cir.float type for source";
576 if (!mlir::dyn_cast<cir::IntType>(resType))
577 return emitOpError() <<
"requires !cir.int type for result";
580 case cir::CastKind::int_to_ptr: {
581 if (!mlir::dyn_cast<cir::IntType>(srcType))
582 return emitOpError() <<
"requires !cir.int type for source";
583 if (!mlir::dyn_cast<cir::PointerType>(resType))
584 return emitOpError() <<
"requires !cir.ptr type for result";
587 case cir::CastKind::ptr_to_int: {
588 if (!mlir::dyn_cast<cir::PointerType>(srcType))
589 return emitOpError() <<
"requires !cir.ptr type for source";
590 if (!mlir::dyn_cast<cir::IntType>(resType))
591 return emitOpError() <<
"requires !cir.int type for result";
594 case cir::CastKind::float_to_bool: {
595 if (!mlir::isa<cir::FPTypeInterface>(srcType))
596 return emitOpError() <<
"requires !cir.float type for source";
597 if (!mlir::isa<cir::BoolType>(resType))
598 return emitOpError() <<
"requires !cir.bool type for result";
601 case cir::CastKind::bool_to_int: {
602 if (!mlir::isa<cir::BoolType>(srcType))
603 return emitOpError() <<
"requires !cir.bool type for source";
604 if (!mlir::isa<cir::IntType>(resType))
605 return emitOpError() <<
"requires !cir.int type for result";
608 case cir::CastKind::int_to_float: {
609 if (!mlir::isa<cir::IntType>(srcType))
610 return emitOpError() <<
"requires !cir.int type for source";
611 if (!mlir::isa<cir::FPTypeInterface>(resType))
612 return emitOpError() <<
"requires !cir.float type for result";
615 case cir::CastKind::bool_to_float: {
616 if (!mlir::isa<cir::BoolType>(srcType))
617 return emitOpError() <<
"requires !cir.bool type for source";
618 if (!mlir::isa<cir::FPTypeInterface>(resType))
619 return emitOpError() <<
"requires !cir.float type for result";
622 case cir::CastKind::address_space: {
623 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
624 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
625 if (!srcPtrTy || !resPtrTy)
626 return emitOpError() <<
"requires !cir.ptr type for source and result";
627 if (srcPtrTy.getPointee() != resPtrTy.getPointee())
628 return emitOpError() <<
"requires two types differ in addrspace only";
631 case cir::CastKind::float_to_complex: {
632 if (!mlir::isa<cir::FPTypeInterface>(srcType))
633 return emitOpError() <<
"requires !cir.float type for source";
634 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
636 return emitOpError() <<
"requires !cir.complex type for result";
637 if (srcType != resComplexTy.getElementType())
638 return emitOpError() <<
"requires source type match result element type";
641 case cir::CastKind::int_to_complex: {
642 if (!mlir::isa<cir::IntType>(srcType))
643 return emitOpError() <<
"requires !cir.int type for source";
644 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
646 return emitOpError() <<
"requires !cir.complex type for result";
647 if (srcType != resComplexTy.getElementType())
648 return emitOpError() <<
"requires source type match result element type";
651 case cir::CastKind::float_complex_to_real: {
652 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
654 return emitOpError() <<
"requires !cir.complex type for source";
655 if (!mlir::isa<cir::FPTypeInterface>(resType))
656 return emitOpError() <<
"requires !cir.float type for result";
657 if (srcComplexTy.getElementType() != resType)
658 return emitOpError() <<
"requires source element type match result type";
661 case cir::CastKind::int_complex_to_real: {
662 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
664 return emitOpError() <<
"requires !cir.complex type for source";
665 if (!mlir::isa<cir::IntType>(resType))
666 return emitOpError() <<
"requires !cir.int type for result";
667 if (srcComplexTy.getElementType() != resType)
668 return emitOpError() <<
"requires source element type match result type";
671 case cir::CastKind::float_complex_to_bool: {
672 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
673 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
675 <<
"requires floating point !cir.complex type for source";
676 if (!mlir::isa<cir::BoolType>(resType))
677 return emitOpError() <<
"requires !cir.bool type for result";
680 case cir::CastKind::int_complex_to_bool: {
681 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
682 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
684 <<
"requires floating point !cir.complex type for source";
685 if (!mlir::isa<cir::BoolType>(resType))
686 return emitOpError() <<
"requires !cir.bool type for result";
689 case cir::CastKind::float_complex: {
690 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
691 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
693 <<
"requires floating point !cir.complex type for source";
694 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
695 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
697 <<
"requires floating point !cir.complex type for result";
700 case cir::CastKind::float_complex_to_int_complex: {
701 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
702 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
704 <<
"requires floating point !cir.complex type for source";
705 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
706 if (!resComplexTy || !resComplexTy.isIntegerComplex())
707 return emitOpError() <<
"requires integer !cir.complex type for result";
710 case cir::CastKind::int_complex: {
711 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
712 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
713 return emitOpError() <<
"requires integer !cir.complex type for source";
714 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
715 if (!resComplexTy || !resComplexTy.isIntegerComplex())
716 return emitOpError() <<
"requires integer !cir.complex type for result";
719 case cir::CastKind::int_complex_to_float_complex: {
720 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
721 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
722 return emitOpError() <<
"requires integer !cir.complex type for source";
723 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
724 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
726 <<
"requires floating point !cir.complex type for result";
729 case cir::CastKind::member_ptr_to_bool: {
730 if (!mlir::isa<cir::DataMemberType, cir::MethodType>(srcType))
732 <<
"requires !cir.data_member or !cir.method type for source";
733 if (!mlir::isa<cir::BoolType>(resType))
734 return emitOpError() <<
"requires !cir.bool type for result";
738 llvm_unreachable(
"Unknown CastOp kind?");
742 auto kind = op.getKind();
743 return kind == cir::CastKind::bool_to_int ||
744 kind == cir::CastKind::int_to_bool ||
kind == cir::CastKind::integral;
748 cir::CastOp head = op, tail = op;
754 op = head.getSrc().getDefiningOp<cir::CastOp>();
762 if (head.getKind() == cir::CastKind::bool_to_int &&
763 tail.getKind() == cir::CastKind::int_to_bool)
764 return head.getSrc();
769 if (head.getKind() == cir::CastKind::int_to_bool &&
770 tail.getKind() == cir::CastKind::int_to_bool)
771 return head.getResult();
776OpFoldResult cir::CastOp::fold(FoldAdaptor adaptor) {
777 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getSrc())) {
779 return cir::PoisonAttr::get(getContext(),
getType());
784 case cir::CastKind::integral: {
786 auto foldOrder = getSrc().getDefiningOp()->fold(foldResults);
787 if (foldOrder.succeeded() && mlir::isa<mlir::Attribute>(foldResults[0]))
788 return mlir::cast<mlir::Attribute>(foldResults[0]);
791 case cir::CastKind::bitcast:
792 case cir::CastKind::address_space:
793 case cir::CastKind::float_complex:
794 case cir::CastKind::int_complex: {
808 if (
auto srcConst = getSrc().getDefiningOp<cir::ConstantOp>()) {
810 case cir::CastKind::integral: {
811 mlir::Type srcTy = getSrc().getType();
813 assert(mlir::isa<cir::VectorType>(srcTy) ==
814 mlir::isa<cir::VectorType>(
getType()));
815 if (mlir::isa<cir::VectorType>(srcTy))
818 auto srcIntTy = mlir::cast<cir::IntType>(srcTy);
819 auto dstIntTy = mlir::cast<cir::IntType>(
getType());
822 ? srcConst.getIntValue().sextOrTrunc(dstIntTy.getWidth())
823 : srcConst.getIntValue().zextOrTrunc(dstIntTy.getWidth());
824 return cir::IntAttr::get(dstIntTy, newVal);
837mlir::OperandRange cir::CallOp::getArgOperands() {
839 return getArgs().drop_front(1);
843mlir::MutableOperandRange cir::CallOp::getArgOperandsMutable() {
844 mlir::MutableOperandRange args = getArgsMutable();
846 return args.slice(1, args.size() - 1);
850mlir::Value cir::CallOp::getIndirectCall() {
851 assert(isIndirect());
852 return getOperand(0);
856Value cir::CallOp::getArgOperand(
unsigned i) {
859 return getOperand(i);
863unsigned cir::CallOp::getNumArgOperands() {
865 return this->getOperation()->getNumOperands() - 1;
866 return this->getOperation()->getNumOperands();
869static mlir::ParseResult
871 mlir::OperationState &result) {
872 mlir::Block *normalDestSuccessor;
873 if (parser.parseSuccessor(normalDestSuccessor))
874 return mlir::failure();
876 if (parser.parseComma())
877 return mlir::failure();
879 mlir::Block *unwindDestSuccessor;
880 if (parser.parseSuccessor(unwindDestSuccessor))
881 return mlir::failure();
883 result.addSuccessors(normalDestSuccessor);
884 result.addSuccessors(unwindDestSuccessor);
885 return mlir::success();
889 mlir::OperationState &result,
890 bool hasDestinationBlocks =
false) {
893 mlir::FlatSymbolRefAttr calleeAttr;
897 .parseOptionalAttribute(calleeAttr, CIRDialect::getCalleeAttrName(),
900 OpAsmParser::UnresolvedOperand indirectVal;
902 if (parser.parseOperand(indirectVal).failed())
904 ops.push_back(indirectVal);
907 if (parser.parseLParen())
908 return mlir::failure();
910 opsLoc = parser.getCurrentLocation();
911 if (parser.parseOperandList(ops))
912 return mlir::failure();
913 if (parser.parseRParen())
914 return mlir::failure();
916 if (hasDestinationBlocks &&
918 return ::mlir::failure();
921 if (parser.parseOptionalKeyword(
"nothrow").succeeded())
922 result.addAttribute(CIRDialect::getNoThrowAttrName(),
923 mlir::UnitAttr::get(parser.getContext()));
925 if (parser.parseOptionalKeyword(
"side_effect").succeeded()) {
926 if (parser.parseLParen().failed())
928 cir::SideEffect sideEffect;
931 if (parser.parseRParen().failed())
933 auto attr = cir::SideEffectAttr::get(parser.getContext(), sideEffect);
934 result.addAttribute(CIRDialect::getSideEffectAttrName(), attr);
937 if (parser.parseOptionalAttrDict(result.attributes))
938 return ::mlir::failure();
940 if (parser.parseColon())
941 return ::mlir::failure();
947 if (call_interface_impl::parseFunctionSignature(parser, argTypes, argAttrs,
948 resultTypes, resultAttrs))
949 return mlir::failure();
951 if (resultTypes.size() > 1 || resultAttrs.size() > 1)
952 return parser.emitError(
953 parser.getCurrentLocation(),
954 "functions with multiple return types are not supported");
956 result.addTypes(resultTypes);
958 if (parser.resolveOperands(ops, argTypes, opsLoc, result.operands))
959 return mlir::failure();
961 if (!resultAttrs.empty() && resultAttrs[0])
963 CIRDialect::getResAttrsAttrName(),
964 mlir::ArrayAttr::get(parser.getContext(), {resultAttrs[0]}));
969 bool argAttrsEmpty =
true;
971 llvm::transform(argAttrs, std::back_inserter(convertedArgAttrs),
972 [&](DictionaryAttr da) -> mlir::Attribute {
974 argAttrsEmpty =
false;
978 if (!argAttrsEmpty) {
983 argAttrsRef = argAttrsRef.drop_front();
985 result.addAttribute(CIRDialect::getArgAttrsAttrName(),
986 mlir::ArrayAttr::get(parser.getContext(), argAttrsRef));
989 return mlir::success();
994 mlir::Value indirectCallee, mlir::OpAsmPrinter &printer,
995 bool isNothrow, cir::SideEffect sideEffect, ArrayAttr argAttrs,
996 ArrayAttr resAttrs, mlir::Block *normalDest =
nullptr,
997 mlir::Block *unwindDest =
nullptr) {
1000 auto callLikeOp = mlir::cast<cir::CIRCallOpInterface>(op);
1001 auto ops = callLikeOp.getArgOperands();
1005 printer.printAttributeWithoutType(calleeSym);
1008 assert(indirectCallee);
1009 printer << indirectCallee;
1012 printer <<
"(" << ops <<
")";
1015 assert(unwindDest &&
"expected two successors");
1016 auto tryCall = cast<cir::TryCallOp>(op);
1017 printer <<
' ' << tryCall.getNormalDest();
1020 printer << tryCall.getUnwindDest();
1024 printer <<
" nothrow";
1026 if (sideEffect != cir::SideEffect::All) {
1027 printer <<
" side_effect(";
1028 printer << stringifySideEffect(sideEffect);
1033 CIRDialect::getCalleeAttrName(),
1034 CIRDialect::getNoThrowAttrName(),
1035 CIRDialect::getSideEffectAttrName(),
1036 CIRDialect::getOperandSegmentSizesAttrName(),
1037 llvm::StringRef(
"res_attrs"),
1038 llvm::StringRef(
"arg_attrs")};
1039 printer.printOptionalAttrDict(op->getAttrs(), elidedAttrs);
1041 if (calleeSym || !argAttrs) {
1042 call_interface_impl::printFunctionSignature(
1043 printer, op->getOperands().getTypes(), argAttrs,
1044 false, op->getResultTypes(), resAttrs);
1052 shimmedArgAttrs.push_back(mlir::DictionaryAttr::get(op->getContext(), {}));
1053 shimmedArgAttrs.append(argAttrs.begin(), argAttrs.end());
1054 call_interface_impl::printFunctionSignature(
1055 printer, op->getOperands().getTypes(),
1056 mlir::ArrayAttr::get(op->getContext(), shimmedArgAttrs),
1057 false, op->getResultTypes(), resAttrs);
1061mlir::ParseResult cir::CallOp::parse(mlir::OpAsmParser &parser,
1062 mlir::OperationState &result) {
1066void cir::CallOp::print(mlir::OpAsmPrinter &p) {
1067 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
1068 cir::SideEffect sideEffect = getSideEffect();
1069 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
1070 sideEffect, getArgAttrsAttr(), getResAttrsAttr());
1075 SymbolTableCollection &symbolTable) {
1077 op->getAttrOfType<FlatSymbolRefAttr>(CIRDialect::getCalleeAttrName());
1080 return mlir::success();
1083 auto fn = symbolTable.lookupNearestSymbolFrom<cir::FuncOp>(op, fnAttr);
1085 return op->emitOpError() <<
"'" << fnAttr.getValue()
1086 <<
"' does not reference a valid function";
1088 auto callIf = dyn_cast<cir::CIRCallOpInterface>(op);
1089 assert(callIf &&
"expected CIR call interface to be always available");
1093 auto fnType = fn.getFunctionType();
1094 if (!fn.getNoProto()) {
1095 unsigned numCallOperands = callIf.getNumArgOperands();
1096 unsigned numFnOpOperands = fnType.getNumInputs();
1098 if (!fnType.isVarArg() && numCallOperands != numFnOpOperands)
1099 return op->emitOpError(
"incorrect number of operands for callee");
1100 if (fnType.isVarArg() && numCallOperands < numFnOpOperands)
1101 return op->emitOpError(
"too few operands for callee");
1103 for (
unsigned i = 0, e = numFnOpOperands; i != e; ++i)
1104 if (callIf.getArgOperand(i).getType() != fnType.getInput(i))
1105 return op->emitOpError(
"operand type mismatch: expected operand type ")
1106 << fnType.getInput(i) <<
", but provided "
1107 << op->getOperand(i).getType() <<
" for operand number " << i;
1113 if (fnType.hasVoidReturn() && op->getNumResults() != 0)
1114 return op->emitOpError(
"callee returns void but call has results");
1117 if (!fnType.hasVoidReturn() && op->getNumResults() != 1)
1118 return op->emitOpError(
"incorrect number of results for callee");
1121 if (!fnType.hasVoidReturn() &&
1122 op->getResultTypes().front() != fnType.getReturnType()) {
1123 return op->emitOpError(
"result type mismatch: expected ")
1124 << fnType.getReturnType() <<
", but provided "
1125 << op->getResult(0).getType();
1128 return mlir::success();
1132cir::CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1140mlir::OperandRange cir::TryCallOp::getArgOperands() {
1142 return getArgs().drop_front(1);
1146mlir::MutableOperandRange cir::TryCallOp::getArgOperandsMutable() {
1147 mlir::MutableOperandRange args = getArgsMutable();
1149 return args.slice(1, args.size() - 1);
1153mlir::Value cir::TryCallOp::getIndirectCall() {
1154 assert(isIndirect());
1155 return getOperand(0);
1159Value cir::TryCallOp::getArgOperand(
unsigned i) {
1162 return getOperand(i);
1166unsigned cir::TryCallOp::getNumArgOperands() {
1168 return this->getOperation()->getNumOperands() - 1;
1169 return this->getOperation()->getNumOperands();
1173cir::TryCallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1177mlir::ParseResult cir::TryCallOp::parse(mlir::OpAsmParser &parser,
1178 mlir::OperationState &result) {
1182void cir::TryCallOp::print(::mlir::OpAsmPrinter &p) {
1183 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
1184 cir::SideEffect sideEffect = getSideEffect();
1185 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
1186 sideEffect, getArgAttrsAttr(), getResAttrsAttr(),
1187 getNormalDest(), getUnwindDest());
1195 cir::FuncOp function) {
1197 if (op.getNumOperands() > 1)
1198 return op.emitOpError() <<
"expects at most 1 return operand";
1201 auto expectedTy = function.getFunctionType().getReturnType();
1203 (op.getNumOperands() == 0 ? cir::VoidType::get(op.getContext())
1204 : op.getOperand(0).getType());
1205 if (actualTy != expectedTy)
1206 return op.emitOpError() <<
"returns " << actualTy
1207 <<
" but enclosing function returns " << expectedTy;
1209 return mlir::success();
1212mlir::LogicalResult cir::ReturnOp::verify() {
1215 auto *fnOp = getOperation()->getParentOp();
1216 while (!isa<cir::FuncOp>(fnOp))
1217 fnOp = fnOp->getParentOp();
1230ParseResult cir::IfOp::parse(OpAsmParser &parser, OperationState &result) {
1232 result.regions.reserve(2);
1233 Region *thenRegion = result.addRegion();
1234 Region *elseRegion = result.addRegion();
1236 mlir::Builder &builder = parser.getBuilder();
1237 OpAsmParser::UnresolvedOperand cond;
1238 Type boolType = cir::BoolType::get(builder.getContext());
1240 if (parser.parseOperand(cond) ||
1241 parser.resolveOperand(cond, boolType, result.operands))
1245 mlir::SMLoc parseThenLoc = parser.getCurrentLocation();
1246 if (parser.parseRegion(*thenRegion, {}, {}))
1253 if (!parser.parseOptionalKeyword(
"else")) {
1254 mlir::SMLoc parseElseLoc = parser.getCurrentLocation();
1255 if (parser.parseRegion(*elseRegion, {}, {}))
1262 if (parser.parseOptionalAttrDict(result.attributes))
1267void cir::IfOp::print(OpAsmPrinter &p) {
1268 p <<
" " << getCondition() <<
" ";
1269 mlir::Region &thenRegion = this->getThenRegion();
1270 p.printRegion(thenRegion,
1275 mlir::Region &elseRegion = this->getElseRegion();
1276 if (!elseRegion.empty()) {
1278 p.printRegion(elseRegion,
1283 p.printOptionalAttrDict(getOperation()->getAttrs());
1289 cir::YieldOp::create(builder, loc);
1297void cir::IfOp::getSuccessorRegions(mlir::RegionBranchPoint point,
1298 SmallVectorImpl<RegionSuccessor> ®ions) {
1300 if (!point.isParent()) {
1301 regions.push_back(RegionSuccessor::parent());
1306 Region *elseRegion = &this->getElseRegion();
1307 if (elseRegion->empty())
1308 elseRegion =
nullptr;
1311 regions.push_back(RegionSuccessor(&getThenRegion()));
1314 regions.push_back(RegionSuccessor(elseRegion));
1319mlir::ValueRange cir::IfOp::getSuccessorInputs(RegionSuccessor successor) {
1320 return successor.isParent() ? ValueRange(getOperation()->getResults())
1324void cir::IfOp::build(OpBuilder &builder, OperationState &result,
Value cond,
1327 assert(thenBuilder &&
"the builder callback for 'then' must be present");
1328 result.addOperands(cond);
1330 OpBuilder::InsertionGuard guard(builder);
1331 Region *thenRegion = result.addRegion();
1332 builder.createBlock(thenRegion);
1333 thenBuilder(builder, result.location);
1335 Region *elseRegion = result.addRegion();
1336 if (!withElseRegion)
1339 builder.createBlock(elseRegion);
1340 elseBuilder(builder, result.location);
1352void cir::ScopeOp::getSuccessorRegions(
1353 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1355 if (!point.isParent()) {
1356 regions.push_back(RegionSuccessor::parent());
1361 regions.push_back(RegionSuccessor(&getScopeRegion()));
1364mlir::ValueRange cir::ScopeOp::getSuccessorInputs(RegionSuccessor successor) {
1365 return successor.isParent() ? ValueRange(getOperation()->getResults())
1369void cir::ScopeOp::build(
1370 OpBuilder &builder, OperationState &result,
1371 function_ref<
void(OpBuilder &, Type &, Location)> scopeBuilder) {
1372 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1374 OpBuilder::InsertionGuard guard(builder);
1375 Region *scopeRegion = result.addRegion();
1376 builder.createBlock(scopeRegion);
1380 scopeBuilder(builder, yieldTy, result.location);
1383 result.addTypes(TypeRange{yieldTy});
1386void cir::ScopeOp::build(
1387 OpBuilder &builder, OperationState &result,
1388 function_ref<
void(OpBuilder &, Location)> scopeBuilder) {
1389 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1390 OpBuilder::InsertionGuard guard(builder);
1391 Region *scopeRegion = result.addRegion();
1392 builder.createBlock(scopeRegion);
1394 scopeBuilder(builder, result.location);
1397LogicalResult cir::ScopeOp::verify() {
1399 return emitOpError() <<
"cir.scope must not be empty since it should "
1400 "include at least an implicit cir.yield ";
1403 mlir::Block &lastBlock =
getRegion().back();
1404 if (lastBlock.empty() || !lastBlock.mightHaveTerminator() ||
1405 !lastBlock.getTerminator()->hasTrait<OpTrait::IsTerminator>())
1406 return emitOpError() <<
"last block of cir.scope must be terminated";
1410LogicalResult cir::ScopeOp::fold(FoldAdaptor ,
1411 SmallVectorImpl<OpFoldResult> &results) {
1416 if (block.getOperations().size() != 1)
1419 auto yield = dyn_cast<cir::YieldOp>(block.front());
1424 if (getNumResults() != 1 || yield.getNumOperands() != 1)
1427 results.push_back(yield.getOperand(0));
1435void cir::CleanupScopeOp::getSuccessorRegions(
1436 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1437 if (!point.isParent()) {
1438 regions.push_back(RegionSuccessor::parent());
1443 regions.push_back(RegionSuccessor(&getBodyRegion()));
1444 regions.push_back(RegionSuccessor(&getCleanupRegion()));
1448cir::CleanupScopeOp::getSuccessorInputs(RegionSuccessor successor) {
1449 return ValueRange();
1452LogicalResult cir::CleanupScopeOp::canonicalize(CleanupScopeOp op,
1453 PatternRewriter &rewriter) {
1454 auto isRegionTrivial = [](Region ®ion) {
1455 assert(!region.empty() &&
"CleanupScopeOp regions must not be empty");
1456 if (!region.hasOneBlock())
1458 Block &block = llvm::getSingleElement(region);
1459 return llvm::hasSingleElement(block) &&
1460 isa<cir::YieldOp>(llvm::getSingleElement(block));
1463 Region &body = op.getBodyRegion();
1464 Region &
cleanup = op.getCleanupRegion();
1468 if (op.getCleanupKind() == CleanupKind::EH && isRegionTrivial(body)) {
1469 rewriter.eraseOp(op);
1475 if (!isRegionTrivial(
cleanup) || !body.hasOneBlock())
1478 Block &bodyBlock = body.front();
1479 if (!isa<cir::YieldOp>(bodyBlock.getTerminator()))
1482 Operation *yield = bodyBlock.getTerminator();
1483 rewriter.inlineBlockBefore(&bodyBlock, op);
1484 rewriter.eraseOp(yield);
1485 rewriter.eraseOp(op);
1489void cir::CleanupScopeOp::build(
1490 OpBuilder &builder, OperationState &result, CleanupKind cleanupKind,
1491 function_ref<
void(OpBuilder &, Location)> bodyBuilder,
1492 function_ref<
void(OpBuilder &, Location)> cleanupBuilder) {
1493 result.addAttribute(getCleanupKindAttrName(result.name),
1494 CleanupKindAttr::get(builder.getContext(), cleanupKind));
1496 OpBuilder::InsertionGuard guard(builder);
1499 Region *bodyRegion = result.addRegion();
1500 builder.createBlock(bodyRegion);
1502 bodyBuilder(builder, result.location);
1505 Region *cleanupRegion = result.addRegion();
1506 builder.createBlock(cleanupRegion);
1508 cleanupBuilder(builder, result.location);
1523LogicalResult cir::BrOp::canonicalize(BrOp op, PatternRewriter &rewriter) {
1524 Block *src = op->getBlock();
1525 Block *dst = op.getDest();
1532 if (src->getNumSuccessors() != 1 || dst->getSinglePredecessor() != src)
1537 if (isa<cir::LabelOp, cir::IndirectBrOp>(dst->front()))
1540 auto operands = op.getDestOperands();
1541 rewriter.eraseOp(op);
1542 rewriter.mergeBlocks(dst, src, operands);
1546mlir::SuccessorOperands cir::BrOp::getSuccessorOperands(
unsigned index) {
1547 assert(index == 0 &&
"invalid successor index");
1548 return mlir::SuccessorOperands(getDestOperandsMutable());
1559mlir::SuccessorOperands
1560cir::IndirectBrOp::getSuccessorOperands(
unsigned index) {
1561 assert(index < getNumSuccessors() &&
"invalid successor index");
1562 return mlir::SuccessorOperands(getSuccOperandsMutable()[index]);
1566 OpAsmParser &parser, Type &flagType,
1567 SmallVectorImpl<Block *> &succOperandBlocks,
1570 if (failed(parser.parseCommaSeparatedList(
1571 OpAsmParser::Delimiter::Square,
1573 Block *destination = nullptr;
1574 SmallVector<OpAsmParser::UnresolvedOperand> operands;
1575 SmallVector<Type> operandTypes;
1577 if (parser.parseSuccessor(destination).failed())
1580 if (succeeded(parser.parseOptionalLParen())) {
1581 if (failed(parser.parseOperandList(
1582 operands, OpAsmParser::Delimiter::None)) ||
1583 failed(parser.parseColonTypeList(operandTypes)) ||
1584 failed(parser.parseRParen()))
1587 succOperandBlocks.push_back(destination);
1588 succOperands.emplace_back(operands);
1589 succOperandsTypes.emplace_back(operandTypes);
1592 "successor blocks")))
1598 Type flagType, SuccessorRange succs,
1599 OperandRangeRange succOperands,
1600 const TypeRangeRange &succOperandsTypes) {
1603 llvm::zip(succs, succOperands),
1606 p.printSuccessorAndUseList(std::get<0>(i), std::get<1>(i));
1609 if (!succOperands.empty())
1618mlir::SuccessorOperands cir::BrCondOp::getSuccessorOperands(
unsigned index) {
1619 assert(index < getNumSuccessors() &&
"invalid successor index");
1620 return SuccessorOperands(index == 0 ? getDestOperandsTrueMutable()
1621 : getDestOperandsFalseMutable());
1625 if (IntegerAttr condAttr = dyn_cast_if_present<IntegerAttr>(operands.front()))
1626 return condAttr.getValue().isOne() ? getDestTrue() : getDestFalse();
1634void cir::CaseOp::getSuccessorRegions(
1635 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1636 if (!point.isParent()) {
1637 regions.push_back(RegionSuccessor::parent());
1640 regions.push_back(RegionSuccessor(&getCaseRegion()));
1643mlir::ValueRange cir::CaseOp::getSuccessorInputs(RegionSuccessor successor) {
1644 return successor.isParent() ? ValueRange(getOperation()->getResults())
1648void cir::CaseOp::build(OpBuilder &builder, OperationState &result,
1649 ArrayAttr value, CaseOpKind
kind,
1650 OpBuilder::InsertPoint &insertPoint) {
1651 OpBuilder::InsertionGuard guardSwitch(builder);
1652 result.addAttribute(
"value", value);
1653 result.getOrAddProperties<Properties>().
kind =
1654 cir::CaseOpKindAttr::get(builder.getContext(),
kind);
1655 Region *caseRegion = result.addRegion();
1656 builder.createBlock(caseRegion);
1658 insertPoint = builder.saveInsertionPoint();
1665void cir::SwitchOp::getSuccessorRegions(
1666 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ion) {
1667 if (!point.isParent()) {
1668 region.push_back(RegionSuccessor::parent());
1672 region.push_back(RegionSuccessor(&getBody()));
1675mlir::ValueRange cir::SwitchOp::getSuccessorInputs(RegionSuccessor successor) {
1676 return successor.isParent() ? ValueRange(getOperation()->getResults())
1680void cir::SwitchOp::build(OpBuilder &builder, OperationState &result,
1682 assert(switchBuilder &&
"the builder callback for regions must be present");
1683 OpBuilder::InsertionGuard guardSwitch(builder);
1684 Region *switchRegion = result.addRegion();
1685 builder.createBlock(switchRegion);
1686 result.addOperands({cond});
1687 switchBuilder(builder, result.location, result);
1691 walk<mlir::WalkOrder::PreOrder>([&](mlir::Operation *op) {
1693 if (isa<cir::SwitchOp>(op) && op != *
this)
1694 return WalkResult::skip();
1696 if (
auto caseOp = dyn_cast<cir::CaseOp>(op))
1697 cases.push_back(caseOp);
1699 return WalkResult::advance();
1704 collectCases(cases);
1706 if (getBody().empty())
1709 if (!isa<YieldOp>(getBody().front().back()))
1712 if (!llvm::all_of(getBody().front(),
1713 [](Operation &op) {
return isa<CaseOp, YieldOp>(op); }))
1716 return llvm::all_of(cases, [
this](CaseOp op) {
1717 return op->getParentOfType<SwitchOp>() == *
this;
1725void cir::SwitchFlatOp::build(OpBuilder &builder, OperationState &result,
1726 Value value, Block *defaultDestination,
1727 ValueRange defaultOperands,
1729 BlockRange caseDestinations,
1732 std::vector<mlir::Attribute> caseValuesAttrs;
1733 for (
const APInt &val : caseValues)
1734 caseValuesAttrs.push_back(cir::IntAttr::get(value.getType(), val));
1735 mlir::ArrayAttr attrs = ArrayAttr::get(builder.getContext(), caseValuesAttrs);
1737 build(builder, result, value, defaultOperands, caseOperands, attrs,
1738 defaultDestination, caseDestinations);
1744 OpAsmParser &parser, Type flagType, mlir::ArrayAttr &caseValues,
1745 SmallVectorImpl<Block *> &caseDestinations,
1749 if (failed(parser.parseLSquare()))
1751 if (succeeded(parser.parseOptionalRSquare()))
1755 auto parseCase = [&]() {
1757 if (failed(parser.parseInteger(value)))
1760 values.push_back(cir::IntAttr::get(flagType, value));
1765 if (parser.parseColon() || parser.parseSuccessor(destination))
1767 if (!parser.parseOptionalLParen()) {
1768 if (parser.parseOperandList(operands, OpAsmParser::Delimiter::None,
1770 parser.parseColonTypeList(operandTypes) || parser.parseRParen())
1773 caseDestinations.push_back(destination);
1774 caseOperands.emplace_back(operands);
1775 caseOperandTypes.emplace_back(operandTypes);
1778 if (failed(parser.parseCommaSeparatedList(parseCase)))
1781 caseValues = ArrayAttr::get(flagType.getContext(), values);
1783 return parser.parseRSquare();
1787 Type flagType, mlir::ArrayAttr caseValues,
1788 SuccessorRange caseDestinations,
1789 OperandRangeRange caseOperands,
1790 const TypeRangeRange &caseOperandTypes) {
1800 llvm::zip(caseValues, caseDestinations),
1803 mlir::Attribute a = std::get<0>(i);
1804 p << mlir::cast<cir::IntAttr>(a).getValue();
1806 p.printSuccessorAndUseList(std::get<1>(i), caseOperands[index++]);
1821 mlir::Attribute &valueAttr) {
1823 return parser.parseAttribute(valueAttr,
"value", attr);
1827 p.printAttribute(value);
1830mlir::LogicalResult cir::GlobalOp::verify() {
1833 if (getInitialValue().has_value()) {
1845void cir::GlobalOp::build(
1846 OpBuilder &odsBuilder, OperationState &odsState, llvm::StringRef sym_name,
1847 mlir::Type sym_type,
bool isConstant,
1848 mlir::ptr::MemorySpaceAttrInterface addrSpace,
1849 cir::GlobalLinkageKind linkage,
1850 function_ref<
void(OpBuilder &, Location)> ctorBuilder,
1851 function_ref<
void(OpBuilder &, Location)> dtorBuilder) {
1852 odsState.addAttribute(getSymNameAttrName(odsState.name),
1853 odsBuilder.getStringAttr(sym_name));
1854 odsState.addAttribute(getSymTypeAttrName(odsState.name),
1855 mlir::TypeAttr::get(sym_type));
1856 auto &properties = odsState.getOrAddProperties<cir::GlobalOp::Properties>();
1857 properties.setConstant(isConstant);
1861 odsState.addAttribute(getAddrSpaceAttrName(odsState.name), addrSpace);
1863 cir::GlobalLinkageKindAttr linkageAttr =
1864 cir::GlobalLinkageKindAttr::get(odsBuilder.getContext(), linkage);
1865 odsState.addAttribute(getLinkageAttrName(odsState.name), linkageAttr);
1867 Region *ctorRegion = odsState.addRegion();
1869 odsBuilder.createBlock(ctorRegion);
1870 ctorBuilder(odsBuilder, odsState.location);
1873 Region *dtorRegion = odsState.addRegion();
1875 odsBuilder.createBlock(dtorRegion);
1876 dtorBuilder(odsBuilder, odsState.location);
1885void cir::GlobalOp::getSuccessorRegions(
1886 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1888 if (!point.isParent()) {
1889 regions.push_back(RegionSuccessor::parent());
1894 Region *ctorRegion = &this->getCtorRegion();
1895 if (ctorRegion->empty())
1896 ctorRegion =
nullptr;
1899 Region *dtorRegion = &this->getDtorRegion();
1900 if (dtorRegion->empty())
1901 dtorRegion =
nullptr;
1905 regions.push_back(RegionSuccessor(ctorRegion));
1907 regions.push_back(RegionSuccessor(dtorRegion));
1910mlir::ValueRange cir::GlobalOp::getSuccessorInputs(RegionSuccessor successor) {
1911 return successor.isParent() ? ValueRange(getOperation()->getResults())
1916 TypeAttr type, Attribute initAttr,
1917 mlir::Region &ctorRegion,
1918 mlir::Region &dtorRegion) {
1919 auto printType = [&]() { p <<
": " << type; };
1920 if (!op.isDeclaration()) {
1922 if (!ctorRegion.empty()) {
1926 p.printRegion(ctorRegion,
1935 if (!dtorRegion.empty()) {
1937 p.printRegion(dtorRegion,
1948 Attribute &initialValueAttr,
1949 mlir::Region &ctorRegion,
1950 mlir::Region &dtorRegion) {
1952 if (parser.parseOptionalEqual().failed()) {
1955 if (parser.parseColonType(opTy))
1960 if (!parser.parseOptionalKeyword(
"ctor")) {
1961 if (parser.parseColonType(opTy))
1963 auto parseLoc = parser.getCurrentLocation();
1964 if (parser.parseRegion(ctorRegion, {}, {}))
1975 assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
1976 "Non-typed attrs shouldn't appear here.");
1977 auto typedAttr = mlir::cast<mlir::TypedAttr>(initialValueAttr);
1978 opTy = typedAttr.getType();
1983 if (!parser.parseOptionalKeyword(
"dtor")) {
1984 auto parseLoc = parser.getCurrentLocation();
1985 if (parser.parseRegion(dtorRegion, {}, {}))
1992 typeAttr = TypeAttr::get(opTy);
2001cir::GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2004 mlir::Operation *op =
2005 symbolTable.lookupNearestSymbolFrom(*
this, getNameAttr());
2006 if (op ==
nullptr || !(isa<GlobalOp>(op) || isa<FuncOp>(op)))
2007 return emitOpError(
"'")
2009 <<
"' does not reference a valid cir.global or cir.func";
2012 mlir::ptr::MemorySpaceAttrInterface symAddrSpaceAttr{};
2013 if (
auto g = dyn_cast<GlobalOp>(op)) {
2014 symTy = g.getSymType();
2015 symAddrSpaceAttr = g.getAddrSpaceAttr();
2018 if (getTls() && !g.getTlsModel())
2019 return emitOpError(
"access to global not marked thread local");
2024 bool getGlobalIsStaticLocal = getStaticLocal();
2025 bool globalIsStaticLocal = g.getStaticLocalGuard().has_value();
2026 if (getGlobalIsStaticLocal != globalIsStaticLocal &&
2027 !getOperation()->getParentOfType<cir::GlobalOp>())
2028 return emitOpError(
"static_local attribute mismatch");
2029 }
else if (
auto f = dyn_cast<FuncOp>(op)) {
2030 symTy = f.getFunctionType();
2032 llvm_unreachable(
"Unexpected operation for GetGlobalOp");
2035 auto resultType = dyn_cast<PointerType>(getAddr().
getType());
2036 if (!resultType || symTy != resultType.getPointee())
2037 return emitOpError(
"result type pointee type '")
2038 << resultType.getPointee() <<
"' does not match type " << symTy
2039 <<
" of the global @" <<
getName();
2041 if (symAddrSpaceAttr != resultType.getAddrSpace()) {
2042 return emitOpError()
2043 <<
"result type address space does not match the address "
2044 "space of the global @"
2056cir::VTableAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2062 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
2064 return emitOpError(
"'")
2065 <<
name <<
"' does not reference a valid cir.global";
2066 std::optional<mlir::Attribute> init = op.getInitialValue();
2069 if (!isa<cir::VTableAttr>(*init))
2070 return emitOpError(
"Expected #cir.vtable in initializer for global '")
2080cir::VTTAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2089 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
2091 return emitOpError(
"'")
2092 <<
name <<
"' does not reference a valid cir.global";
2093 std::optional<mlir::Attribute> init = op.getInitialValue();
2096 if (!isa<cir::ConstArrayAttr>(*init))
2098 "Expected constant array in initializer for global VTT '")
2103LogicalResult cir::VTTAddrPointOp::verify() {
2105 if (
getName() && getSymAddr())
2106 return emitOpError(
"should use either a symbol or value, but not both");
2112 mlir::Type resultType = getAddr().getType();
2113 mlir::Type resTy = cir::PointerType::get(
2114 cir::PointerType::get(cir::VoidType::get(getContext())));
2116 if (resultType != resTy)
2117 return emitOpError(
"result type must be ")
2118 << resTy <<
", but provided result type is " << resultType;
2130void cir::FuncOp::build(OpBuilder &builder, OperationState &result,
2131 StringRef name, FuncType type,
2132 GlobalLinkageKind linkage) {
2134 result.addAttribute(SymbolTable::getSymbolAttrName(),
2135 builder.getStringAttr(name));
2136 result.addAttribute(getFunctionTypeAttrName(result.name),
2137 TypeAttr::get(type));
2138 result.addAttribute(
2140 GlobalLinkageKindAttr::get(builder.getContext(), linkage));
2143ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
2144 llvm::SMLoc loc = parser.getCurrentLocation();
2145 mlir::Builder &builder = parser.getBuilder();
2147 mlir::StringAttr builtinNameAttr = getBuiltinAttrName(state.name);
2148 mlir::StringAttr coroutineNameAttr = getCoroutineAttrName(state.name);
2149 mlir::StringAttr inlineKindNameAttr = getInlineKindAttrName(state.name);
2150 mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
2151 mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
2152 mlir::StringAttr comdatNameAttr = getComdatAttrName(state.name);
2153 mlir::StringAttr visNameAttr = getSymVisibilityAttrName(state.name);
2154 mlir::StringAttr dsoLocalNameAttr = getDsoLocalAttrName(state.name);
2155 mlir::StringAttr specialMemberAttr = getCxxSpecialMemberAttrName(state.name);
2157 if (::mlir::succeeded(parser.parseOptionalKeyword(builtinNameAttr.strref())))
2158 state.addAttribute(builtinNameAttr, parser.getBuilder().getUnitAttr());
2159 if (::mlir::succeeded(
2160 parser.parseOptionalKeyword(coroutineNameAttr.strref())))
2161 state.addAttribute(coroutineNameAttr, parser.getBuilder().getUnitAttr());
2164 cir::InlineKindAttr inlineKindAttr;
2168 state.addAttribute(inlineKindNameAttr, inlineKindAttr);
2170 if (::mlir::succeeded(parser.parseOptionalKeyword(lambdaNameAttr.strref())))
2171 state.addAttribute(lambdaNameAttr, parser.getBuilder().getUnitAttr());
2172 if (parser.parseOptionalKeyword(noProtoNameAttr).succeeded())
2173 state.addAttribute(noProtoNameAttr, parser.getBuilder().getUnitAttr());
2175 if (parser.parseOptionalKeyword(comdatNameAttr).succeeded())
2176 state.addAttribute(comdatNameAttr, parser.getBuilder().getUnitAttr());
2180 GlobalLinkageKindAttr::get(
2181 parser.getContext(),
2183 parser, GlobalLinkageKind::ExternalLinkage)));
2185 ::llvm::StringRef visAttrStr;
2186 if (parser.parseOptionalKeyword(&visAttrStr, {
"private",
"public",
"nested"})
2188 state.addAttribute(visNameAttr,
2189 parser.getBuilder().getStringAttr(visAttrStr));
2192 state.getOrAddProperties<cir::FuncOp::Properties>().global_visibility =
2195 if (parser.parseOptionalKeyword(dsoLocalNameAttr).succeeded())
2196 state.addAttribute(dsoLocalNameAttr, parser.getBuilder().getUnitAttr());
2198 StringAttr nameAttr;
2199 if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
2205 bool isVariadic =
false;
2206 if (function_interface_impl::parseFunctionSignatureWithArguments(
2207 parser,
true, arguments, isVariadic, resultTypes,
2212 bool argAttrsEmpty =
true;
2213 for (OpAsmParser::Argument &arg : arguments) {
2214 argTypes.push_back(
arg.type);
2218 argAttrs.push_back(
arg.attrs);
2220 argAttrsEmpty =
false;
2224 if (resultTypes.size() > 1 || resultAttrs.size() > 1)
2225 return parser.emitError(
2226 loc,
"functions with multiple return types are not supported");
2228 mlir::Type returnType =
2229 (resultTypes.empty() ? cir::VoidType::get(builder.getContext())
2230 : resultTypes.front());
2232 cir::FuncType fnType = cir::FuncType::get(argTypes, returnType, isVariadic);
2236 state.addAttribute(getFunctionTypeAttrName(state.name),
2237 TypeAttr::get(fnType));
2239 if (!resultAttrs.empty() && resultAttrs[0])
2241 getResAttrsAttrName(state.name),
2242 mlir::ArrayAttr::get(parser.getContext(), {resultAttrs[0]}));
2245 state.addAttribute(getArgAttrsAttrName(state.name),
2246 mlir::ArrayAttr::get(parser.getContext(), argAttrs));
2248 bool hasAlias =
false;
2249 mlir::StringAttr aliaseeNameAttr = getAliaseeAttrName(state.name);
2250 if (parser.parseOptionalKeyword(
"alias").succeeded()) {
2251 if (parser.parseLParen().failed())
2253 mlir::StringAttr aliaseeAttr;
2254 if (parser.parseOptionalSymbolName(aliaseeAttr).failed())
2256 state.addAttribute(aliaseeNameAttr, FlatSymbolRefAttr::get(aliaseeAttr));
2257 if (parser.parseRParen().failed())
2262 mlir::StringAttr personalityNameAttr = getPersonalityAttrName(state.name);
2263 if (parser.parseOptionalKeyword(
"personality").succeeded()) {
2264 if (parser.parseLParen().failed())
2266 mlir::StringAttr personalityAttr;
2267 if (parser.parseOptionalSymbolName(personalityAttr).failed())
2269 state.addAttribute(personalityNameAttr,
2270 FlatSymbolRefAttr::get(personalityAttr));
2271 if (parser.parseRParen().failed())
2275 auto parseGlobalDtorCtor =
2276 [&](StringRef keyword,
2277 llvm::function_ref<void(std::optional<int> prio)> createAttr)
2278 -> mlir::LogicalResult {
2279 if (mlir::succeeded(parser.parseOptionalKeyword(keyword))) {
2280 std::optional<int> priority;
2281 if (mlir::succeeded(parser.parseOptionalLParen())) {
2282 auto parsedPriority = mlir::FieldParser<int>::parse(parser);
2283 if (mlir::failed(parsedPriority))
2284 return parser.emitError(parser.getCurrentLocation(),
2285 "failed to parse 'priority', of type 'int'");
2286 priority = parsedPriority.value_or(
int());
2288 if (parser.parseRParen())
2291 createAttr(priority);
2297 if (parser.parseOptionalKeyword(
"special_member").succeeded()) {
2298 if (parser.parseLess().failed())
2301 mlir::Attribute
attr;
2302 if (parser.parseAttribute(attr).failed())
2304 if (!mlir::isa<cir::CXXCtorAttr, cir::CXXDtorAttr, cir::CXXAssignAttr>(
2306 return parser.emitError(parser.getCurrentLocation(),
2307 "expected a C++ special member attribute");
2308 state.addAttribute(specialMemberAttr, attr);
2310 if (parser.parseGreater().failed())
2314 if (parseGlobalDtorCtor(
"global_ctor", [&](std::optional<int> priority) {
2315 mlir::IntegerAttr globalCtorPriorityAttr =
2316 builder.getI32IntegerAttr(priority.value_or(65535));
2317 state.addAttribute(getGlobalCtorPriorityAttrName(state.name),
2318 globalCtorPriorityAttr);
2322 if (parseGlobalDtorCtor(
"global_dtor", [&](std::optional<int> priority) {
2323 mlir::IntegerAttr globalDtorPriorityAttr =
2324 builder.getI32IntegerAttr(priority.value_or(65535));
2325 state.addAttribute(getGlobalDtorPriorityAttrName(state.name),
2326 globalDtorPriorityAttr);
2330 if (parser.parseOptionalKeyword(
"side_effect").succeeded()) {
2331 cir::SideEffect sideEffect;
2333 if (parser.parseLParen().failed() ||
2335 parser.parseRParen().failed())
2338 auto attr = cir::SideEffectAttr::get(parser.getContext(), sideEffect);
2339 state.addAttribute(CIRDialect::getSideEffectAttrName(), attr);
2343 NamedAttrList parsedAttrs;
2344 if (parser.parseOptionalAttrDictWithKeyword(parsedAttrs))
2347 for (StringRef disallowed : cir::FuncOp::getAttributeNames()) {
2348 if (parsedAttrs.get(disallowed))
2349 return parser.emitError(loc,
"attribute '")
2351 <<
"' should not be specified in the explicit attribute list";
2354 state.attributes.append(parsedAttrs);
2357 auto *body = state.addRegion();
2358 OptionalParseResult parseResult = parser.parseOptionalRegion(
2359 *body, arguments,
false);
2360 if (parseResult.has_value()) {
2362 return parser.emitError(loc,
"function alias shall not have a body");
2363 if (failed(*parseResult))
2367 return parser.emitError(loc,
"expected non-empty function body");
2376bool cir::FuncOp::isDeclaration() {
2379 std::optional<StringRef> aliasee = getAliasee();
2381 return getFunctionBody().empty();
2387bool cir::FuncOp::isCXXSpecialMemberFunction() {
2388 return getCxxSpecialMemberAttr() !=
nullptr;
2391bool cir::FuncOp::isCxxConstructor() {
2392 auto attr = getCxxSpecialMemberAttr();
2393 return attr && dyn_cast<CXXCtorAttr>(attr);
2396bool cir::FuncOp::isCxxDestructor() {
2397 auto attr = getCxxSpecialMemberAttr();
2398 return attr && dyn_cast<CXXDtorAttr>(attr);
2401bool cir::FuncOp::isCxxSpecialAssignment() {
2402 auto attr = getCxxSpecialMemberAttr();
2403 return attr && dyn_cast<CXXAssignAttr>(attr);
2406std::optional<CtorKind> cir::FuncOp::getCxxConstructorKind() {
2407 mlir::Attribute
attr = getCxxSpecialMemberAttr();
2409 if (
auto ctor = dyn_cast<CXXCtorAttr>(attr))
2410 return ctor.getCtorKind();
2412 return std::nullopt;
2415std::optional<AssignKind> cir::FuncOp::getCxxSpecialAssignKind() {
2416 mlir::Attribute
attr = getCxxSpecialMemberAttr();
2418 if (
auto assign = dyn_cast<CXXAssignAttr>(attr))
2419 return assign.getAssignKind();
2421 return std::nullopt;
2424bool cir::FuncOp::isCxxTrivialMemberFunction() {
2425 mlir::Attribute
attr = getCxxSpecialMemberAttr();
2427 if (
auto ctor = dyn_cast<CXXCtorAttr>(attr))
2428 return ctor.getIsTrivial();
2429 if (
auto dtor = dyn_cast<CXXDtorAttr>(attr))
2430 return dtor.getIsTrivial();
2431 if (
auto assign = dyn_cast<CXXAssignAttr>(attr))
2432 return assign.getIsTrivial();
2437mlir::Region *cir::FuncOp::getCallableRegion() {
2443void cir::FuncOp::print(OpAsmPrinter &p) {
2461 if (getLinkage() != GlobalLinkageKind::ExternalLinkage)
2462 p <<
' ' << stringifyGlobalLinkageKind(getLinkage());
2464 mlir::SymbolTable::Visibility vis = getVisibility();
2465 if (vis != mlir::SymbolTable::Visibility::Public)
2468 if (getGlobalVisibility() != cir::VisibilityKind::Default)
2469 p <<
' ' << stringifyVisibilityKind(getGlobalVisibility());
2475 p.printSymbolName(getSymName());
2476 cir::FuncType fnType = getFunctionType();
2477 function_interface_impl::printFunctionSignature(
2478 p, *
this, fnType.getInputs(), fnType.isVarArg(), fnType.getReturnTypes());
2480 if (std::optional<StringRef> aliaseeName = getAliasee()) {
2482 p.printSymbolName(*aliaseeName);
2486 if (std::optional<StringRef> personalityName = getPersonality()) {
2487 p <<
" personality(";
2488 p.printSymbolName(*personalityName);
2492 if (
auto specialMemberAttr = getCxxSpecialMember()) {
2493 p <<
" special_member<";
2494 p.printAttribute(*specialMemberAttr);
2498 if (
auto globalCtorPriority = getGlobalCtorPriority()) {
2499 p <<
" global_ctor";
2500 if (globalCtorPriority.value() != 65535)
2501 p <<
"(" << globalCtorPriority.value() <<
")";
2504 if (
auto globalDtorPriority = getGlobalDtorPriority()) {
2505 p <<
" global_dtor";
2506 if (globalDtorPriority.value() != 65535)
2507 p <<
"(" << globalDtorPriority.value() <<
")";
2510 if (std::optional<cir::SideEffect> sideEffect = getSideEffect();
2511 sideEffect && *sideEffect != cir::SideEffect::All) {
2512 p <<
" side_effect(";
2513 p << stringifySideEffect(*sideEffect);
2517 function_interface_impl::printFunctionAttributes(
2518 p, *
this, cir::FuncOp::getAttributeNames());
2521 Region &body = getOperation()->getRegion(0);
2522 if (!body.empty()) {
2524 p.printRegion(body,
false,
2529mlir::LogicalResult cir::FuncOp::verify() {
2531 if (!isDeclaration() && getCoroutine()) {
2532 bool foundAwait =
false;
2533 this->walk([&](Operation *op) {
2534 if (
auto await = dyn_cast<AwaitOp>(op)) {
2540 return emitOpError()
2541 <<
"coroutine body must use at least one cir.await op";
2544 llvm::SmallSet<llvm::StringRef, 16> labels;
2545 llvm::SmallSet<llvm::StringRef, 16> gotos;
2546 llvm::SmallSet<llvm::StringRef, 16> blockAddresses;
2547 bool invalidBlockAddress =
false;
2548 getOperation()->walk([&](mlir::Operation *op) {
2549 if (
auto lab = dyn_cast<cir::LabelOp>(op)) {
2550 labels.insert(lab.getLabel());
2551 }
else if (
auto goTo = dyn_cast<cir::GotoOp>(op)) {
2552 gotos.insert(goTo.getLabel());
2553 }
else if (
auto blkAdd = dyn_cast<cir::BlockAddressOp>(op)) {
2554 if (blkAdd.getBlockAddrInfoAttr().getFunc().getAttr() != getSymName()) {
2556 invalidBlockAddress =
true;
2557 return mlir::WalkResult::interrupt();
2559 blockAddresses.insert(blkAdd.getBlockAddrInfoAttr().getLabel());
2561 return mlir::WalkResult::advance();
2564 if (invalidBlockAddress)
2565 return emitOpError() <<
"blockaddress references a different function";
2567 llvm::SmallSet<llvm::StringRef, 16> mismatched;
2568 if (!labels.empty() || !gotos.empty()) {
2569 mismatched = llvm::set_difference(gotos, labels);
2571 if (!mismatched.empty())
2572 return emitOpError() <<
"goto/label mismatch";
2577 if (!labels.empty() || !blockAddresses.empty()) {
2578 mismatched = llvm::set_difference(blockAddresses, labels);
2580 if (!mismatched.empty())
2581 return emitOpError()
2582 <<
"expects an existing label target in the referenced function";
2594 bool noUnsignedWrap,
bool saturated,
2596 bool noWrap = noSignedWrap || noUnsignedWrap;
2597 if (!isa<cir::IntType>(op->getResultTypes()[0]) && noWrap)
2598 return op->emitError()
2599 <<
"only operations on integer values may have nsw/nuw flags";
2600 if (hasSat && saturated && !isa<cir::IntType>(op->getResultTypes()[0]))
2601 return op->emitError()
2602 <<
"only operations on integer values may have sat flag";
2603 if (hasSat && noWrap && saturated)
2604 return op->emitError()
2605 <<
"the nsw/nuw flags and the saturated flag are mutually exclusive";
2606 return mlir::success();
2609LogicalResult cir::AddOp::verify() {
2611 getNoUnsignedWrap(), getSaturated(),
2615LogicalResult cir::SubOp::verify() {
2617 getNoUnsignedWrap(), getSaturated(),
2621LogicalResult cir::MulOp::verify() {
2623 getNoUnsignedWrap(),
false,
2636void cir::TernaryOp::getSuccessorRegions(
2637 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
2639 if (!point.isParent()) {
2640 regions.push_back(RegionSuccessor::parent());
2646 regions.push_back(RegionSuccessor(&getTrueRegion()));
2647 regions.push_back(RegionSuccessor(&getFalseRegion()));
2650mlir::ValueRange cir::TernaryOp::getSuccessorInputs(RegionSuccessor successor) {
2651 return successor.isParent() ? ValueRange(getOperation()->getResults())
2655void cir::TernaryOp::build(
2656 OpBuilder &builder, OperationState &result,
Value cond,
2657 function_ref<
void(OpBuilder &, Location)> trueBuilder,
2658 function_ref<
void(OpBuilder &, Location)> falseBuilder) {
2659 result.addOperands(cond);
2660 OpBuilder::InsertionGuard guard(builder);
2661 Region *trueRegion = result.addRegion();
2662 builder.createBlock(trueRegion);
2663 trueBuilder(builder, result.location);
2664 Region *falseRegion = result.addRegion();
2665 builder.createBlock(falseRegion);
2666 falseBuilder(builder, result.location);
2671 if (trueRegion->back().mightHaveTerminator())
2672 yield = dyn_cast_or_null<cir::YieldOp>(trueRegion->back().getTerminator());
2673 if (!yield && falseRegion->back().mightHaveTerminator())
2674 yield = dyn_cast_or_null<cir::YieldOp>(falseRegion->back().getTerminator());
2676 assert((!yield || yield.getNumOperands() <= 1) &&
2677 "expected zero or one result type");
2678 if (yield && yield.getNumOperands() == 1)
2679 result.addTypes(TypeRange{yield.getOperandTypes().front()});
2686OpFoldResult cir::SelectOp::fold(FoldAdaptor adaptor) {
2687 mlir::Attribute
condition = adaptor.getCondition();
2689 bool conditionValue = mlir::cast<cir::BoolAttr>(
condition).getValue();
2690 return conditionValue ? getTrueValue() : getFalseValue();
2694 mlir::Attribute trueValue = adaptor.getTrueValue();
2695 mlir::Attribute falseValue = adaptor.getFalseValue();
2696 if (trueValue == falseValue)
2698 if (getTrueValue() == getFalseValue())
2699 return getTrueValue();
2704LogicalResult cir::SelectOp::verify() {
2706 auto condTy = dyn_cast<cir::VectorType>(getCondition().
getType());
2713 if (!isa<cir::VectorType>(getTrueValue().
getType()) ||
2714 !isa<cir::VectorType>(getFalseValue().
getType())) {
2715 return emitOpError()
2716 <<
"expected both true and false operands to be vector types "
2717 "when the condition is a vector boolean type";
2726LogicalResult cir::ShiftOp::verify() {
2727 mlir::Operation *op = getOperation();
2728 auto op0VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(0).getType());
2729 auto op1VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(1).getType());
2730 if (!op0VecTy ^ !op1VecTy)
2731 return emitOpError() <<
"input types cannot be one vector and one scalar";
2734 if (op0VecTy.getSize() != op1VecTy.getSize())
2735 return emitOpError() <<
"input vector types must have the same size";
2737 auto opResultTy = mlir::dyn_cast<cir::VectorType>(
getType());
2739 return emitOpError() <<
"the type of the result must be a vector "
2740 <<
"if it is vector shift";
2742 auto op0VecEleTy = mlir::cast<cir::IntType>(op0VecTy.getElementType());
2743 auto op1VecEleTy = mlir::cast<cir::IntType>(op1VecTy.getElementType());
2744 if (op0VecEleTy.getWidth() != op1VecEleTy.getWidth())
2745 return emitOpError()
2746 <<
"vector operands do not have the same elements sizes";
2748 auto resVecEleTy = mlir::cast<cir::IntType>(opResultTy.getElementType());
2749 if (op0VecEleTy.getWidth() != resVecEleTy.getWidth())
2750 return emitOpError() <<
"vector operands and result type do not have the "
2751 "same elements sizes";
2754 return mlir::success();
2761LogicalResult cir::LabelOp::verify() {
2762 mlir::Operation *op = getOperation();
2763 mlir::Block *blk = op->getBlock();
2764 if (&blk->front() != op)
2765 return emitError() <<
"must be the first operation in a block";
2767 return mlir::success();
2774OpFoldResult cir::IncOp::fold(FoldAdaptor adaptor) {
2775 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
2776 return adaptor.getInput();
2784OpFoldResult cir::DecOp::fold(FoldAdaptor adaptor) {
2785 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
2786 return adaptor.getInput();
2794OpFoldResult cir::MinusOp::fold(FoldAdaptor adaptor) {
2795 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
2796 return adaptor.getInput();
2799 if (
auto srcConst = getInput().getDefiningOp<cir::ConstantOp>())
2800 if (mlir::isa<cir::BoolType>(srcConst.getType()))
2801 return srcConst.getResult();
2804 if (mlir::Attribute attr = adaptor.getInput()) {
2805 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr)) {
2806 APInt val = intAttr.getValue();
2808 return cir::IntAttr::get(
getType(), val);
2810 if (
auto fpAttr = mlir::dyn_cast<cir::FPAttr>(attr)) {
2811 APFloat val = fpAttr.getValue();
2813 return cir::FPAttr::get(
getType(), val);
2824OpFoldResult cir::NotOp::fold(FoldAdaptor adaptor) {
2825 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
2826 return adaptor.getInput();
2831 if (mlir::Attribute attr = adaptor.getInput()) {
2832 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr)) {
2833 APInt val = intAttr.getValue();
2835 return cir::IntAttr::get(
getType(), val);
2837 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr))
2838 return cir::BoolAttr::get(getContext(), !boolAttr.getValue());
2849 mlir::Type resultTy) {
2852 mlir::Type inputMemberTy;
2853 mlir::Type resultMemberTy;
2854 if (mlir::isa<cir::DataMemberType>(src.getType())) {
2856 mlir::cast<cir::DataMemberType>(src.getType()).getMemberTy();
2857 resultMemberTy = mlir::cast<cir::DataMemberType>(resultTy).getMemberTy();
2860 if (inputMemberTy != resultMemberTy)
2861 return op->emitOpError()
2862 <<
"member types of the operand and the result do not match";
2864 return mlir::success();
2867LogicalResult cir::BaseDataMemberOp::verify() {
2871LogicalResult cir::DerivedDataMemberOp::verify() {
2879LogicalResult cir::BaseMethodOp::verify() {
2883LogicalResult cir::DerivedMethodOp::verify() {
2891void cir::AwaitOp::build(OpBuilder &builder, OperationState &result,
2895 result.addAttribute(getKindAttrName(result.name),
2896 cir::AwaitKindAttr::get(builder.getContext(),
kind));
2898 OpBuilder::InsertionGuard guard(builder);
2899 Region *readyRegion = result.addRegion();
2900 builder.createBlock(readyRegion);
2901 readyBuilder(builder, result.location);
2905 OpBuilder::InsertionGuard guard(builder);
2906 Region *suspendRegion = result.addRegion();
2907 builder.createBlock(suspendRegion);
2908 suspendBuilder(builder, result.location);
2912 OpBuilder::InsertionGuard guard(builder);
2913 Region *resumeRegion = result.addRegion();
2914 builder.createBlock(resumeRegion);
2915 resumeBuilder(builder, result.location);
2919void cir::AwaitOp::getSuccessorRegions(
2920 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
2923 if (!point.isParent()) {
2924 regions.push_back(RegionSuccessor::parent());
2931 regions.push_back(RegionSuccessor(&this->getReady()));
2932 regions.push_back(RegionSuccessor(&this->getSuspend()));
2933 regions.push_back(RegionSuccessor(&this->getResume()));
2936mlir::ValueRange cir::AwaitOp::getSuccessorInputs(RegionSuccessor successor) {
2937 if (successor.isParent())
2938 return getOperation()->getResults();
2939 if (successor == &getReady())
2940 return getReady().getArguments();
2941 if (successor == &getSuspend())
2942 return getSuspend().getArguments();
2943 if (successor == &getResume())
2944 return getResume().getArguments();
2945 llvm_unreachable(
"invalid region successor");
2948LogicalResult cir::AwaitOp::verify() {
2949 if (!isa<ConditionOp>(this->getReady().back().getTerminator()))
2950 return emitOpError(
"ready region must end with cir.condition");
2958LogicalResult cir::CopyOp::verify() {
2960 if (!
getType().getPointee().hasTrait<DataLayoutTypeInterface::Trait>())
2961 return emitError() <<
"missing data layout for pointee type";
2963 if (getSrc() == getDst())
2964 return emitError() <<
"source and destination are the same";
2966 if (getSkipTailPadding() &&
2967 !mlir::isa<cir::RecordType>(
getType().getPointee()))
2969 <<
"skip_tail_padding is only valid for record pointee types";
2971 return mlir::success();
2978LogicalResult cir::GetRuntimeMemberOp::verify() {
2979 auto recordTy = mlir::cast<RecordType>(getAddr().
getType().getPointee());
2980 cir::DataMemberType memberPtrTy = getMember().getType();
2982 if (recordTy != memberPtrTy.getClassTy())
2983 return emitError() <<
"record type does not match the member pointer type";
2984 if (
getType().getPointee() != memberPtrTy.getMemberTy())
2985 return emitError() <<
"result type does not match the member pointer type";
2986 return mlir::success();
2993LogicalResult cir::GetMethodOp::verify() {
2994 cir::MethodType methodTy = getMethod().getType();
2997 cir::PointerType objectPtrTy = getObject().getType();
2998 mlir::Type objectTy = objectPtrTy.getPointee();
3000 if (methodTy.getClassTy() != objectTy)
3001 return emitError() <<
"method class type and object type do not match";
3004 auto calleeTy = mlir::cast<cir::FuncType>(getCallee().
getType().getPointee());
3005 cir::FuncType methodFuncTy = methodTy.getMemberFuncTy();
3012 if (methodFuncTy.getReturnType() != calleeTy.getReturnType())
3014 <<
"method return type and callee return type do not match";
3019 if (calleeArgsTy.empty())
3020 return emitError() <<
"callee parameter list lacks receiver object ptr";
3022 auto calleeThisArgPtrTy = mlir::dyn_cast<cir::PointerType>(calleeArgsTy[0]);
3023 if (!calleeThisArgPtrTy ||
3024 !mlir::isa<cir::VoidType>(calleeThisArgPtrTy.getPointee())) {
3026 <<
"the first parameter of callee must be a void pointer";
3029 if (calleeArgsTy.slice(1) != methodFuncArgsTy)
3031 <<
"callee parameters and method parameters do not match";
3033 return mlir::success();
3040LogicalResult cir::GetMemberOp::verify() {
3041 const auto recordTy = dyn_cast<RecordType>(getAddrTy().getPointee());
3043 return emitError() <<
"expected pointer to a record type";
3045 if (recordTy.getMembers().size() <=
getIndex())
3046 return emitError() <<
"member index out of bounds";
3049 return emitError() <<
"member type mismatch";
3051 return mlir::success();
3058LogicalResult cir::ExtractMemberOp::verify() {
3059 auto recordTy = mlir::cast<cir::RecordType>(getRecord().
getType());
3060 if (recordTy.getKind() == cir::RecordType::Union)
3062 <<
"cir.extract_member currently does not support unions";
3063 if (recordTy.getMembers().size() <=
getIndex())
3064 return emitError() <<
"member index out of bounds";
3066 return emitError() <<
"member type mismatch";
3067 return mlir::success();
3074LogicalResult cir::InsertMemberOp::verify() {
3075 auto recordTy = mlir::cast<cir::RecordType>(getRecord().
getType());
3076 if (recordTy.getKind() == cir::RecordType::Union)
3077 return emitError() <<
"cir.insert_member currently does not support unions";
3078 if (recordTy.getMembers().size() <=
getIndex())
3079 return emitError() <<
"member index out of bounds";
3081 return emitError() <<
"member type mismatch";
3083 return mlir::success();
3090OpFoldResult cir::VecCreateOp::fold(FoldAdaptor adaptor) {
3091 if (llvm::any_of(getElements(), [](mlir::Value value) {
3092 return !value.getDefiningOp<cir::ConstantOp>();
3096 return cir::ConstVectorAttr::get(
3097 getType(), mlir::ArrayAttr::get(getContext(), adaptor.getElements()));
3100LogicalResult cir::VecCreateOp::verify() {
3104 const cir::VectorType vecTy =
getType();
3105 if (getElements().size() != vecTy.getSize()) {
3106 return emitOpError() <<
"operand count of " << getElements().size()
3107 <<
" doesn't match vector type " << vecTy
3108 <<
" element count of " << vecTy.getSize();
3111 const mlir::Type elementType = vecTy.getElementType();
3112 for (
const mlir::Value element : getElements()) {
3113 if (element.getType() != elementType) {
3114 return emitOpError() <<
"operand type " << element.getType()
3115 <<
" doesn't match vector element type "
3127OpFoldResult cir::VecExtractOp::fold(FoldAdaptor adaptor) {
3128 const auto vectorAttr =
3129 llvm::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec());
3133 const auto indexAttr =
3134 llvm::dyn_cast_if_present<cir::IntAttr>(adaptor.getIndex());
3138 const mlir::ArrayAttr elements = vectorAttr.getElts();
3139 const uint64_t index = indexAttr.getUInt();
3140 if (index >= elements.size())
3143 return elements[index];
3150OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
3152 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getLhs());
3154 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getRhs());
3155 if (!lhsVecAttr || !rhsVecAttr)
3158 mlir::Type inputElemTy =
3159 mlir::cast<cir::VectorType>(lhsVecAttr.getType()).getElementType();
3160 if (!isAnyIntegerOrFloatingPointType(inputElemTy))
3163 cir::CmpOpKind opKind = adaptor.getKind();
3164 mlir::ArrayAttr lhsVecElhs = lhsVecAttr.getElts();
3165 mlir::ArrayAttr rhsVecElhs = rhsVecAttr.getElts();
3166 uint64_t vecSize = lhsVecElhs.size();
3169 bool isIntAttr = vecSize && mlir::isa<cir::IntAttr>(lhsVecElhs[0]);
3170 for (uint64_t i = 0; i < vecSize; i++) {
3171 mlir::Attribute lhsAttr = lhsVecElhs[i];
3172 mlir::Attribute rhsAttr = rhsVecElhs[i];
3175 case cir::CmpOpKind::lt: {
3177 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <
3178 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3180 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <
3181 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3185 case cir::CmpOpKind::le: {
3187 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <=
3188 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3190 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <=
3191 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3195 case cir::CmpOpKind::gt: {
3197 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >
3198 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3200 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >
3201 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3205 case cir::CmpOpKind::ge: {
3207 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >=
3208 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3210 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >=
3211 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3215 case cir::CmpOpKind::eq: {
3217 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() ==
3218 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3220 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() ==
3221 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3225 case cir::CmpOpKind::ne: {
3227 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() !=
3228 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3230 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() !=
3231 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3237 elements[i] = cir::IntAttr::get(
getType().getElementType(), cmpResult);
3240 return cir::ConstVectorAttr::get(
3241 getType(), mlir::ArrayAttr::get(getContext(), elements));
3248OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor adaptor) {
3250 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec1());
3252 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec2());
3253 if (!vec1Attr || !vec2Attr)
3256 mlir::Type vec1ElemTy =
3257 mlir::cast<cir::VectorType>(vec1Attr.getType()).getElementType();
3259 mlir::ArrayAttr vec1Elts = vec1Attr.getElts();
3260 mlir::ArrayAttr vec2Elts = vec2Attr.getElts();
3261 mlir::ArrayAttr indicesElts = adaptor.getIndices();
3264 elements.reserve(indicesElts.size());
3266 uint64_t vec1Size = vec1Elts.size();
3267 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
3268 if (idxAttr.getSInt() == -1) {
3269 elements.push_back(cir::UndefAttr::get(vec1ElemTy));
3273 uint64_t idxValue = idxAttr.getUInt();
3274 elements.push_back(idxValue < vec1Size ? vec1Elts[idxValue]
3275 : vec2Elts[idxValue - vec1Size]);
3278 return cir::ConstVectorAttr::get(
3279 getType(), mlir::ArrayAttr::get(getContext(), elements));
3282LogicalResult cir::VecShuffleOp::verify() {
3285 if (getIndices().size() != getResult().
getType().getSize()) {
3286 return emitOpError() <<
": the number of elements in " << getIndices()
3287 <<
" and " << getResult().getType() <<
" don't match";
3292 if (getVec1().
getType().getElementType() !=
3293 getResult().
getType().getElementType()) {
3294 return emitOpError() <<
": element types of " << getVec1().getType()
3295 <<
" and " << getResult().getType() <<
" don't match";
3298 const uint64_t maxValidIndex =
3299 getVec1().getType().getSize() + getVec2().getType().getSize() - 1;
3301 getIndices().getAsRange<cir::IntAttr>(), [&](cir::IntAttr idxAttr) {
3302 return idxAttr.getSInt() != -1 && idxAttr.getUInt() > maxValidIndex;
3304 return emitOpError() <<
": index for __builtin_shufflevector must be "
3305 "less than the total number of vector elements";
3314OpFoldResult cir::VecShuffleDynamicOp::fold(FoldAdaptor adaptor) {
3315 mlir::Attribute vec = adaptor.getVec();
3316 mlir::Attribute indices = adaptor.getIndices();
3317 if (mlir::isa_and_nonnull<cir::ConstVectorAttr>(vec) &&
3318 mlir::isa_and_nonnull<cir::ConstVectorAttr>(indices)) {
3319 auto vecAttr = mlir::cast<cir::ConstVectorAttr>(vec);
3320 auto indicesAttr = mlir::cast<cir::ConstVectorAttr>(indices);
3322 mlir::ArrayAttr vecElts = vecAttr.getElts();
3323 mlir::ArrayAttr indicesElts = indicesAttr.getElts();
3325 const uint64_t numElements = vecElts.size();
3328 elements.reserve(numElements);
3330 const uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
3331 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
3332 uint64_t idxValue = idxAttr.getUInt();
3333 uint64_t newIdx = idxValue & maskBits;
3334 elements.push_back(vecElts[newIdx]);
3337 return cir::ConstVectorAttr::get(
3338 getType(), mlir::ArrayAttr::get(getContext(), elements));
3344LogicalResult cir::VecShuffleDynamicOp::verify() {
3346 if (getVec().
getType().getSize() !=
3347 mlir::cast<cir::VectorType>(getIndices().
getType()).getSize()) {
3348 return emitOpError() <<
": the number of elements in " << getVec().getType()
3349 <<
" and " << getIndices().getType() <<
" don't match";
3358LogicalResult cir::VecTernaryOp::verify() {
3363 if (getCond().
getType().getSize() != getLhs().
getType().getSize()) {
3364 return emitOpError() <<
": the number of elements in "
3365 << getCond().getType() <<
" and " << getLhs().getType()
3371OpFoldResult cir::VecTernaryOp::fold(FoldAdaptor adaptor) {
3372 mlir::Attribute cond = adaptor.getCond();
3373 mlir::Attribute lhs = adaptor.getLhs();
3374 mlir::Attribute rhs = adaptor.getRhs();
3376 if (!mlir::isa_and_nonnull<cir::ConstVectorAttr>(cond) ||
3377 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(lhs) ||
3378 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(rhs))
3380 auto condVec = mlir::cast<cir::ConstVectorAttr>(cond);
3381 auto lhsVec = mlir::cast<cir::ConstVectorAttr>(lhs);
3382 auto rhsVec = mlir::cast<cir::ConstVectorAttr>(rhs);
3384 mlir::ArrayAttr condElts = condVec.getElts();
3387 elements.reserve(condElts.size());
3389 for (
const auto &[idx, condAttr] :
3390 llvm::enumerate(condElts.getAsRange<cir::IntAttr>())) {
3391 if (condAttr.getSInt()) {
3392 elements.push_back(lhsVec.getElts()[idx]);
3394 elements.push_back(rhsVec.getElts()[idx]);
3398 cir::VectorType vecTy = getLhs().getType();
3399 return cir::ConstVectorAttr::get(
3400 vecTy, mlir::ArrayAttr::get(getContext(), elements));
3407LogicalResult cir::ComplexCreateOp::verify() {
3410 <<
"operand type of cir.complex.create does not match its result type";
3417OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) {
3418 mlir::Attribute real = adaptor.getReal();
3419 mlir::Attribute imag = adaptor.getImag();
3425 auto realAttr = mlir::cast<mlir::TypedAttr>(real);
3426 auto imagAttr = mlir::cast<mlir::TypedAttr>(imag);
3427 return cir::ConstComplexAttr::get(realAttr, imagAttr);
3434LogicalResult cir::ComplexRealOp::verify() {
3435 mlir::Type operandTy = getOperand().getType();
3436 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
3437 operandTy = complexOperandTy.getElementType();
3440 emitOpError() <<
": result type does not match operand type";
3447OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) {
3448 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
3451 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
3452 return complexCreateOp.getOperand(0);
3455 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
3456 return complex ? complex.getReal() :
nullptr;
3463LogicalResult cir::ComplexImagOp::verify() {
3464 mlir::Type operandTy = getOperand().getType();
3465 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
3466 operandTy = complexOperandTy.getElementType();
3469 emitOpError() <<
": result type does not match operand type";
3476OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) {
3477 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
3480 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
3481 return complexCreateOp.getOperand(1);
3484 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
3485 return complex ? complex.getImag() :
nullptr;
3492LogicalResult cir::ComplexRealPtrOp::verify() {
3493 mlir::Type resultPointeeTy =
getType().getPointee();
3494 cir::PointerType operandPtrTy = getOperand().getType();
3495 auto operandPointeeTy =
3496 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
3498 if (resultPointeeTy != operandPointeeTy.getElementType()) {
3499 return emitOpError() <<
": result type does not match operand type";
3509LogicalResult cir::ComplexImagPtrOp::verify() {
3510 mlir::Type resultPointeeTy =
getType().getPointee();
3511 cir::PointerType operandPtrTy = getOperand().getType();
3512 auto operandPointeeTy =
3513 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
3515 if (resultPointeeTy != operandPointeeTy.getElementType()) {
3516 return emitOpError()
3517 <<
"cir.complex.imag_ptr result type does not match operand type";
3528 llvm::function_ref<llvm::APInt(
const llvm::APInt &)> func,
3529 bool poisonZero =
false) {
3530 if (mlir::isa_and_present<cir::PoisonAttr>(inputAttr)) {
3535 auto input = mlir::dyn_cast_if_present<IntAttr>(inputAttr);
3539 llvm::APInt inputValue = input.getValue();
3540 if (poisonZero && inputValue.isZero())
3541 return cir::PoisonAttr::get(input.getType());
3543 llvm::APInt resultValue = func(inputValue);
3544 return IntAttr::get(input.getType(), resultValue);
3547OpFoldResult BitClrsbOp::fold(FoldAdaptor adaptor) {
3548 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3549 unsigned resultValue =
3550 inputValue.getBitWidth() - inputValue.getSignificantBits();
3551 return llvm::APInt(inputValue.getBitWidth(), resultValue);
3555OpFoldResult BitClzOp::fold(FoldAdaptor adaptor) {
3558 [](
const llvm::APInt &inputValue) {
3559 unsigned resultValue = inputValue.countLeadingZeros();
3560 return llvm::APInt(inputValue.getBitWidth(), resultValue);
3565OpFoldResult BitCtzOp::fold(FoldAdaptor adaptor) {
3568 [](
const llvm::APInt &inputValue) {
3569 return llvm::APInt(inputValue.getBitWidth(),
3570 inputValue.countTrailingZeros());
3575OpFoldResult BitFfsOp::fold(FoldAdaptor adaptor) {
3576 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3577 unsigned trailingZeros = inputValue.countTrailingZeros();
3579 trailingZeros == inputValue.getBitWidth() ? 0 : trailingZeros + 1;
3580 return llvm::APInt(inputValue.getBitWidth(), result);
3584OpFoldResult BitParityOp::fold(FoldAdaptor adaptor) {
3585 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3586 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount() % 2);
3590OpFoldResult BitPopcountOp::fold(FoldAdaptor adaptor) {
3591 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3592 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount());
3596OpFoldResult BitReverseOp::fold(FoldAdaptor adaptor) {
3597 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3598 return inputValue.reverseBits();
3602OpFoldResult ByteSwapOp::fold(FoldAdaptor adaptor) {
3603 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3604 return inputValue.byteSwap();
3608OpFoldResult RotateOp::fold(FoldAdaptor adaptor) {
3609 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()) ||
3610 mlir::isa_and_present<cir::PoisonAttr>(adaptor.getAmount())) {
3612 return cir::PoisonAttr::get(
getType());
3615 auto input = mlir::dyn_cast_if_present<IntAttr>(adaptor.getInput());
3616 auto amount = mlir::dyn_cast_if_present<IntAttr>(adaptor.getAmount());
3617 if (!input && !amount)
3626 llvm::APInt inputValue;
3628 inputValue = input.getValue();
3629 if (inputValue.isZero() || inputValue.isAllOnes()) {
3635 uint64_t amountValue;
3637 amountValue = amount.getValue().urem(getInput().
getType().getWidth());
3638 if (amountValue == 0) {
3644 if (!input || !amount)
3647 assert(inputValue.getBitWidth() == getInput().
getType().getWidth() &&
3648 "input value must have the same bit width as the input type");
3650 llvm::APInt resultValue;
3652 resultValue = inputValue.rotl(amountValue);
3654 resultValue = inputValue.rotr(amountValue);
3656 return IntAttr::get(input.getContext(), input.getType(), resultValue);
3663void cir::InlineAsmOp::print(OpAsmPrinter &p) {
3664 p <<
'(' << getAsmFlavor() <<
", ";
3669 auto *nameIt = names.begin();
3670 auto *attrIt = getOperandAttrs().begin();
3672 for (mlir::OperandRange ops : getAsmOperands()) {
3673 p << *nameIt <<
" = ";
3676 llvm::interleaveComma(llvm::make_range(ops.begin(), ops.end()), p,
3678 p.printOperand(value);
3679 p <<
" : " << value.getType();
3681 p <<
" (maybe_memory)";
3690 p.printString(getAsmString());
3692 p.printString(getConstraints());
3696 if (getSideEffects())
3697 p <<
" side_effects";
3699 std::array elidedAttrs{
3700 llvm::StringRef(
"asm_flavor"), llvm::StringRef(
"asm_string"),
3701 llvm::StringRef(
"constraints"), llvm::StringRef(
"operand_attrs"),
3702 llvm::StringRef(
"operands_segments"), llvm::StringRef(
"side_effects")};
3703 p.printOptionalAttrDict(getOperation()->getAttrs(), elidedAttrs);
3705 if (
auto v = getRes())
3706 p <<
" -> " << v.getType();
3709void cir::InlineAsmOp::build(OpBuilder &odsBuilder, OperationState &odsState,
3711 StringRef asmString, StringRef constraints,
3712 bool sideEffects, cir::AsmFlavor asmFlavor,
3716 for (
auto operandRange : asmOperands) {
3717 segments.push_back(operandRange.size());
3718 odsState.addOperands(operandRange);
3721 odsState.addAttribute(
3722 "operands_segments",
3723 DenseI32ArrayAttr::get(odsBuilder.getContext(), segments));
3724 odsState.addAttribute(
"asm_string", odsBuilder.getStringAttr(asmString));
3725 odsState.addAttribute(
"constraints", odsBuilder.getStringAttr(constraints));
3726 odsState.addAttribute(
"asm_flavor",
3727 AsmFlavorAttr::get(odsBuilder.getContext(), asmFlavor));
3730 odsState.addAttribute(
"side_effects", odsBuilder.getUnitAttr());
3732 odsState.addAttribute(
"operand_attrs", odsBuilder.getArrayAttr(operandAttrs));
3735ParseResult cir::InlineAsmOp::parse(OpAsmParser &parser,
3736 OperationState &result) {
3739 std::string asmString, constraints;
3741 MLIRContext *ctxt = parser.getBuilder().getContext();
3743 auto error = [&](
const Twine &msg) -> LogicalResult {
3744 return parser.emitError(parser.getCurrentLocation(), msg);
3747 auto expected = [&](
const std::string &
c) {
3748 return error(
"expected '" +
c +
"'");
3751 if (parser.parseLParen().failed())
3752 return expected(
"(");
3754 auto flavor = FieldParser<AsmFlavor, AsmFlavor>::parse(parser);
3756 return error(
"Unknown AsmFlavor");
3758 if (parser.parseComma().failed())
3759 return expected(
",");
3761 auto parseValue = [&](
Value &v) {
3762 OpAsmParser::UnresolvedOperand op;
3764 if (parser.parseOperand(op) || parser.parseColon())
3765 return error(
"can't parse operand");
3768 if (parser.parseType(typ).failed())
3769 return error(
"can't parse operand type");
3771 if (parser.resolveOperand(op, typ, tmp))
3772 return error(
"can't resolve operand");
3774 return mlir::success();
3777 auto parseOperands = [&](llvm::StringRef
name) {
3778 if (parser.parseKeyword(name).failed())
3779 return error(
"expected " + name +
" operands here");
3780 if (parser.parseEqual().failed())
3781 return expected(
"=");
3782 if (parser.parseLSquare().failed())
3783 return expected(
"[");
3786 if (parser.parseOptionalRSquare().succeeded()) {
3787 operandsGroupSizes.push_back(size);
3788 if (parser.parseComma())
3789 return expected(
",");
3790 return mlir::success();
3793 auto parseOperand = [&]() {
3795 if (parseValue(val).succeeded()) {
3796 result.operands.push_back(val);
3799 if (parser.parseOptionalLParen().failed()) {
3800 operandAttrs.push_back(mlir::Attribute());
3801 return mlir::success();
3804 if (parser.parseKeyword(
"maybe_memory").succeeded()) {
3805 operandAttrs.push_back(mlir::UnitAttr::get(ctxt));
3806 if (parser.parseRParen())
3807 return expected(
")");
3808 return mlir::success();
3810 return expected(
"maybe_memory");
3813 return mlir::failure();
3816 if (parser.parseCommaSeparatedList(parseOperand).failed())
3817 return mlir::failure();
3819 if (parser.parseRSquare().failed() || parser.parseComma().failed())
3820 return expected(
"]");
3821 operandsGroupSizes.push_back(size);
3822 return mlir::success();
3825 if (parseOperands(
"out").failed() || parseOperands(
"in").failed() ||
3826 parseOperands(
"in_out").failed())
3827 return error(
"failed to parse operands");
3829 if (parser.parseLBrace())
3830 return expected(
"{");
3831 if (parser.parseString(&asmString))
3832 return error(
"asm string parsing failed");
3833 if (parser.parseString(&constraints))
3834 return error(
"constraints string parsing failed");
3835 if (parser.parseRBrace())
3836 return expected(
"}");
3837 if (parser.parseRParen())
3838 return expected(
")");
3840 if (parser.parseOptionalKeyword(
"side_effects").succeeded())
3841 result.attributes.set(
"side_effects", UnitAttr::get(ctxt));
3843 if (parser.parseOptionalArrow().succeeded() &&
3844 parser.parseType(resType).failed())
3845 return mlir::failure();
3847 if (parser.parseOptionalAttrDict(result.attributes).failed())
3848 return mlir::failure();
3850 result.attributes.set(
"asm_flavor", AsmFlavorAttr::get(ctxt, *flavor));
3851 result.attributes.set(
"asm_string", StringAttr::get(ctxt, asmString));
3852 result.attributes.set(
"constraints", StringAttr::get(ctxt, constraints));
3853 result.attributes.set(
"operand_attrs", ArrayAttr::get(ctxt, operandAttrs));
3854 result.getOrAddProperties<InlineAsmOp::Properties>().operands_segments =
3855 parser.getBuilder().getDenseI32ArrayAttr(operandsGroupSizes);
3857 result.addTypes(TypeRange{resType});
3859 return mlir::success();
3866mlir::LogicalResult cir::ThrowOp::verify() {
3871 if (getNumOperands() != 0) {
3874 return emitOpError() <<
"'type_info' symbol attribute missing";
3884LogicalResult cir::AtomicFetchOp::verify() {
3885 if (getBinop() != cir::AtomicFetchKind::Add &&
3886 getBinop() != cir::AtomicFetchKind::Sub &&
3887 getBinop() != cir::AtomicFetchKind::Max &&
3888 getBinop() != cir::AtomicFetchKind::Min &&
3889 !mlir::isa<cir::IntType>(getVal().
getType()))
3890 return emitError(
"only atomic add, sub, max, and min operation could "
3891 "operate on floating-point values");
3899LogicalResult cir::TypeInfoAttr::verify(
3900 ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
3901 ::mlir::Type type, ::mlir::ArrayAttr typeInfoData) {
3903 if (cir::ConstRecordAttr::verify(emitError, type, typeInfoData).failed())
3913void cir::TryOp::getSuccessorRegions(
3914 mlir::RegionBranchPoint point,
3917 if (!point.isParent()) {
3918 regions.push_back(RegionSuccessor::parent());
3922 regions.push_back(mlir::RegionSuccessor(&getTryRegion()));
3926 for (mlir::Region &handlerRegion : this->getHandlerRegions())
3927 regions.push_back(mlir::RegionSuccessor(&handlerRegion));
3930mlir::ValueRange cir::TryOp::getSuccessorInputs(RegionSuccessor successor) {
3931 return successor.isParent() ? ValueRange(getOperation()->getResults())
3935LogicalResult cir::TryOp::verify() {
3936 mlir::ArrayAttr handlerTypes = getHandlerTypes();
3937 if (!handlerTypes) {
3938 if (!getHandlerRegions().empty())
3940 "handler regions must be empty when no handler types are present");
3944 mlir::MutableArrayRef<mlir::Region> handlerRegions = getHandlerRegions();
3948 if (handlerRegions.size() != handlerTypes.size())
3950 "number of handler regions and handler types must match");
3952 for (
const auto &[typeAttr, handlerRegion] :
3953 llvm::zip(handlerTypes, handlerRegions)) {
3955 mlir::Block &entryBlock = handlerRegion.front();
3956 if (entryBlock.getNumArguments() != 1 ||
3957 !mlir::isa<cir::EhTokenType>(entryBlock.getArgument(0).getType()))
3959 "handler region must have a single '!cir.eh_token' argument");
3962 if (mlir::isa<cir::UnwindAttr>(typeAttr))
3965 if (entryBlock.empty() || !mlir::isa<cir::BeginCatchOp>(entryBlock.front()))
3967 "catch handler region must start with 'cir.begin_catch'");
3975 mlir::MutableArrayRef<mlir::Region> handlerRegions,
3976 mlir::ArrayAttr handlerTypes) {
3980 for (
const auto [typeIdx, typeAttr] : llvm::enumerate(handlerTypes)) {
3984 if (mlir::isa<cir::CatchAllAttr>(typeAttr)) {
3985 printer <<
"catch all ";
3986 }
else if (mlir::isa<cir::UnwindAttr>(typeAttr)) {
3987 printer <<
"unwind ";
3989 printer <<
"catch [type ";
3990 printer.printAttribute(typeAttr);
3995 mlir::Region ®ion = handlerRegions[typeIdx];
3996 if (!region.empty() && region.front().getNumArguments() > 0) {
3998 printer.printRegionArgument(region.front().getArgument(0));
4002 printer.printRegion(region,
4009 mlir::OpAsmParser &parser,
4011 mlir::ArrayAttr &handlerTypes) {
4013 auto parseCheckedCatcherRegion = [&]() -> mlir::ParseResult {
4014 handlerRegions.emplace_back(
new mlir::Region);
4016 mlir::Region &currRegion = *handlerRegions.back();
4020 if (parser.parseLParen())
4022 mlir::OpAsmParser::Argument arg;
4023 if (parser.parseArgument(arg,
true))
4025 regionArgs.push_back(arg);
4026 if (parser.parseRParen())
4029 mlir::SMLoc regionLoc = parser.getCurrentLocation();
4030 if (parser.parseRegion(currRegion, regionArgs)) {
4031 handlerRegions.clear();
4035 if (currRegion.empty())
4036 return parser.emitError(regionLoc,
"handler region shall not be empty");
4038 if (!(currRegion.back().mightHaveTerminator() &&
4039 currRegion.back().getTerminator()))
4040 return parser.emitError(
4041 regionLoc,
"blocks are expected to be explicitly terminated");
4046 bool hasCatchAll =
false;
4048 while (parser.parseOptionalKeyword(
"catch").succeeded()) {
4049 bool hasLSquare = parser.parseOptionalLSquare().succeeded();
4051 llvm::StringRef attrStr;
4052 if (parser.parseOptionalKeyword(&attrStr, {
"all",
"type"}).failed())
4053 return parser.emitError(parser.getCurrentLocation(),
4054 "expected 'all' or 'type' keyword");
4056 bool isCatchAll = attrStr ==
"all";
4059 return parser.emitError(parser.getCurrentLocation(),
4060 "can't have more than one catch all");
4064 mlir::Attribute exceptionRTTIAttr;
4065 if (!isCatchAll && parser.parseAttribute(exceptionRTTIAttr).failed())
4066 return parser.emitError(parser.getCurrentLocation(),
4067 "expected valid RTTI info attribute");
4069 catcherAttrs.push_back(isCatchAll
4070 ? cir::CatchAllAttr::get(parser.getContext())
4071 : exceptionRTTIAttr);
4073 if (hasLSquare && isCatchAll)
4074 return parser.emitError(parser.getCurrentLocation(),
4075 "catch all dosen't need RTTI info attribute");
4077 if (hasLSquare && parser.parseRSquare().failed())
4078 return parser.emitError(parser.getCurrentLocation(),
4079 "expected `]` after RTTI info attribute");
4081 if (parseCheckedCatcherRegion().failed())
4082 return mlir::failure();
4085 if (parser.parseOptionalKeyword(
"unwind").succeeded()) {
4087 return parser.emitError(parser.getCurrentLocation(),
4088 "unwind can't be used with catch all");
4090 catcherAttrs.push_back(cir::UnwindAttr::get(parser.getContext()));
4091 if (parseCheckedCatcherRegion().failed())
4092 return mlir::failure();
4095 handlerTypes = parser.getBuilder().getArrayAttr(catcherAttrs);
4096 return mlir::success();
4104cir::EhTypeIdOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
4105 Operation *op = symbolTable.lookupNearestSymbolFrom(*
this, getTypeSymAttr());
4106 if (!isa_and_nonnull<GlobalOp>(op))
4107 return emitOpError(
"'")
4108 << getTypeSym() <<
"' does not reference a valid cir.global";
4118 SmallVectorImpl<Block *> &catchDestinations,
4119 Block *&defaultDestination,
4120 mlir::UnitAttr &defaultIsCatchAll) {
4122 if (parser.parseLSquare())
4126 bool hasCatchAll =
false;
4127 bool hasUnwind =
false;
4130 auto parseHandler = [&]() -> ParseResult {
4132 if (succeeded(parser.parseOptionalKeyword(
"catch_all"))) {
4134 return parser.emitError(parser.getCurrentLocation(),
4135 "duplicate 'catch_all' handler");
4137 return parser.emitError(parser.getCurrentLocation(),
4138 "cannot have both 'catch_all' and 'unwind'");
4141 if (parser.parseColon().failed())
4144 if (parser.parseSuccessor(defaultDestination).failed())
4150 if (succeeded(parser.parseOptionalKeyword(
"unwind"))) {
4152 return parser.emitError(parser.getCurrentLocation(),
4153 "duplicate 'unwind' handler");
4155 return parser.emitError(parser.getCurrentLocation(),
4156 "cannot have both 'catch_all' and 'unwind'");
4159 if (parser.parseColon().failed())
4162 if (parser.parseSuccessor(defaultDestination).failed())
4170 if (parser.parseKeyword(
"catch").failed())
4173 if (parser.parseLParen().failed())
4176 mlir::Attribute catchTypeAttr;
4177 if (parser.parseAttribute(catchTypeAttr).failed())
4179 handlerTypes.push_back(catchTypeAttr);
4181 if (parser.parseRParen().failed())
4184 if (parser.parseColon().failed())
4188 if (parser.parseSuccessor(dest).failed())
4190 catchDestinations.push_back(dest);
4194 if (parser.parseCommaSeparatedList(parseHandler).failed())
4197 if (parser.parseRSquare().failed())
4201 if (!hasCatchAll && !hasUnwind)
4202 return parser.emitError(parser.getCurrentLocation(),
4203 "must have either 'catch_all' or 'unwind' handler");
4206 if (!handlerTypes.empty())
4207 catchTypes = parser.getBuilder().getArrayAttr(handlerTypes);
4210 defaultIsCatchAll = parser.getBuilder().getUnitAttr();
4216 mlir::ArrayAttr catchTypes,
4217 SuccessorRange catchDestinations,
4218 Block *defaultDestination,
4219 mlir::UnitAttr defaultIsCatchAll) {
4227 llvm::zip(catchTypes, catchDestinations),
4230 p.printAttribute(std::get<0>(i));
4232 p.printSuccessor(std::get<1>(i));
4244 if (defaultIsCatchAll)
4245 p <<
" catch_all : ";
4248 p.printSuccessor(defaultDestination);
4258#define GET_OP_CLASSES
4259#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)
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 LogicalResult verifyMemberPtrCast(Operation *op, mlir::Value src, mlir::Type resultTy)
static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, mlir::OperationState &result, bool hasDestinationBlocks=false)
static bool isIntOrBoolCast(cir::CastOp op)
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)
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 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 LogicalResult verifyBinaryOverflowOp(mlir::Operation *op, bool noSignedWrap, bool noUnsignedWrap, bool saturated, bool hasSat)
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 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
__device__ __2f16 float c
void buildTerminatedBody(mlir::OpBuilder &builder, mlir::Location loc)
mlir::ptr::MemorySpaceAttrInterface normalizeDefaultAddressSpace(mlir::ptr::MemorySpaceAttrInterface addrSpace)
Normalize LangAddressSpace::Default to null (empty attribute).
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()