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();
211 cir::VisibilityAttr &visibility) {
212 switch (visibility.getValue()) {
213 case cir::VisibilityKind::Hidden:
216 case cir::VisibilityKind::Protected:
217 printer <<
"protected";
219 case cir::VisibilityKind::Default:
225 cir::VisibilityKind visibilityKind =
227 visibility = cir::VisibilityAttr::get(parser.getContext(), visibilityKind);
235 cir::InlineKindAttr &inlineKindAttr) {
237 static constexpr llvm::StringRef keywords[] = {
"no_inline",
"always_inline",
241 llvm::StringRef keyword;
242 if (parser.parseOptionalKeyword(&keyword, keywords).failed()) {
248 auto inlineKindResult = ::cir::symbolizeEnum<::cir::InlineKind>(keyword);
249 if (!inlineKindResult) {
250 return parser.emitError(parser.getCurrentLocation(),
"expected one of [")
252 <<
"] for inlineKind, got: " << keyword;
256 ::cir::InlineKindAttr::get(parser.getContext(), *inlineKindResult);
261 if (inlineKindAttr) {
262 p <<
" " << stringifyInlineKind(inlineKindAttr.getValue());
270 mlir::Region ®ion) {
271 auto regionLoc = parser.getCurrentLocation();
272 if (parser.parseRegion(region))
281 mlir::Region ®ion) {
282 printer.printRegion(region,
287mlir::OptionalParseResult
289 mlir::ptr::MemorySpaceAttrInterface &attr);
292 mlir::ptr::MemorySpaceAttrInterface attr);
298void cir::AllocaOp::build(mlir::OpBuilder &odsBuilder,
299 mlir::OperationState &odsState, mlir::Type addr,
300 mlir::Type allocaType, llvm::StringRef name,
301 mlir::IntegerAttr alignment) {
302 odsState.addAttribute(getAllocaTypeAttrName(odsState.name),
303 mlir::TypeAttr::get(allocaType));
304 odsState.addAttribute(getNameAttrName(odsState.name),
305 odsBuilder.getStringAttr(name));
307 odsState.addAttribute(getAlignmentAttrName(odsState.name), alignment);
309 odsState.addTypes(addr);
316LogicalResult cir::BreakOp::verify() {
317 if (!getOperation()->getParentOfType<LoopOpInterface>() &&
318 !getOperation()->getParentOfType<SwitchOp>())
319 return emitOpError(
"must be within a loop");
331void cir::ConditionOp::getSuccessorRegions(
337 if (
auto loopOp = dyn_cast<LoopOpInterface>(getOperation()->getParentOp())) {
338 regions.emplace_back(&loopOp.getBody());
339 regions.push_back(RegionSuccessor::parent());
343 auto await = cast<AwaitOp>(getOperation()->getParentOp());
344 regions.emplace_back(&await.getResume());
345 regions.emplace_back(&await.getSuspend());
349cir::ConditionOp::getMutableSuccessorOperands(RegionSuccessor point) {
351 return MutableOperandRange(getOperation(), 0, 0);
355cir::ResumeOp::getMutableSuccessorOperands(RegionSuccessor point) {
357 return MutableOperandRange(getOperation(), 0, 0);
360LogicalResult cir::ConditionOp::verify() {
361 if (!isa<LoopOpInterface, AwaitOp>(getOperation()->getParentOp()))
362 return emitOpError(
"condition must be within a conditional region");
371 mlir::Attribute attrType) {
372 if (isa<cir::ConstPtrAttr>(attrType)) {
373 if (!mlir::isa<cir::PointerType>(opType))
374 return op->emitOpError(
375 "pointer constant initializing a non-pointer type");
379 if (isa<cir::DataMemberAttr, cir::MethodAttr>(attrType)) {
385 if (isa<cir::ZeroAttr>(attrType)) {
386 if (isa<cir::RecordType, cir::ArrayType, cir::VectorType, cir::ComplexType>(
389 return op->emitOpError(
390 "zero expects struct, array, vector, or complex type");
393 if (mlir::isa<cir::UndefAttr>(attrType)) {
394 if (!mlir::isa<cir::VoidType>(opType))
396 return op->emitOpError(
"undef expects non-void type");
399 if (mlir::isa<cir::BoolAttr>(attrType)) {
400 if (!mlir::isa<cir::BoolType>(opType))
401 return op->emitOpError(
"result type (")
402 << opType <<
") must be '!cir.bool' for '" << attrType <<
"'";
406 if (mlir::isa<cir::IntAttr, cir::FPAttr>(attrType)) {
407 auto at = cast<TypedAttr>(attrType);
408 if (at.getType() != opType) {
409 return op->emitOpError(
"result type (")
410 << opType <<
") does not match value type (" << at.getType()
416 if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
417 cir::ConstComplexAttr, cir::ConstRecordAttr,
418 cir::GlobalViewAttr, cir::PoisonAttr, cir::TypeInfoAttr,
419 cir::VTableAttr>(attrType))
422 assert(isa<TypedAttr>(attrType) &&
"What else could we be looking at here?");
423 return op->emitOpError(
"global with type ")
424 << cast<TypedAttr>(attrType).getType() <<
" not yet supported";
427LogicalResult cir::ConstantOp::verify() {
434OpFoldResult cir::ConstantOp::fold(FoldAdaptor ) {
442LogicalResult cir::ContinueOp::verify() {
443 if (!getOperation()->getParentOfType<LoopOpInterface>())
444 return emitOpError(
"must be within a loop");
452LogicalResult cir::CastOp::verify() {
453 mlir::Type resType =
getType();
454 mlir::Type srcType = getSrc().getType();
458 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
459 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
460 if (srcPtrTy && resPtrTy && (
getKind() != cir::CastKind::address_space))
461 if (srcPtrTy.getAddrSpace() != resPtrTy.getAddrSpace()) {
462 return emitOpError() <<
"result type address space does not match the "
463 "address space of the operand";
466 if (mlir::isa<cir::VectorType>(srcType) &&
467 mlir::isa<cir::VectorType>(resType)) {
470 srcType = mlir::dyn_cast<cir::VectorType>(srcType).getElementType();
471 resType = mlir::dyn_cast<cir::VectorType>(resType).getElementType();
475 case cir::CastKind::int_to_bool: {
476 if (!mlir::isa<cir::BoolType>(resType))
477 return emitOpError() <<
"requires !cir.bool type for result";
478 if (!mlir::isa<cir::IntType>(srcType))
479 return emitOpError() <<
"requires !cir.int type for source";
482 case cir::CastKind::ptr_to_bool: {
483 if (!mlir::isa<cir::BoolType>(resType))
484 return emitOpError() <<
"requires !cir.bool type for result";
485 if (!mlir::isa<cir::PointerType>(srcType))
486 return emitOpError() <<
"requires !cir.ptr type for source";
489 case cir::CastKind::integral: {
490 if (!mlir::isa<cir::IntType>(resType))
491 return emitOpError() <<
"requires !cir.int type for result";
492 if (!mlir::isa<cir::IntType>(srcType))
493 return emitOpError() <<
"requires !cir.int type for source";
496 case cir::CastKind::array_to_ptrdecay: {
497 const auto arrayPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
498 const auto flatPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
499 if (!arrayPtrTy || !flatPtrTy)
500 return emitOpError() <<
"requires !cir.ptr type for source and result";
505 case cir::CastKind::bitcast: {
507 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
508 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
510 if (srcPtrTy && resPtrTy) {
516 case cir::CastKind::floating: {
517 if (!mlir::isa<cir::FPTypeInterface>(srcType) ||
518 !mlir::isa<cir::FPTypeInterface>(resType))
519 return emitOpError() <<
"requires !cir.float type for source and result";
522 case cir::CastKind::float_to_int: {
523 if (!mlir::isa<cir::FPTypeInterface>(srcType))
524 return emitOpError() <<
"requires !cir.float type for source";
525 if (!mlir::dyn_cast<cir::IntType>(resType))
526 return emitOpError() <<
"requires !cir.int type for result";
529 case cir::CastKind::int_to_ptr: {
530 if (!mlir::dyn_cast<cir::IntType>(srcType))
531 return emitOpError() <<
"requires !cir.int type for source";
532 if (!mlir::dyn_cast<cir::PointerType>(resType))
533 return emitOpError() <<
"requires !cir.ptr type for result";
536 case cir::CastKind::ptr_to_int: {
537 if (!mlir::dyn_cast<cir::PointerType>(srcType))
538 return emitOpError() <<
"requires !cir.ptr type for source";
539 if (!mlir::dyn_cast<cir::IntType>(resType))
540 return emitOpError() <<
"requires !cir.int type for result";
543 case cir::CastKind::float_to_bool: {
544 if (!mlir::isa<cir::FPTypeInterface>(srcType))
545 return emitOpError() <<
"requires !cir.float type for source";
546 if (!mlir::isa<cir::BoolType>(resType))
547 return emitOpError() <<
"requires !cir.bool type for result";
550 case cir::CastKind::bool_to_int: {
551 if (!mlir::isa<cir::BoolType>(srcType))
552 return emitOpError() <<
"requires !cir.bool type for source";
553 if (!mlir::isa<cir::IntType>(resType))
554 return emitOpError() <<
"requires !cir.int type for result";
557 case cir::CastKind::int_to_float: {
558 if (!mlir::isa<cir::IntType>(srcType))
559 return emitOpError() <<
"requires !cir.int type for source";
560 if (!mlir::isa<cir::FPTypeInterface>(resType))
561 return emitOpError() <<
"requires !cir.float type for result";
564 case cir::CastKind::bool_to_float: {
565 if (!mlir::isa<cir::BoolType>(srcType))
566 return emitOpError() <<
"requires !cir.bool type for source";
567 if (!mlir::isa<cir::FPTypeInterface>(resType))
568 return emitOpError() <<
"requires !cir.float type for result";
571 case cir::CastKind::address_space: {
572 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
573 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
574 if (!srcPtrTy || !resPtrTy)
575 return emitOpError() <<
"requires !cir.ptr type for source and result";
576 if (srcPtrTy.getPointee() != resPtrTy.getPointee())
577 return emitOpError() <<
"requires two types differ in addrspace only";
580 case cir::CastKind::float_to_complex: {
581 if (!mlir::isa<cir::FPTypeInterface>(srcType))
582 return emitOpError() <<
"requires !cir.float type for source";
583 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
585 return emitOpError() <<
"requires !cir.complex type for result";
586 if (srcType != resComplexTy.getElementType())
587 return emitOpError() <<
"requires source type match result element type";
590 case cir::CastKind::int_to_complex: {
591 if (!mlir::isa<cir::IntType>(srcType))
592 return emitOpError() <<
"requires !cir.int type for source";
593 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
595 return emitOpError() <<
"requires !cir.complex type for result";
596 if (srcType != resComplexTy.getElementType())
597 return emitOpError() <<
"requires source type match result element type";
600 case cir::CastKind::float_complex_to_real: {
601 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
603 return emitOpError() <<
"requires !cir.complex type for source";
604 if (!mlir::isa<cir::FPTypeInterface>(resType))
605 return emitOpError() <<
"requires !cir.float type for result";
606 if (srcComplexTy.getElementType() != resType)
607 return emitOpError() <<
"requires source element type match result type";
610 case cir::CastKind::int_complex_to_real: {
611 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
613 return emitOpError() <<
"requires !cir.complex type for source";
614 if (!mlir::isa<cir::IntType>(resType))
615 return emitOpError() <<
"requires !cir.int type for result";
616 if (srcComplexTy.getElementType() != resType)
617 return emitOpError() <<
"requires source element type match result type";
620 case cir::CastKind::float_complex_to_bool: {
621 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
622 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
624 <<
"requires floating point !cir.complex type for source";
625 if (!mlir::isa<cir::BoolType>(resType))
626 return emitOpError() <<
"requires !cir.bool type for result";
629 case cir::CastKind::int_complex_to_bool: {
630 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
631 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
633 <<
"requires floating point !cir.complex type for source";
634 if (!mlir::isa<cir::BoolType>(resType))
635 return emitOpError() <<
"requires !cir.bool type for result";
638 case cir::CastKind::float_complex: {
639 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
640 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
642 <<
"requires floating point !cir.complex type for source";
643 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
644 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
646 <<
"requires floating point !cir.complex type for result";
649 case cir::CastKind::float_complex_to_int_complex: {
650 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
651 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
653 <<
"requires floating point !cir.complex type for source";
654 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
655 if (!resComplexTy || !resComplexTy.isIntegerComplex())
656 return emitOpError() <<
"requires integer !cir.complex type for result";
659 case cir::CastKind::int_complex: {
660 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
661 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
662 return emitOpError() <<
"requires integer !cir.complex type for source";
663 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
664 if (!resComplexTy || !resComplexTy.isIntegerComplex())
665 return emitOpError() <<
"requires integer !cir.complex type for result";
668 case cir::CastKind::int_complex_to_float_complex: {
669 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
670 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
671 return emitOpError() <<
"requires integer !cir.complex type for source";
672 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
673 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
675 <<
"requires floating point !cir.complex type for result";
678 case cir::CastKind::member_ptr_to_bool: {
679 if (!mlir::isa<cir::DataMemberType, cir::MethodType>(srcType))
681 <<
"requires !cir.data_member or !cir.method type for source";
682 if (!mlir::isa<cir::BoolType>(resType))
683 return emitOpError() <<
"requires !cir.bool type for result";
687 llvm_unreachable(
"Unknown CastOp kind?");
691 auto kind = op.getKind();
692 return kind == cir::CastKind::bool_to_int ||
693 kind == cir::CastKind::int_to_bool ||
kind == cir::CastKind::integral;
697 cir::CastOp head = op, tail = op;
703 op = head.getSrc().getDefiningOp<cir::CastOp>();
711 if (head.getKind() == cir::CastKind::bool_to_int &&
712 tail.getKind() == cir::CastKind::int_to_bool)
713 return head.getSrc();
718 if (head.getKind() == cir::CastKind::int_to_bool &&
719 tail.getKind() == cir::CastKind::int_to_bool)
720 return head.getResult();
725OpFoldResult cir::CastOp::fold(FoldAdaptor adaptor) {
726 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getSrc())) {
728 return cir::PoisonAttr::get(getContext(),
getType());
733 case cir::CastKind::integral: {
735 auto foldOrder = getSrc().getDefiningOp()->fold(foldResults);
736 if (foldOrder.succeeded() && mlir::isa<mlir::Attribute>(foldResults[0]))
737 return mlir::cast<mlir::Attribute>(foldResults[0]);
740 case cir::CastKind::bitcast:
741 case cir::CastKind::address_space:
742 case cir::CastKind::float_complex:
743 case cir::CastKind::int_complex: {
757 if (
auto srcConst = getSrc().getDefiningOp<cir::ConstantOp>()) {
759 case cir::CastKind::integral: {
760 mlir::Type srcTy = getSrc().getType();
762 assert(mlir::isa<cir::VectorType>(srcTy) ==
763 mlir::isa<cir::VectorType>(
getType()));
764 if (mlir::isa<cir::VectorType>(srcTy))
767 auto srcIntTy = mlir::cast<cir::IntType>(srcTy);
768 auto dstIntTy = mlir::cast<cir::IntType>(
getType());
771 ? srcConst.getIntValue().sextOrTrunc(dstIntTy.getWidth())
772 : srcConst.getIntValue().zextOrTrunc(dstIntTy.getWidth());
773 return cir::IntAttr::get(dstIntTy, newVal);
786mlir::OperandRange cir::CallOp::getArgOperands() {
788 return getArgs().drop_front(1);
792mlir::MutableOperandRange cir::CallOp::getArgOperandsMutable() {
793 mlir::MutableOperandRange args = getArgsMutable();
795 return args.slice(1, args.size() - 1);
799mlir::Value cir::CallOp::getIndirectCall() {
800 assert(isIndirect());
801 return getOperand(0);
805Value cir::CallOp::getArgOperand(
unsigned i) {
808 return getOperand(i);
812unsigned cir::CallOp::getNumArgOperands() {
814 return this->getOperation()->getNumOperands() - 1;
815 return this->getOperation()->getNumOperands();
818static mlir::ParseResult
820 mlir::OperationState &result) {
821 mlir::Block *normalDestSuccessor;
822 if (parser.parseSuccessor(normalDestSuccessor))
823 return mlir::failure();
825 if (parser.parseComma())
826 return mlir::failure();
828 mlir::Block *unwindDestSuccessor;
829 if (parser.parseSuccessor(unwindDestSuccessor))
830 return mlir::failure();
832 result.addSuccessors(normalDestSuccessor);
833 result.addSuccessors(unwindDestSuccessor);
834 return mlir::success();
838 mlir::OperationState &result,
839 bool hasDestinationBlocks =
false) {
842 mlir::FlatSymbolRefAttr calleeAttr;
846 .parseOptionalAttribute(calleeAttr, CIRDialect::getCalleeAttrName(),
849 OpAsmParser::UnresolvedOperand indirectVal;
851 if (parser.parseOperand(indirectVal).failed())
853 ops.push_back(indirectVal);
856 if (parser.parseLParen())
857 return mlir::failure();
859 opsLoc = parser.getCurrentLocation();
860 if (parser.parseOperandList(ops))
861 return mlir::failure();
862 if (parser.parseRParen())
863 return mlir::failure();
865 if (hasDestinationBlocks &&
867 return ::mlir::failure();
870 if (parser.parseOptionalKeyword(
"nothrow").succeeded())
871 result.addAttribute(CIRDialect::getNoThrowAttrName(),
872 mlir::UnitAttr::get(parser.getContext()));
874 if (parser.parseOptionalKeyword(
"side_effect").succeeded()) {
875 if (parser.parseLParen().failed())
877 cir::SideEffect sideEffect;
880 if (parser.parseRParen().failed())
882 auto attr = cir::SideEffectAttr::get(parser.getContext(), sideEffect);
883 result.addAttribute(CIRDialect::getSideEffectAttrName(), attr);
886 if (parser.parseOptionalAttrDict(result.attributes))
887 return ::mlir::failure();
889 if (parser.parseColon())
890 return ::mlir::failure();
896 if (call_interface_impl::parseFunctionSignature(parser, argTypes, argAttrs,
897 resultTypes, resultAttrs))
898 return mlir::failure();
900 if (resultTypes.size() > 1 || resultAttrs.size() > 1)
901 return parser.emitError(
902 parser.getCurrentLocation(),
903 "functions with multiple return types are not supported");
905 result.addTypes(resultTypes);
907 if (parser.resolveOperands(ops, argTypes, opsLoc, result.operands))
908 return mlir::failure();
910 if (!resultAttrs.empty() && resultAttrs[0])
912 CIRDialect::getResAttrsAttrName(),
913 mlir::ArrayAttr::get(parser.getContext(), {resultAttrs[0]}));
918 bool argAttrsEmpty =
true;
920 llvm::transform(argAttrs, std::back_inserter(convertedArgAttrs),
921 [&](DictionaryAttr da) -> mlir::Attribute {
923 argAttrsEmpty =
false;
927 if (!argAttrsEmpty) {
932 argAttrsRef = argAttrsRef.drop_front();
934 result.addAttribute(CIRDialect::getArgAttrsAttrName(),
935 mlir::ArrayAttr::get(parser.getContext(), argAttrsRef));
938 return mlir::success();
943 mlir::Value indirectCallee, mlir::OpAsmPrinter &printer,
944 bool isNothrow, cir::SideEffect sideEffect, ArrayAttr argAttrs,
945 ArrayAttr resAttrs, mlir::Block *normalDest =
nullptr,
946 mlir::Block *unwindDest =
nullptr) {
949 auto callLikeOp = mlir::cast<cir::CIRCallOpInterface>(op);
950 auto ops = callLikeOp.getArgOperands();
954 printer.printAttributeWithoutType(calleeSym);
957 assert(indirectCallee);
958 printer << indirectCallee;
961 printer <<
"(" << ops <<
")";
964 assert(unwindDest &&
"expected two successors");
965 auto tryCall = cast<cir::TryCallOp>(op);
966 printer <<
' ' << tryCall.getNormalDest();
969 printer << tryCall.getUnwindDest();
973 printer <<
" nothrow";
975 if (sideEffect != cir::SideEffect::All) {
976 printer <<
" side_effect(";
977 printer << stringifySideEffect(sideEffect);
982 CIRDialect::getCalleeAttrName(),
983 CIRDialect::getNoThrowAttrName(),
984 CIRDialect::getSideEffectAttrName(),
985 CIRDialect::getOperandSegmentSizesAttrName(),
986 llvm::StringRef(
"res_attrs"),
987 llvm::StringRef(
"arg_attrs")};
988 printer.printOptionalAttrDict(op->getAttrs(), elidedAttrs);
990 if (calleeSym || !argAttrs) {
991 call_interface_impl::printFunctionSignature(
992 printer, op->getOperands().getTypes(), argAttrs,
993 false, op->getResultTypes(), resAttrs);
1001 shimmedArgAttrs.push_back(mlir::DictionaryAttr::get(op->getContext(), {}));
1002 shimmedArgAttrs.append(argAttrs.begin(), argAttrs.end());
1003 call_interface_impl::printFunctionSignature(
1004 printer, op->getOperands().getTypes(),
1005 mlir::ArrayAttr::get(op->getContext(), shimmedArgAttrs),
1006 false, op->getResultTypes(), resAttrs);
1010mlir::ParseResult cir::CallOp::parse(mlir::OpAsmParser &parser,
1011 mlir::OperationState &result) {
1015void cir::CallOp::print(mlir::OpAsmPrinter &p) {
1016 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
1017 cir::SideEffect sideEffect = getSideEffect();
1018 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
1019 sideEffect, getArgAttrsAttr(), getResAttrsAttr());
1024 SymbolTableCollection &symbolTable) {
1026 op->getAttrOfType<FlatSymbolRefAttr>(CIRDialect::getCalleeAttrName());
1029 return mlir::success();
1032 auto fn = symbolTable.lookupNearestSymbolFrom<cir::FuncOp>(op, fnAttr);
1034 return op->emitOpError() <<
"'" << fnAttr.getValue()
1035 <<
"' does not reference a valid function";
1037 auto callIf = dyn_cast<cir::CIRCallOpInterface>(op);
1038 assert(callIf &&
"expected CIR call interface to be always available");
1042 auto fnType = fn.getFunctionType();
1043 if (!fn.getNoProto()) {
1044 unsigned numCallOperands = callIf.getNumArgOperands();
1045 unsigned numFnOpOperands = fnType.getNumInputs();
1047 if (!fnType.isVarArg() && numCallOperands != numFnOpOperands)
1048 return op->emitOpError(
"incorrect number of operands for callee");
1049 if (fnType.isVarArg() && numCallOperands < numFnOpOperands)
1050 return op->emitOpError(
"too few operands for callee");
1052 for (
unsigned i = 0, e = numFnOpOperands; i != e; ++i)
1053 if (callIf.getArgOperand(i).getType() != fnType.getInput(i))
1054 return op->emitOpError(
"operand type mismatch: expected operand type ")
1055 << fnType.getInput(i) <<
", but provided "
1056 << op->getOperand(i).getType() <<
" for operand number " << i;
1062 if (fnType.hasVoidReturn() && op->getNumResults() != 0)
1063 return op->emitOpError(
"callee returns void but call has results");
1066 if (!fnType.hasVoidReturn() && op->getNumResults() != 1)
1067 return op->emitOpError(
"incorrect number of results for callee");
1070 if (!fnType.hasVoidReturn() &&
1071 op->getResultTypes().front() != fnType.getReturnType()) {
1072 return op->emitOpError(
"result type mismatch: expected ")
1073 << fnType.getReturnType() <<
", but provided "
1074 << op->getResult(0).getType();
1077 return mlir::success();
1081cir::CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1089mlir::OperandRange cir::TryCallOp::getArgOperands() {
1091 return getArgs().drop_front(1);
1095mlir::MutableOperandRange cir::TryCallOp::getArgOperandsMutable() {
1096 mlir::MutableOperandRange args = getArgsMutable();
1098 return args.slice(1, args.size() - 1);
1102mlir::Value cir::TryCallOp::getIndirectCall() {
1103 assert(isIndirect());
1104 return getOperand(0);
1108Value cir::TryCallOp::getArgOperand(
unsigned i) {
1111 return getOperand(i);
1115unsigned cir::TryCallOp::getNumArgOperands() {
1117 return this->getOperation()->getNumOperands() - 1;
1118 return this->getOperation()->getNumOperands();
1122cir::TryCallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1126mlir::ParseResult cir::TryCallOp::parse(mlir::OpAsmParser &parser,
1127 mlir::OperationState &result) {
1131void cir::TryCallOp::print(::mlir::OpAsmPrinter &p) {
1132 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
1133 cir::SideEffect sideEffect = getSideEffect();
1134 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
1135 sideEffect, getArgAttrsAttr(), getResAttrsAttr(),
1136 getNormalDest(), getUnwindDest());
1144 cir::FuncOp function) {
1146 if (op.getNumOperands() > 1)
1147 return op.emitOpError() <<
"expects at most 1 return operand";
1150 auto expectedTy = function.getFunctionType().getReturnType();
1152 (op.getNumOperands() == 0 ? cir::VoidType::get(op.getContext())
1153 : op.getOperand(0).getType());
1154 if (actualTy != expectedTy)
1155 return op.emitOpError() <<
"returns " << actualTy
1156 <<
" but enclosing function returns " << expectedTy;
1158 return mlir::success();
1161mlir::LogicalResult cir::ReturnOp::verify() {
1164 auto *fnOp = getOperation()->getParentOp();
1165 while (!isa<cir::FuncOp>(fnOp))
1166 fnOp = fnOp->getParentOp();
1179ParseResult cir::IfOp::parse(OpAsmParser &parser, OperationState &result) {
1181 result.regions.reserve(2);
1182 Region *thenRegion = result.addRegion();
1183 Region *elseRegion = result.addRegion();
1185 mlir::Builder &builder = parser.getBuilder();
1186 OpAsmParser::UnresolvedOperand cond;
1187 Type boolType = cir::BoolType::get(builder.getContext());
1189 if (parser.parseOperand(cond) ||
1190 parser.resolveOperand(cond, boolType, result.operands))
1194 mlir::SMLoc parseThenLoc = parser.getCurrentLocation();
1195 if (parser.parseRegion(*thenRegion, {}, {}))
1202 if (!parser.parseOptionalKeyword(
"else")) {
1203 mlir::SMLoc parseElseLoc = parser.getCurrentLocation();
1204 if (parser.parseRegion(*elseRegion, {}, {}))
1211 if (parser.parseOptionalAttrDict(result.attributes))
1216void cir::IfOp::print(OpAsmPrinter &p) {
1217 p <<
" " << getCondition() <<
" ";
1218 mlir::Region &thenRegion = this->getThenRegion();
1219 p.printRegion(thenRegion,
1224 mlir::Region &elseRegion = this->getElseRegion();
1225 if (!elseRegion.empty()) {
1227 p.printRegion(elseRegion,
1232 p.printOptionalAttrDict(getOperation()->getAttrs());
1238 cir::YieldOp::create(builder, loc);
1246void cir::IfOp::getSuccessorRegions(mlir::RegionBranchPoint point,
1247 SmallVectorImpl<RegionSuccessor> ®ions) {
1249 if (!point.isParent()) {
1250 regions.push_back(RegionSuccessor::parent());
1255 Region *elseRegion = &this->getElseRegion();
1256 if (elseRegion->empty())
1257 elseRegion =
nullptr;
1260 regions.push_back(RegionSuccessor(&getThenRegion()));
1263 regions.push_back(RegionSuccessor(elseRegion));
1268mlir::ValueRange cir::IfOp::getSuccessorInputs(RegionSuccessor successor) {
1269 return successor.isParent() ? ValueRange(getOperation()->getResults())
1273void cir::IfOp::build(OpBuilder &builder, OperationState &result,
Value cond,
1276 assert(thenBuilder &&
"the builder callback for 'then' must be present");
1277 result.addOperands(cond);
1279 OpBuilder::InsertionGuard guard(builder);
1280 Region *thenRegion = result.addRegion();
1281 builder.createBlock(thenRegion);
1282 thenBuilder(builder, result.location);
1284 Region *elseRegion = result.addRegion();
1285 if (!withElseRegion)
1288 builder.createBlock(elseRegion);
1289 elseBuilder(builder, result.location);
1301void cir::ScopeOp::getSuccessorRegions(
1302 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1304 if (!point.isParent()) {
1305 regions.push_back(RegionSuccessor::parent());
1310 regions.push_back(RegionSuccessor(&getScopeRegion()));
1313mlir::ValueRange cir::ScopeOp::getSuccessorInputs(RegionSuccessor successor) {
1314 return successor.isParent() ? ValueRange(getOperation()->getResults())
1318void cir::ScopeOp::build(
1319 OpBuilder &builder, OperationState &result,
1320 function_ref<
void(OpBuilder &, Type &, Location)> scopeBuilder) {
1321 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1323 OpBuilder::InsertionGuard guard(builder);
1324 Region *scopeRegion = result.addRegion();
1325 builder.createBlock(scopeRegion);
1329 scopeBuilder(builder, yieldTy, result.location);
1332 result.addTypes(TypeRange{yieldTy});
1335void cir::ScopeOp::build(
1336 OpBuilder &builder, OperationState &result,
1337 function_ref<
void(OpBuilder &, Location)> scopeBuilder) {
1338 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1339 OpBuilder::InsertionGuard guard(builder);
1340 Region *scopeRegion = result.addRegion();
1341 builder.createBlock(scopeRegion);
1343 scopeBuilder(builder, result.location);
1346LogicalResult cir::ScopeOp::verify() {
1348 return emitOpError() <<
"cir.scope must not be empty since it should "
1349 "include at least an implicit cir.yield ";
1352 mlir::Block &lastBlock =
getRegion().back();
1353 if (lastBlock.empty() || !lastBlock.mightHaveTerminator() ||
1354 !lastBlock.getTerminator()->hasTrait<OpTrait::IsTerminator>())
1355 return emitOpError() <<
"last block of cir.scope must be terminated";
1359LogicalResult cir::ScopeOp::fold(FoldAdaptor ,
1360 SmallVectorImpl<OpFoldResult> &results) {
1365 if (block.getOperations().size() != 1)
1368 auto yield = dyn_cast<cir::YieldOp>(block.front());
1373 if (getNumResults() != 1 || yield.getNumOperands() != 1)
1376 results.push_back(yield.getOperand(0));
1384void cir::CleanupScopeOp::getSuccessorRegions(
1385 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1386 if (!point.isParent()) {
1387 regions.push_back(RegionSuccessor::parent());
1392 regions.push_back(RegionSuccessor(&getBodyRegion()));
1393 regions.push_back(RegionSuccessor(&getCleanupRegion()));
1397cir::CleanupScopeOp::getSuccessorInputs(RegionSuccessor successor) {
1398 return ValueRange();
1401void cir::CleanupScopeOp::build(
1402 OpBuilder &builder, OperationState &result, CleanupKind cleanupKind,
1403 function_ref<
void(OpBuilder &, Location)> bodyBuilder,
1404 function_ref<
void(OpBuilder &, Location)> cleanupBuilder) {
1405 result.addAttribute(getCleanupKindAttrName(result.name),
1406 CleanupKindAttr::get(builder.getContext(), cleanupKind));
1408 OpBuilder::InsertionGuard guard(builder);
1411 Region *bodyRegion = result.addRegion();
1412 builder.createBlock(bodyRegion);
1414 bodyBuilder(builder, result.location);
1417 Region *cleanupRegion = result.addRegion();
1418 builder.createBlock(cleanupRegion);
1420 cleanupBuilder(builder, result.location);
1435LogicalResult cir::BrOp::canonicalize(BrOp op, PatternRewriter &rewriter) {
1436 Block *src = op->getBlock();
1437 Block *
dst = op.getDest();
1444 if (src->getNumSuccessors() != 1 ||
dst->getSinglePredecessor() != src)
1449 if (isa<cir::LabelOp, cir::IndirectBrOp>(
dst->front()))
1452 auto operands = op.getDestOperands();
1453 rewriter.eraseOp(op);
1454 rewriter.mergeBlocks(dst, src, operands);
1458mlir::SuccessorOperands cir::BrOp::getSuccessorOperands(
unsigned index) {
1459 assert(index == 0 &&
"invalid successor index");
1460 return mlir::SuccessorOperands(getDestOperandsMutable());
1471mlir::SuccessorOperands
1472cir::IndirectBrOp::getSuccessorOperands(
unsigned index) {
1473 assert(index < getNumSuccessors() &&
"invalid successor index");
1474 return mlir::SuccessorOperands(getSuccOperandsMutable()[index]);
1478 OpAsmParser &parser, Type &flagType,
1479 SmallVectorImpl<Block *> &succOperandBlocks,
1482 if (failed(parser.parseCommaSeparatedList(
1483 OpAsmParser::Delimiter::Square,
1485 Block *destination = nullptr;
1486 SmallVector<OpAsmParser::UnresolvedOperand> operands;
1487 SmallVector<Type> operandTypes;
1489 if (parser.parseSuccessor(destination).failed())
1492 if (succeeded(parser.parseOptionalLParen())) {
1493 if (failed(parser.parseOperandList(
1494 operands, OpAsmParser::Delimiter::None)) ||
1495 failed(parser.parseColonTypeList(operandTypes)) ||
1496 failed(parser.parseRParen()))
1499 succOperandBlocks.push_back(destination);
1500 succOperands.emplace_back(operands);
1501 succOperandsTypes.emplace_back(operandTypes);
1504 "successor blocks")))
1510 Type flagType, SuccessorRange succs,
1511 OperandRangeRange succOperands,
1512 const TypeRangeRange &succOperandsTypes) {
1515 llvm::zip(succs, succOperands),
1518 p.printSuccessorAndUseList(std::get<0>(i), std::get<1>(i));
1521 if (!succOperands.empty())
1530mlir::SuccessorOperands cir::BrCondOp::getSuccessorOperands(
unsigned index) {
1531 assert(index < getNumSuccessors() &&
"invalid successor index");
1532 return SuccessorOperands(index == 0 ? getDestOperandsTrueMutable()
1533 : getDestOperandsFalseMutable());
1537 if (IntegerAttr condAttr = dyn_cast_if_present<IntegerAttr>(operands.front()))
1538 return condAttr.getValue().isOne() ? getDestTrue() : getDestFalse();
1546void cir::CaseOp::getSuccessorRegions(
1547 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1548 if (!point.isParent()) {
1549 regions.push_back(RegionSuccessor::parent());
1552 regions.push_back(RegionSuccessor(&getCaseRegion()));
1555mlir::ValueRange cir::CaseOp::getSuccessorInputs(RegionSuccessor successor) {
1556 return successor.isParent() ? ValueRange(getOperation()->getResults())
1560void cir::CaseOp::build(OpBuilder &builder, OperationState &result,
1561 ArrayAttr value, CaseOpKind
kind,
1562 OpBuilder::InsertPoint &insertPoint) {
1563 OpBuilder::InsertionGuard guardSwitch(builder);
1564 result.addAttribute(
"value", value);
1565 result.getOrAddProperties<Properties>().
kind =
1566 cir::CaseOpKindAttr::get(builder.getContext(),
kind);
1567 Region *caseRegion = result.addRegion();
1568 builder.createBlock(caseRegion);
1570 insertPoint = builder.saveInsertionPoint();
1577void cir::SwitchOp::getSuccessorRegions(
1578 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ion) {
1579 if (!point.isParent()) {
1580 region.push_back(RegionSuccessor::parent());
1584 region.push_back(RegionSuccessor(&getBody()));
1587mlir::ValueRange cir::SwitchOp::getSuccessorInputs(RegionSuccessor successor) {
1588 return successor.isParent() ? ValueRange(getOperation()->getResults())
1592void cir::SwitchOp::build(OpBuilder &builder, OperationState &result,
1594 assert(switchBuilder &&
"the builder callback for regions must be present");
1595 OpBuilder::InsertionGuard guardSwitch(builder);
1596 Region *switchRegion = result.addRegion();
1597 builder.createBlock(switchRegion);
1598 result.addOperands({cond});
1599 switchBuilder(builder, result.location, result);
1603 walk<mlir::WalkOrder::PreOrder>([&](mlir::Operation *op) {
1605 if (isa<cir::SwitchOp>(op) && op != *
this)
1606 return WalkResult::skip();
1608 if (
auto caseOp = dyn_cast<cir::CaseOp>(op))
1609 cases.push_back(caseOp);
1611 return WalkResult::advance();
1616 collectCases(cases);
1618 if (getBody().empty())
1621 if (!isa<YieldOp>(getBody().front().back()))
1624 if (!llvm::all_of(getBody().front(),
1625 [](Operation &op) {
return isa<CaseOp, YieldOp>(op); }))
1628 return llvm::all_of(cases, [
this](CaseOp op) {
1629 return op->getParentOfType<SwitchOp>() == *
this;
1637void cir::SwitchFlatOp::build(OpBuilder &builder, OperationState &result,
1638 Value value, Block *defaultDestination,
1639 ValueRange defaultOperands,
1641 BlockRange caseDestinations,
1644 std::vector<mlir::Attribute> caseValuesAttrs;
1645 for (
const APInt &val : caseValues)
1646 caseValuesAttrs.push_back(cir::IntAttr::get(value.getType(), val));
1647 mlir::ArrayAttr attrs = ArrayAttr::get(builder.getContext(), caseValuesAttrs);
1649 build(builder, result, value, defaultOperands, caseOperands, attrs,
1650 defaultDestination, caseDestinations);
1656 OpAsmParser &parser, Type flagType, mlir::ArrayAttr &caseValues,
1657 SmallVectorImpl<Block *> &caseDestinations,
1661 if (failed(parser.parseLSquare()))
1663 if (succeeded(parser.parseOptionalRSquare()))
1667 auto parseCase = [&]() {
1669 if (failed(parser.parseInteger(value)))
1672 values.push_back(cir::IntAttr::get(flagType, value));
1677 if (parser.parseColon() || parser.parseSuccessor(destination))
1679 if (!parser.parseOptionalLParen()) {
1680 if (parser.parseOperandList(operands, OpAsmParser::Delimiter::None,
1682 parser.parseColonTypeList(operandTypes) || parser.parseRParen())
1685 caseDestinations.push_back(destination);
1686 caseOperands.emplace_back(operands);
1687 caseOperandTypes.emplace_back(operandTypes);
1690 if (failed(parser.parseCommaSeparatedList(parseCase)))
1693 caseValues = ArrayAttr::get(flagType.getContext(), values);
1695 return parser.parseRSquare();
1699 Type flagType, mlir::ArrayAttr caseValues,
1700 SuccessorRange caseDestinations,
1701 OperandRangeRange caseOperands,
1702 const TypeRangeRange &caseOperandTypes) {
1712 llvm::zip(caseValues, caseDestinations),
1715 mlir::Attribute a = std::get<0>(i);
1716 p << mlir::cast<cir::IntAttr>(a).getValue();
1718 p.printSuccessorAndUseList(std::get<1>(i), caseOperands[index++]);
1733 mlir::Attribute &valueAttr) {
1735 return parser.parseAttribute(valueAttr,
"value", attr);
1739 p.printAttribute(value);
1742mlir::LogicalResult cir::GlobalOp::verify() {
1745 if (getInitialValue().has_value()) {
1757void cir::GlobalOp::build(
1758 OpBuilder &odsBuilder, OperationState &odsState, llvm::StringRef sym_name,
1759 mlir::Type sym_type,
bool isConstant,
1760 mlir::ptr::MemorySpaceAttrInterface addrSpace,
1761 cir::GlobalLinkageKind linkage,
1762 function_ref<
void(OpBuilder &, Location)> ctorBuilder,
1763 function_ref<
void(OpBuilder &, Location)> dtorBuilder) {
1764 odsState.addAttribute(getSymNameAttrName(odsState.name),
1765 odsBuilder.getStringAttr(sym_name));
1766 odsState.addAttribute(getSymTypeAttrName(odsState.name),
1767 mlir::TypeAttr::get(sym_type));
1769 odsState.addAttribute(getConstantAttrName(odsState.name),
1770 odsBuilder.getUnitAttr());
1774 odsState.addAttribute(getAddrSpaceAttrName(odsState.name), addrSpace);
1776 cir::GlobalLinkageKindAttr linkageAttr =
1777 cir::GlobalLinkageKindAttr::get(odsBuilder.getContext(), linkage);
1778 odsState.addAttribute(getLinkageAttrName(odsState.name), linkageAttr);
1780 Region *ctorRegion = odsState.addRegion();
1782 odsBuilder.createBlock(ctorRegion);
1783 ctorBuilder(odsBuilder, odsState.location);
1786 Region *dtorRegion = odsState.addRegion();
1788 odsBuilder.createBlock(dtorRegion);
1789 dtorBuilder(odsBuilder, odsState.location);
1792 odsState.addAttribute(getGlobalVisibilityAttrName(odsState.name),
1793 cir::VisibilityAttr::get(odsBuilder.getContext()));
1801void cir::GlobalOp::getSuccessorRegions(
1802 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1804 if (!point.isParent()) {
1805 regions.push_back(RegionSuccessor::parent());
1810 Region *ctorRegion = &this->getCtorRegion();
1811 if (ctorRegion->empty())
1812 ctorRegion =
nullptr;
1815 Region *dtorRegion = &this->getDtorRegion();
1816 if (dtorRegion->empty())
1817 dtorRegion =
nullptr;
1821 regions.push_back(RegionSuccessor(ctorRegion));
1823 regions.push_back(RegionSuccessor(dtorRegion));
1826mlir::ValueRange cir::GlobalOp::getSuccessorInputs(RegionSuccessor successor) {
1827 return successor.isParent() ? ValueRange(getOperation()->getResults())
1832 TypeAttr type, Attribute initAttr,
1833 mlir::Region &ctorRegion,
1834 mlir::Region &dtorRegion) {
1835 auto printType = [&]() { p <<
": " << type; };
1836 if (!op.isDeclaration()) {
1838 if (!ctorRegion.empty()) {
1842 p.printRegion(ctorRegion,
1851 if (!dtorRegion.empty()) {
1853 p.printRegion(dtorRegion,
1864 Attribute &initialValueAttr,
1865 mlir::Region &ctorRegion,
1866 mlir::Region &dtorRegion) {
1868 if (parser.parseOptionalEqual().failed()) {
1871 if (parser.parseColonType(opTy))
1876 if (!parser.parseOptionalKeyword(
"ctor")) {
1877 if (parser.parseColonType(opTy))
1879 auto parseLoc = parser.getCurrentLocation();
1880 if (parser.parseRegion(ctorRegion, {}, {}))
1891 assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
1892 "Non-typed attrs shouldn't appear here.");
1893 auto typedAttr = mlir::cast<mlir::TypedAttr>(initialValueAttr);
1894 opTy = typedAttr.getType();
1899 if (!parser.parseOptionalKeyword(
"dtor")) {
1900 auto parseLoc = parser.getCurrentLocation();
1901 if (parser.parseRegion(dtorRegion, {}, {}))
1908 typeAttr = TypeAttr::get(opTy);
1917cir::GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1920 mlir::Operation *op =
1921 symbolTable.lookupNearestSymbolFrom(*
this, getNameAttr());
1922 if (op ==
nullptr || !(isa<GlobalOp>(op) || isa<FuncOp>(op)))
1923 return emitOpError(
"'")
1925 <<
"' does not reference a valid cir.global or cir.func";
1928 mlir::ptr::MemorySpaceAttrInterface symAddrSpaceAttr{};
1929 if (
auto g = dyn_cast<GlobalOp>(op)) {
1930 symTy = g.getSymType();
1931 symAddrSpaceAttr = g.getAddrSpaceAttr();
1934 if (getTls() && !g.getTlsModel())
1935 return emitOpError(
"access to global not marked thread local");
1940 bool getGlobalIsStaticLocal = getStaticLocal();
1941 bool globalIsStaticLocal = g.getStaticLocalGuard().has_value();
1942 if (getGlobalIsStaticLocal != globalIsStaticLocal &&
1943 !getOperation()->getParentOfType<cir::GlobalOp>())
1944 return emitOpError(
"static_local attribute mismatch");
1945 }
else if (
auto f = dyn_cast<FuncOp>(op)) {
1946 symTy = f.getFunctionType();
1948 llvm_unreachable(
"Unexpected operation for GetGlobalOp");
1951 auto resultType = dyn_cast<PointerType>(getAddr().
getType());
1952 if (!resultType || symTy != resultType.getPointee())
1953 return emitOpError(
"result type pointee type '")
1954 << resultType.getPointee() <<
"' does not match type " << symTy
1955 <<
" of the global @" <<
getName();
1957 if (symAddrSpaceAttr != resultType.getAddrSpace()) {
1958 return emitOpError()
1959 <<
"result type address space does not match the address "
1960 "space of the global @"
1972cir::VTableAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1978 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
1980 return emitOpError(
"'")
1981 <<
name <<
"' does not reference a valid cir.global";
1982 std::optional<mlir::Attribute> init = op.getInitialValue();
1985 if (!isa<cir::VTableAttr>(*init))
1986 return emitOpError(
"Expected #cir.vtable in initializer for global '")
1996cir::VTTAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2005 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
2007 return emitOpError(
"'")
2008 <<
name <<
"' does not reference a valid cir.global";
2009 std::optional<mlir::Attribute> init = op.getInitialValue();
2012 if (!isa<cir::ConstArrayAttr>(*init))
2014 "Expected constant array in initializer for global VTT '")
2019LogicalResult cir::VTTAddrPointOp::verify() {
2021 if (
getName() && getSymAddr())
2022 return emitOpError(
"should use either a symbol or value, but not both");
2028 mlir::Type resultType = getAddr().getType();
2029 mlir::Type resTy = cir::PointerType::get(
2030 cir::PointerType::get(cir::VoidType::get(getContext())));
2032 if (resultType != resTy)
2033 return emitOpError(
"result type must be ")
2034 << resTy <<
", but provided result type is " << resultType;
2046void cir::FuncOp::build(OpBuilder &builder, OperationState &result,
2047 StringRef name, FuncType type,
2048 GlobalLinkageKind linkage) {
2050 result.addAttribute(SymbolTable::getSymbolAttrName(),
2051 builder.getStringAttr(name));
2052 result.addAttribute(getFunctionTypeAttrName(result.name),
2053 TypeAttr::get(type));
2054 result.addAttribute(
2056 GlobalLinkageKindAttr::get(builder.getContext(), linkage));
2057 result.addAttribute(getGlobalVisibilityAttrName(result.name),
2058 cir::VisibilityAttr::get(builder.getContext()));
2061ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
2062 llvm::SMLoc loc = parser.getCurrentLocation();
2063 mlir::Builder &builder = parser.getBuilder();
2065 mlir::StringAttr builtinNameAttr = getBuiltinAttrName(state.name);
2066 mlir::StringAttr coroutineNameAttr = getCoroutineAttrName(state.name);
2067 mlir::StringAttr inlineKindNameAttr = getInlineKindAttrName(state.name);
2068 mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
2069 mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
2070 mlir::StringAttr comdatNameAttr = getComdatAttrName(state.name);
2071 mlir::StringAttr visNameAttr = getSymVisibilityAttrName(state.name);
2072 mlir::StringAttr visibilityNameAttr = getGlobalVisibilityAttrName(state.name);
2073 mlir::StringAttr dsoLocalNameAttr = getDsoLocalAttrName(state.name);
2074 mlir::StringAttr specialMemberAttr = getCxxSpecialMemberAttrName(state.name);
2076 if (::mlir::succeeded(parser.parseOptionalKeyword(builtinNameAttr.strref())))
2077 state.addAttribute(builtinNameAttr, parser.getBuilder().getUnitAttr());
2078 if (::mlir::succeeded(
2079 parser.parseOptionalKeyword(coroutineNameAttr.strref())))
2080 state.addAttribute(coroutineNameAttr, parser.getBuilder().getUnitAttr());
2083 cir::InlineKindAttr inlineKindAttr;
2087 state.addAttribute(inlineKindNameAttr, inlineKindAttr);
2089 if (::mlir::succeeded(parser.parseOptionalKeyword(lambdaNameAttr.strref())))
2090 state.addAttribute(lambdaNameAttr, parser.getBuilder().getUnitAttr());
2091 if (parser.parseOptionalKeyword(noProtoNameAttr).succeeded())
2092 state.addAttribute(noProtoNameAttr, parser.getBuilder().getUnitAttr());
2094 if (parser.parseOptionalKeyword(comdatNameAttr).succeeded())
2095 state.addAttribute(comdatNameAttr, parser.getBuilder().getUnitAttr());
2099 GlobalLinkageKindAttr::get(
2100 parser.getContext(),
2102 parser, GlobalLinkageKind::ExternalLinkage)));
2104 ::llvm::StringRef visAttrStr;
2105 if (parser.parseOptionalKeyword(&visAttrStr, {
"private",
"public",
"nested"})
2107 state.addAttribute(visNameAttr,
2108 parser.getBuilder().getStringAttr(visAttrStr));
2111 cir::VisibilityAttr cirVisibilityAttr;
2113 state.addAttribute(visibilityNameAttr, cirVisibilityAttr);
2115 if (parser.parseOptionalKeyword(dsoLocalNameAttr).succeeded())
2116 state.addAttribute(dsoLocalNameAttr, parser.getBuilder().getUnitAttr());
2118 StringAttr nameAttr;
2119 if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
2125 bool isVariadic =
false;
2126 if (function_interface_impl::parseFunctionSignatureWithArguments(
2127 parser,
true, arguments, isVariadic, resultTypes,
2132 bool argAttrsEmpty =
true;
2133 for (OpAsmParser::Argument &arg : arguments) {
2134 argTypes.push_back(
arg.type);
2138 argAttrs.push_back(
arg.attrs);
2140 argAttrsEmpty =
false;
2144 if (resultTypes.size() > 1 || resultAttrs.size() > 1)
2145 return parser.emitError(
2146 loc,
"functions with multiple return types are not supported");
2148 mlir::Type returnType =
2149 (resultTypes.empty() ? cir::VoidType::get(builder.getContext())
2150 : resultTypes.front());
2152 cir::FuncType fnType = cir::FuncType::get(argTypes, returnType, isVariadic);
2156 state.addAttribute(getFunctionTypeAttrName(state.name),
2157 TypeAttr::get(fnType));
2159 if (!resultAttrs.empty() && resultAttrs[0])
2161 getResAttrsAttrName(state.name),
2162 mlir::ArrayAttr::get(parser.getContext(), {resultAttrs[0]}));
2165 state.addAttribute(getArgAttrsAttrName(state.name),
2166 mlir::ArrayAttr::get(parser.getContext(), argAttrs));
2168 bool hasAlias =
false;
2169 mlir::StringAttr aliaseeNameAttr = getAliaseeAttrName(state.name);
2170 if (parser.parseOptionalKeyword(
"alias").succeeded()) {
2171 if (parser.parseLParen().failed())
2173 mlir::StringAttr aliaseeAttr;
2174 if (parser.parseOptionalSymbolName(aliaseeAttr).failed())
2176 state.addAttribute(aliaseeNameAttr, FlatSymbolRefAttr::get(aliaseeAttr));
2177 if (parser.parseRParen().failed())
2182 mlir::StringAttr personalityNameAttr = getPersonalityAttrName(state.name);
2183 if (parser.parseOptionalKeyword(
"personality").succeeded()) {
2184 if (parser.parseLParen().failed())
2186 mlir::StringAttr personalityAttr;
2187 if (parser.parseOptionalSymbolName(personalityAttr).failed())
2189 state.addAttribute(personalityNameAttr,
2190 FlatSymbolRefAttr::get(personalityAttr));
2191 if (parser.parseRParen().failed())
2195 auto parseGlobalDtorCtor =
2196 [&](StringRef keyword,
2197 llvm::function_ref<void(std::optional<int> prio)> createAttr)
2198 -> mlir::LogicalResult {
2199 if (mlir::succeeded(parser.parseOptionalKeyword(keyword))) {
2200 std::optional<int> priority;
2201 if (mlir::succeeded(parser.parseOptionalLParen())) {
2202 auto parsedPriority = mlir::FieldParser<int>::parse(parser);
2203 if (mlir::failed(parsedPriority))
2204 return parser.emitError(parser.getCurrentLocation(),
2205 "failed to parse 'priority', of type 'int'");
2206 priority = parsedPriority.value_or(
int());
2208 if (parser.parseRParen())
2211 createAttr(priority);
2217 if (parser.parseOptionalKeyword(
"special_member").succeeded()) {
2218 if (parser.parseLess().failed())
2221 mlir::Attribute
attr;
2222 if (parser.parseAttribute(attr).failed())
2224 if (!mlir::isa<cir::CXXCtorAttr, cir::CXXDtorAttr, cir::CXXAssignAttr>(
2226 return parser.emitError(parser.getCurrentLocation(),
2227 "expected a C++ special member attribute");
2228 state.addAttribute(specialMemberAttr, attr);
2230 if (parser.parseGreater().failed())
2234 if (parseGlobalDtorCtor(
"global_ctor", [&](std::optional<int> priority) {
2235 mlir::IntegerAttr globalCtorPriorityAttr =
2236 builder.getI32IntegerAttr(priority.value_or(65535));
2237 state.addAttribute(getGlobalCtorPriorityAttrName(state.name),
2238 globalCtorPriorityAttr);
2242 if (parseGlobalDtorCtor(
"global_dtor", [&](std::optional<int> priority) {
2243 mlir::IntegerAttr globalDtorPriorityAttr =
2244 builder.getI32IntegerAttr(priority.value_or(65535));
2245 state.addAttribute(getGlobalDtorPriorityAttrName(state.name),
2246 globalDtorPriorityAttr);
2250 if (parser.parseOptionalKeyword(
"side_effect").succeeded()) {
2251 cir::SideEffect sideEffect;
2253 if (parser.parseLParen().failed() ||
2255 parser.parseRParen().failed())
2258 auto attr = cir::SideEffectAttr::get(parser.getContext(), sideEffect);
2259 state.addAttribute(CIRDialect::getSideEffectAttrName(), attr);
2263 NamedAttrList parsedAttrs;
2264 if (parser.parseOptionalAttrDictWithKeyword(parsedAttrs))
2267 for (StringRef disallowed : cir::FuncOp::getAttributeNames()) {
2268 if (parsedAttrs.get(disallowed))
2269 return parser.emitError(loc,
"attribute '")
2271 <<
"' should not be specified in the explicit attribute list";
2274 state.attributes.append(parsedAttrs);
2277 auto *body = state.addRegion();
2278 OptionalParseResult parseResult = parser.parseOptionalRegion(
2279 *body, arguments,
false);
2280 if (parseResult.has_value()) {
2282 return parser.emitError(loc,
"function alias shall not have a body");
2283 if (failed(*parseResult))
2287 return parser.emitError(loc,
"expected non-empty function body");
2296bool cir::FuncOp::isDeclaration() {
2299 std::optional<StringRef> aliasee = getAliasee();
2301 return getFunctionBody().empty();
2307bool cir::FuncOp::isCXXSpecialMemberFunction() {
2308 return getCxxSpecialMemberAttr() !=
nullptr;
2311bool cir::FuncOp::isCxxConstructor() {
2312 auto attr = getCxxSpecialMemberAttr();
2313 return attr && dyn_cast<CXXCtorAttr>(attr);
2316bool cir::FuncOp::isCxxDestructor() {
2317 auto attr = getCxxSpecialMemberAttr();
2318 return attr && dyn_cast<CXXDtorAttr>(attr);
2321bool cir::FuncOp::isCxxSpecialAssignment() {
2322 auto attr = getCxxSpecialMemberAttr();
2323 return attr && dyn_cast<CXXAssignAttr>(attr);
2326std::optional<CtorKind> cir::FuncOp::getCxxConstructorKind() {
2327 mlir::Attribute
attr = getCxxSpecialMemberAttr();
2329 if (
auto ctor = dyn_cast<CXXCtorAttr>(attr))
2330 return ctor.getCtorKind();
2332 return std::nullopt;
2335std::optional<AssignKind> cir::FuncOp::getCxxSpecialAssignKind() {
2336 mlir::Attribute
attr = getCxxSpecialMemberAttr();
2338 if (
auto assign = dyn_cast<CXXAssignAttr>(attr))
2339 return assign.getAssignKind();
2341 return std::nullopt;
2344bool cir::FuncOp::isCxxTrivialMemberFunction() {
2345 mlir::Attribute
attr = getCxxSpecialMemberAttr();
2347 if (
auto ctor = dyn_cast<CXXCtorAttr>(attr))
2348 return ctor.getIsTrivial();
2349 if (
auto dtor = dyn_cast<CXXDtorAttr>(attr))
2350 return dtor.getIsTrivial();
2351 if (
auto assign = dyn_cast<CXXAssignAttr>(attr))
2352 return assign.getIsTrivial();
2357mlir::Region *cir::FuncOp::getCallableRegion() {
2363void cir::FuncOp::print(OpAsmPrinter &p) {
2381 if (getLinkage() != GlobalLinkageKind::ExternalLinkage)
2382 p <<
' ' << stringifyGlobalLinkageKind(getLinkage());
2384 mlir::SymbolTable::Visibility vis = getVisibility();
2385 if (vis != mlir::SymbolTable::Visibility::Public)
2388 cir::VisibilityAttr cirVisibilityAttr = getGlobalVisibilityAttr();
2389 if (!cirVisibilityAttr.isDefault()) {
2398 p.printSymbolName(getSymName());
2399 cir::FuncType fnType = getFunctionType();
2400 function_interface_impl::printFunctionSignature(
2401 p, *
this, fnType.getInputs(), fnType.isVarArg(), fnType.getReturnTypes());
2403 if (std::optional<StringRef> aliaseeName = getAliasee()) {
2405 p.printSymbolName(*aliaseeName);
2409 if (std::optional<StringRef> personalityName = getPersonality()) {
2410 p <<
" personality(";
2411 p.printSymbolName(*personalityName);
2415 if (
auto specialMemberAttr = getCxxSpecialMember()) {
2416 p <<
" special_member<";
2417 p.printAttribute(*specialMemberAttr);
2421 if (
auto globalCtorPriority = getGlobalCtorPriority()) {
2422 p <<
" global_ctor";
2423 if (globalCtorPriority.value() != 65535)
2424 p <<
"(" << globalCtorPriority.value() <<
")";
2427 if (
auto globalDtorPriority = getGlobalDtorPriority()) {
2428 p <<
" global_dtor";
2429 if (globalDtorPriority.value() != 65535)
2430 p <<
"(" << globalDtorPriority.value() <<
")";
2433 if (std::optional<cir::SideEffect> sideEffect = getSideEffect();
2434 sideEffect && *sideEffect != cir::SideEffect::All) {
2435 p <<
" side_effect(";
2436 p << stringifySideEffect(*sideEffect);
2440 function_interface_impl::printFunctionAttributes(
2441 p, *
this, cir::FuncOp::getAttributeNames());
2444 Region &body = getOperation()->getRegion(0);
2445 if (!body.empty()) {
2447 p.printRegion(body,
false,
2452mlir::LogicalResult cir::FuncOp::verify() {
2454 if (!isDeclaration() && getCoroutine()) {
2455 bool foundAwait =
false;
2456 this->walk([&](Operation *op) {
2457 if (
auto await = dyn_cast<AwaitOp>(op)) {
2463 return emitOpError()
2464 <<
"coroutine body must use at least one cir.await op";
2467 llvm::SmallSet<llvm::StringRef, 16> labels;
2468 llvm::SmallSet<llvm::StringRef, 16> gotos;
2469 llvm::SmallSet<llvm::StringRef, 16> blockAddresses;
2470 bool invalidBlockAddress =
false;
2471 getOperation()->walk([&](mlir::Operation *op) {
2472 if (
auto lab = dyn_cast<cir::LabelOp>(op)) {
2473 labels.insert(lab.getLabel());
2474 }
else if (
auto goTo = dyn_cast<cir::GotoOp>(op)) {
2475 gotos.insert(goTo.getLabel());
2476 }
else if (
auto blkAdd = dyn_cast<cir::BlockAddressOp>(op)) {
2477 if (blkAdd.getBlockAddrInfoAttr().getFunc().getAttr() != getSymName()) {
2479 invalidBlockAddress =
true;
2480 return mlir::WalkResult::interrupt();
2482 blockAddresses.insert(blkAdd.getBlockAddrInfoAttr().getLabel());
2484 return mlir::WalkResult::advance();
2487 if (invalidBlockAddress)
2488 return emitOpError() <<
"blockaddress references a different function";
2490 llvm::SmallSet<llvm::StringRef, 16> mismatched;
2491 if (!labels.empty() || !gotos.empty()) {
2492 mismatched = llvm::set_difference(gotos, labels);
2494 if (!mismatched.empty())
2495 return emitOpError() <<
"goto/label mismatch";
2500 if (!labels.empty() || !blockAddresses.empty()) {
2501 mismatched = llvm::set_difference(blockAddresses, labels);
2503 if (!mismatched.empty())
2504 return emitOpError()
2505 <<
"expects an existing label target in the referenced function";
2517 bool noUnsignedWrap,
bool saturated,
2519 bool noWrap = noSignedWrap || noUnsignedWrap;
2520 if (!isa<cir::IntType>(op->getResultTypes()[0]) && noWrap)
2521 return op->emitError()
2522 <<
"only operations on integer values may have nsw/nuw flags";
2523 if (hasSat && saturated && !isa<cir::IntType>(op->getResultTypes()[0]))
2524 return op->emitError()
2525 <<
"only operations on integer values may have sat flag";
2526 if (hasSat && noWrap && saturated)
2527 return op->emitError()
2528 <<
"the nsw/nuw flags and the saturated flag are mutually exclusive";
2529 return mlir::success();
2532LogicalResult cir::AddOp::verify() {
2534 getNoUnsignedWrap(), getSaturated(),
2538LogicalResult cir::SubOp::verify() {
2540 getNoUnsignedWrap(), getSaturated(),
2544LogicalResult cir::MulOp::verify() {
2546 getNoUnsignedWrap(),
false,
2559void cir::TernaryOp::getSuccessorRegions(
2560 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
2562 if (!point.isParent()) {
2563 regions.push_back(RegionSuccessor::parent());
2569 regions.push_back(RegionSuccessor(&getTrueRegion()));
2570 regions.push_back(RegionSuccessor(&getFalseRegion()));
2573mlir::ValueRange cir::TernaryOp::getSuccessorInputs(RegionSuccessor successor) {
2574 return successor.isParent() ? ValueRange(getOperation()->getResults())
2578void cir::TernaryOp::build(
2579 OpBuilder &builder, OperationState &result,
Value cond,
2580 function_ref<
void(OpBuilder &, Location)> trueBuilder,
2581 function_ref<
void(OpBuilder &, Location)> falseBuilder) {
2582 result.addOperands(cond);
2583 OpBuilder::InsertionGuard guard(builder);
2584 Region *trueRegion = result.addRegion();
2585 builder.createBlock(trueRegion);
2586 trueBuilder(builder, result.location);
2587 Region *falseRegion = result.addRegion();
2588 builder.createBlock(falseRegion);
2589 falseBuilder(builder, result.location);
2594 if (trueRegion->back().mightHaveTerminator())
2595 yield = dyn_cast_or_null<cir::YieldOp>(trueRegion->back().getTerminator());
2596 if (!yield && falseRegion->back().mightHaveTerminator())
2597 yield = dyn_cast_or_null<cir::YieldOp>(falseRegion->back().getTerminator());
2599 assert((!yield || yield.getNumOperands() <= 1) &&
2600 "expected zero or one result type");
2601 if (yield && yield.getNumOperands() == 1)
2602 result.addTypes(TypeRange{yield.getOperandTypes().front()});
2609OpFoldResult cir::SelectOp::fold(FoldAdaptor adaptor) {
2610 mlir::Attribute
condition = adaptor.getCondition();
2612 bool conditionValue = mlir::cast<cir::BoolAttr>(
condition).getValue();
2613 return conditionValue ? getTrueValue() : getFalseValue();
2617 mlir::Attribute trueValue = adaptor.getTrueValue();
2618 mlir::Attribute falseValue = adaptor.getFalseValue();
2619 if (trueValue == falseValue)
2621 if (getTrueValue() == getFalseValue())
2622 return getTrueValue();
2627LogicalResult cir::SelectOp::verify() {
2629 auto condTy = dyn_cast<cir::VectorType>(getCondition().
getType());
2636 if (!isa<cir::VectorType>(getTrueValue().
getType()) ||
2637 !isa<cir::VectorType>(getFalseValue().
getType())) {
2638 return emitOpError()
2639 <<
"expected both true and false operands to be vector types "
2640 "when the condition is a vector boolean type";
2649LogicalResult cir::ShiftOp::verify() {
2650 mlir::Operation *op = getOperation();
2651 auto op0VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(0).getType());
2652 auto op1VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(1).getType());
2653 if (!op0VecTy ^ !op1VecTy)
2654 return emitOpError() <<
"input types cannot be one vector and one scalar";
2657 if (op0VecTy.getSize() != op1VecTy.getSize())
2658 return emitOpError() <<
"input vector types must have the same size";
2660 auto opResultTy = mlir::dyn_cast<cir::VectorType>(
getType());
2662 return emitOpError() <<
"the type of the result must be a vector "
2663 <<
"if it is vector shift";
2665 auto op0VecEleTy = mlir::cast<cir::IntType>(op0VecTy.getElementType());
2666 auto op1VecEleTy = mlir::cast<cir::IntType>(op1VecTy.getElementType());
2667 if (op0VecEleTy.getWidth() != op1VecEleTy.getWidth())
2668 return emitOpError()
2669 <<
"vector operands do not have the same elements sizes";
2671 auto resVecEleTy = mlir::cast<cir::IntType>(opResultTy.getElementType());
2672 if (op0VecEleTy.getWidth() != resVecEleTy.getWidth())
2673 return emitOpError() <<
"vector operands and result type do not have the "
2674 "same elements sizes";
2677 return mlir::success();
2684LogicalResult cir::LabelOp::verify() {
2685 mlir::Operation *op = getOperation();
2686 mlir::Block *blk = op->getBlock();
2687 if (&blk->front() != op)
2688 return emitError() <<
"must be the first operation in a block";
2690 return mlir::success();
2697OpFoldResult cir::IncOp::fold(FoldAdaptor adaptor) {
2698 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
2699 return adaptor.getInput();
2707OpFoldResult cir::DecOp::fold(FoldAdaptor adaptor) {
2708 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
2709 return adaptor.getInput();
2717OpFoldResult cir::MinusOp::fold(FoldAdaptor adaptor) {
2718 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
2719 return adaptor.getInput();
2722 if (
auto srcConst = getInput().getDefiningOp<cir::ConstantOp>())
2723 if (mlir::isa<cir::BoolType>(srcConst.getType()))
2724 return srcConst.getResult();
2727 if (mlir::Attribute attr = adaptor.getInput()) {
2728 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr)) {
2729 APInt val = intAttr.getValue();
2731 return cir::IntAttr::get(
getType(), val);
2733 if (
auto fpAttr = mlir::dyn_cast<cir::FPAttr>(attr)) {
2734 APFloat val = fpAttr.getValue();
2736 return cir::FPAttr::get(
getType(), val);
2747OpFoldResult cir::NotOp::fold(FoldAdaptor adaptor) {
2748 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
2749 return adaptor.getInput();
2754 if (mlir::Attribute attr = adaptor.getInput()) {
2755 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr)) {
2756 APInt val = intAttr.getValue();
2758 return cir::IntAttr::get(
getType(), val);
2760 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr))
2761 return cir::BoolAttr::get(getContext(), !boolAttr.getValue());
2772 mlir::Type resultTy) {
2775 mlir::Type inputMemberTy;
2776 mlir::Type resultMemberTy;
2777 if (mlir::isa<cir::DataMemberType>(src.getType())) {
2779 mlir::cast<cir::DataMemberType>(src.getType()).getMemberTy();
2780 resultMemberTy = mlir::cast<cir::DataMemberType>(resultTy).getMemberTy();
2783 if (inputMemberTy != resultMemberTy)
2784 return op->emitOpError()
2785 <<
"member types of the operand and the result do not match";
2787 return mlir::success();
2790LogicalResult cir::BaseDataMemberOp::verify() {
2794LogicalResult cir::DerivedDataMemberOp::verify() {
2802LogicalResult cir::BaseMethodOp::verify() {
2806LogicalResult cir::DerivedMethodOp::verify() {
2814void cir::AwaitOp::build(OpBuilder &builder, OperationState &result,
2818 result.addAttribute(getKindAttrName(result.name),
2819 cir::AwaitKindAttr::get(builder.getContext(),
kind));
2821 OpBuilder::InsertionGuard guard(builder);
2822 Region *readyRegion = result.addRegion();
2823 builder.createBlock(readyRegion);
2824 readyBuilder(builder, result.location);
2828 OpBuilder::InsertionGuard guard(builder);
2829 Region *suspendRegion = result.addRegion();
2830 builder.createBlock(suspendRegion);
2831 suspendBuilder(builder, result.location);
2835 OpBuilder::InsertionGuard guard(builder);
2836 Region *resumeRegion = result.addRegion();
2837 builder.createBlock(resumeRegion);
2838 resumeBuilder(builder, result.location);
2842void cir::AwaitOp::getSuccessorRegions(
2843 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
2846 if (!point.isParent()) {
2847 regions.push_back(RegionSuccessor::parent());
2854 regions.push_back(RegionSuccessor(&this->getReady()));
2855 regions.push_back(RegionSuccessor(&this->getSuspend()));
2856 regions.push_back(RegionSuccessor(&this->getResume()));
2859mlir::ValueRange cir::AwaitOp::getSuccessorInputs(RegionSuccessor successor) {
2860 if (successor.isParent())
2861 return getOperation()->getResults();
2862 if (successor == &getReady())
2863 return getReady().getArguments();
2864 if (successor == &getSuspend())
2865 return getSuspend().getArguments();
2866 if (successor == &getResume())
2867 return getResume().getArguments();
2868 llvm_unreachable(
"invalid region successor");
2871LogicalResult cir::AwaitOp::verify() {
2872 if (!isa<ConditionOp>(this->getReady().back().getTerminator()))
2873 return emitOpError(
"ready region must end with cir.condition");
2881LogicalResult cir::CopyOp::verify() {
2883 if (!
getType().getPointee().hasTrait<DataLayoutTypeInterface::Trait>())
2884 return emitError() <<
"missing data layout for pointee type";
2886 if (getSrc() == getDst())
2887 return emitError() <<
"source and destination are the same";
2889 return mlir::success();
2896LogicalResult cir::GetRuntimeMemberOp::verify() {
2897 auto recordTy = mlir::cast<RecordType>(getAddr().
getType().getPointee());
2898 cir::DataMemberType memberPtrTy = getMember().getType();
2900 if (recordTy != memberPtrTy.getClassTy())
2901 return emitError() <<
"record type does not match the member pointer type";
2902 if (
getType().getPointee() != memberPtrTy.getMemberTy())
2903 return emitError() <<
"result type does not match the member pointer type";
2904 return mlir::success();
2911LogicalResult cir::GetMethodOp::verify() {
2912 cir::MethodType methodTy = getMethod().getType();
2915 cir::PointerType objectPtrTy = getObject().getType();
2916 mlir::Type objectTy = objectPtrTy.getPointee();
2918 if (methodTy.getClassTy() != objectTy)
2919 return emitError() <<
"method class type and object type do not match";
2922 auto calleeTy = mlir::cast<cir::FuncType>(getCallee().
getType().getPointee());
2923 cir::FuncType methodFuncTy = methodTy.getMemberFuncTy();
2930 if (methodFuncTy.getReturnType() != calleeTy.getReturnType())
2932 <<
"method return type and callee return type do not match";
2937 if (calleeArgsTy.empty())
2938 return emitError() <<
"callee parameter list lacks receiver object ptr";
2940 auto calleeThisArgPtrTy = mlir::dyn_cast<cir::PointerType>(calleeArgsTy[0]);
2941 if (!calleeThisArgPtrTy ||
2942 !mlir::isa<cir::VoidType>(calleeThisArgPtrTy.getPointee())) {
2944 <<
"the first parameter of callee must be a void pointer";
2947 if (calleeArgsTy.slice(1) != methodFuncArgsTy)
2949 <<
"callee parameters and method parameters do not match";
2951 return mlir::success();
2958LogicalResult cir::GetMemberOp::verify() {
2959 const auto recordTy = dyn_cast<RecordType>(getAddrTy().getPointee());
2961 return emitError() <<
"expected pointer to a record type";
2963 if (recordTy.getMembers().size() <=
getIndex())
2964 return emitError() <<
"member index out of bounds";
2967 return emitError() <<
"member type mismatch";
2969 return mlir::success();
2976LogicalResult cir::ExtractMemberOp::verify() {
2977 auto recordTy = mlir::cast<cir::RecordType>(getRecord().
getType());
2978 if (recordTy.getKind() == cir::RecordType::Union)
2980 <<
"cir.extract_member currently does not support unions";
2981 if (recordTy.getMembers().size() <=
getIndex())
2982 return emitError() <<
"member index out of bounds";
2984 return emitError() <<
"member type mismatch";
2985 return mlir::success();
2992LogicalResult cir::InsertMemberOp::verify() {
2993 auto recordTy = mlir::cast<cir::RecordType>(getRecord().
getType());
2994 if (recordTy.getKind() == cir::RecordType::Union)
2995 return emitError() <<
"cir.insert_member currently does not support unions";
2996 if (recordTy.getMembers().size() <=
getIndex())
2997 return emitError() <<
"member index out of bounds";
2999 return emitError() <<
"member type mismatch";
3001 return mlir::success();
3008OpFoldResult cir::VecCreateOp::fold(FoldAdaptor adaptor) {
3009 if (llvm::any_of(getElements(), [](mlir::Value value) {
3010 return !value.getDefiningOp<cir::ConstantOp>();
3014 return cir::ConstVectorAttr::get(
3015 getType(), mlir::ArrayAttr::get(getContext(), adaptor.getElements()));
3018LogicalResult cir::VecCreateOp::verify() {
3022 const cir::VectorType vecTy =
getType();
3023 if (getElements().size() != vecTy.getSize()) {
3024 return emitOpError() <<
"operand count of " << getElements().size()
3025 <<
" doesn't match vector type " << vecTy
3026 <<
" element count of " << vecTy.getSize();
3029 const mlir::Type elementType = vecTy.getElementType();
3030 for (
const mlir::Value element : getElements()) {
3031 if (element.getType() != elementType) {
3032 return emitOpError() <<
"operand type " << element.getType()
3033 <<
" doesn't match vector element type "
3045OpFoldResult cir::VecExtractOp::fold(FoldAdaptor adaptor) {
3046 const auto vectorAttr =
3047 llvm::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec());
3051 const auto indexAttr =
3052 llvm::dyn_cast_if_present<cir::IntAttr>(adaptor.getIndex());
3056 const mlir::ArrayAttr elements = vectorAttr.getElts();
3057 const uint64_t index = indexAttr.getUInt();
3058 if (index >= elements.size())
3061 return elements[index];
3068OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
3070 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getLhs());
3072 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getRhs());
3073 if (!lhsVecAttr || !rhsVecAttr)
3076 mlir::Type inputElemTy =
3077 mlir::cast<cir::VectorType>(lhsVecAttr.getType()).getElementType();
3078 if (!isAnyIntegerOrFloatingPointType(inputElemTy))
3081 cir::CmpOpKind opKind = adaptor.getKind();
3082 mlir::ArrayAttr lhsVecElhs = lhsVecAttr.getElts();
3083 mlir::ArrayAttr rhsVecElhs = rhsVecAttr.getElts();
3084 uint64_t vecSize = lhsVecElhs.size();
3087 bool isIntAttr = vecSize && mlir::isa<cir::IntAttr>(lhsVecElhs[0]);
3088 for (uint64_t i = 0; i < vecSize; i++) {
3089 mlir::Attribute lhsAttr = lhsVecElhs[i];
3090 mlir::Attribute rhsAttr = rhsVecElhs[i];
3093 case cir::CmpOpKind::lt: {
3095 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <
3096 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3098 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <
3099 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3103 case cir::CmpOpKind::le: {
3105 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <=
3106 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3108 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <=
3109 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3113 case cir::CmpOpKind::gt: {
3115 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >
3116 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3118 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >
3119 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3123 case cir::CmpOpKind::ge: {
3125 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >=
3126 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3128 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >=
3129 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3133 case cir::CmpOpKind::eq: {
3135 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() ==
3136 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3138 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() ==
3139 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3143 case cir::CmpOpKind::ne: {
3145 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() !=
3146 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3148 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() !=
3149 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3155 elements[i] = cir::IntAttr::get(
getType().getElementType(), cmpResult);
3158 return cir::ConstVectorAttr::get(
3159 getType(), mlir::ArrayAttr::get(getContext(), elements));
3166OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor adaptor) {
3168 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec1());
3170 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec2());
3171 if (!vec1Attr || !vec2Attr)
3174 mlir::Type vec1ElemTy =
3175 mlir::cast<cir::VectorType>(vec1Attr.getType()).getElementType();
3177 mlir::ArrayAttr vec1Elts = vec1Attr.getElts();
3178 mlir::ArrayAttr vec2Elts = vec2Attr.getElts();
3179 mlir::ArrayAttr indicesElts = adaptor.getIndices();
3182 elements.reserve(indicesElts.size());
3184 uint64_t vec1Size = vec1Elts.size();
3185 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
3186 if (idxAttr.getSInt() == -1) {
3187 elements.push_back(cir::UndefAttr::get(vec1ElemTy));
3191 uint64_t idxValue = idxAttr.getUInt();
3192 elements.push_back(idxValue < vec1Size ? vec1Elts[idxValue]
3193 : vec2Elts[idxValue - vec1Size]);
3196 return cir::ConstVectorAttr::get(
3197 getType(), mlir::ArrayAttr::get(getContext(), elements));
3200LogicalResult cir::VecShuffleOp::verify() {
3203 if (getIndices().size() != getResult().
getType().getSize()) {
3204 return emitOpError() <<
": the number of elements in " << getIndices()
3205 <<
" and " << getResult().getType() <<
" don't match";
3210 if (getVec1().
getType().getElementType() !=
3211 getResult().
getType().getElementType()) {
3212 return emitOpError() <<
": element types of " << getVec1().getType()
3213 <<
" and " << getResult().getType() <<
" don't match";
3216 const uint64_t maxValidIndex =
3217 getVec1().getType().getSize() + getVec2().getType().getSize() - 1;
3219 getIndices().getAsRange<cir::IntAttr>(), [&](cir::IntAttr idxAttr) {
3220 return idxAttr.getSInt() != -1 && idxAttr.getUInt() > maxValidIndex;
3222 return emitOpError() <<
": index for __builtin_shufflevector must be "
3223 "less than the total number of vector elements";
3232OpFoldResult cir::VecShuffleDynamicOp::fold(FoldAdaptor adaptor) {
3233 mlir::Attribute vec = adaptor.getVec();
3234 mlir::Attribute indices = adaptor.getIndices();
3235 if (mlir::isa_and_nonnull<cir::ConstVectorAttr>(vec) &&
3236 mlir::isa_and_nonnull<cir::ConstVectorAttr>(indices)) {
3237 auto vecAttr = mlir::cast<cir::ConstVectorAttr>(vec);
3238 auto indicesAttr = mlir::cast<cir::ConstVectorAttr>(indices);
3240 mlir::ArrayAttr vecElts = vecAttr.getElts();
3241 mlir::ArrayAttr indicesElts = indicesAttr.getElts();
3243 const uint64_t numElements = vecElts.size();
3246 elements.reserve(numElements);
3248 const uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
3249 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
3250 uint64_t idxValue = idxAttr.getUInt();
3251 uint64_t newIdx = idxValue & maskBits;
3252 elements.push_back(vecElts[newIdx]);
3255 return cir::ConstVectorAttr::get(
3256 getType(), mlir::ArrayAttr::get(getContext(), elements));
3262LogicalResult cir::VecShuffleDynamicOp::verify() {
3264 if (getVec().
getType().getSize() !=
3265 mlir::cast<cir::VectorType>(getIndices().
getType()).getSize()) {
3266 return emitOpError() <<
": the number of elements in " << getVec().getType()
3267 <<
" and " << getIndices().getType() <<
" don't match";
3276LogicalResult cir::VecTernaryOp::verify() {
3281 if (getCond().
getType().getSize() != getLhs().
getType().getSize()) {
3282 return emitOpError() <<
": the number of elements in "
3283 << getCond().getType() <<
" and " << getLhs().getType()
3289OpFoldResult cir::VecTernaryOp::fold(FoldAdaptor adaptor) {
3290 mlir::Attribute cond = adaptor.getCond();
3291 mlir::Attribute lhs = adaptor.getLhs();
3292 mlir::Attribute rhs = adaptor.getRhs();
3294 if (!mlir::isa_and_nonnull<cir::ConstVectorAttr>(cond) ||
3295 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(lhs) ||
3296 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(rhs))
3298 auto condVec = mlir::cast<cir::ConstVectorAttr>(cond);
3299 auto lhsVec = mlir::cast<cir::ConstVectorAttr>(lhs);
3300 auto rhsVec = mlir::cast<cir::ConstVectorAttr>(rhs);
3302 mlir::ArrayAttr condElts = condVec.getElts();
3305 elements.reserve(condElts.size());
3307 for (
const auto &[idx, condAttr] :
3308 llvm::enumerate(condElts.getAsRange<cir::IntAttr>())) {
3309 if (condAttr.getSInt()) {
3310 elements.push_back(lhsVec.getElts()[idx]);
3312 elements.push_back(rhsVec.getElts()[idx]);
3316 cir::VectorType vecTy = getLhs().getType();
3317 return cir::ConstVectorAttr::get(
3318 vecTy, mlir::ArrayAttr::get(getContext(), elements));
3325LogicalResult cir::ComplexCreateOp::verify() {
3328 <<
"operand type of cir.complex.create does not match its result type";
3335OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) {
3336 mlir::Attribute real = adaptor.getReal();
3337 mlir::Attribute imag = adaptor.getImag();
3343 auto realAttr = mlir::cast<mlir::TypedAttr>(real);
3344 auto imagAttr = mlir::cast<mlir::TypedAttr>(imag);
3345 return cir::ConstComplexAttr::get(realAttr, imagAttr);
3352LogicalResult cir::ComplexRealOp::verify() {
3353 mlir::Type operandTy = getOperand().getType();
3354 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
3355 operandTy = complexOperandTy.getElementType();
3358 emitOpError() <<
": result type does not match operand type";
3365OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) {
3366 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
3369 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
3370 return complexCreateOp.getOperand(0);
3373 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
3374 return complex ? complex.getReal() :
nullptr;
3381LogicalResult cir::ComplexImagOp::verify() {
3382 mlir::Type operandTy = getOperand().getType();
3383 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
3384 operandTy = complexOperandTy.getElementType();
3387 emitOpError() <<
": result type does not match operand type";
3394OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) {
3395 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
3398 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
3399 return complexCreateOp.getOperand(1);
3402 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
3403 return complex ? complex.getImag() :
nullptr;
3410LogicalResult cir::ComplexRealPtrOp::verify() {
3411 mlir::Type resultPointeeTy =
getType().getPointee();
3412 cir::PointerType operandPtrTy = getOperand().getType();
3413 auto operandPointeeTy =
3414 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
3416 if (resultPointeeTy != operandPointeeTy.getElementType()) {
3417 return emitOpError() <<
": result type does not match operand type";
3427LogicalResult cir::ComplexImagPtrOp::verify() {
3428 mlir::Type resultPointeeTy =
getType().getPointee();
3429 cir::PointerType operandPtrTy = getOperand().getType();
3430 auto operandPointeeTy =
3431 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
3433 if (resultPointeeTy != operandPointeeTy.getElementType()) {
3434 return emitOpError()
3435 <<
"cir.complex.imag_ptr result type does not match operand type";
3446 llvm::function_ref<llvm::APInt(
const llvm::APInt &)> func,
3447 bool poisonZero =
false) {
3448 if (mlir::isa_and_present<cir::PoisonAttr>(inputAttr)) {
3453 auto input = mlir::dyn_cast_if_present<IntAttr>(inputAttr);
3457 llvm::APInt inputValue = input.getValue();
3458 if (poisonZero && inputValue.isZero())
3459 return cir::PoisonAttr::get(input.getType());
3461 llvm::APInt resultValue = func(inputValue);
3462 return IntAttr::get(input.getType(), resultValue);
3465OpFoldResult BitClrsbOp::fold(FoldAdaptor adaptor) {
3466 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3467 unsigned resultValue =
3468 inputValue.getBitWidth() - inputValue.getSignificantBits();
3469 return llvm::APInt(inputValue.getBitWidth(), resultValue);
3473OpFoldResult BitClzOp::fold(FoldAdaptor adaptor) {
3476 [](
const llvm::APInt &inputValue) {
3477 unsigned resultValue = inputValue.countLeadingZeros();
3478 return llvm::APInt(inputValue.getBitWidth(), resultValue);
3483OpFoldResult BitCtzOp::fold(FoldAdaptor adaptor) {
3486 [](
const llvm::APInt &inputValue) {
3487 return llvm::APInt(inputValue.getBitWidth(),
3488 inputValue.countTrailingZeros());
3493OpFoldResult BitFfsOp::fold(FoldAdaptor adaptor) {
3494 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3495 unsigned trailingZeros = inputValue.countTrailingZeros();
3497 trailingZeros == inputValue.getBitWidth() ? 0 : trailingZeros + 1;
3498 return llvm::APInt(inputValue.getBitWidth(), result);
3502OpFoldResult BitParityOp::fold(FoldAdaptor adaptor) {
3503 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3504 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount() % 2);
3508OpFoldResult BitPopcountOp::fold(FoldAdaptor adaptor) {
3509 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3510 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount());
3514OpFoldResult BitReverseOp::fold(FoldAdaptor adaptor) {
3515 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3516 return inputValue.reverseBits();
3520OpFoldResult ByteSwapOp::fold(FoldAdaptor adaptor) {
3521 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3522 return inputValue.byteSwap();
3526OpFoldResult RotateOp::fold(FoldAdaptor adaptor) {
3527 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()) ||
3528 mlir::isa_and_present<cir::PoisonAttr>(adaptor.getAmount())) {
3530 return cir::PoisonAttr::get(
getType());
3533 auto input = mlir::dyn_cast_if_present<IntAttr>(adaptor.getInput());
3534 auto amount = mlir::dyn_cast_if_present<IntAttr>(adaptor.getAmount());
3535 if (!input && !amount)
3544 llvm::APInt inputValue;
3546 inputValue = input.getValue();
3547 if (inputValue.isZero() || inputValue.isAllOnes()) {
3553 uint64_t amountValue;
3555 amountValue = amount.getValue().urem(getInput().
getType().getWidth());
3556 if (amountValue == 0) {
3562 if (!input || !amount)
3565 assert(inputValue.getBitWidth() == getInput().
getType().getWidth() &&
3566 "input value must have the same bit width as the input type");
3568 llvm::APInt resultValue;
3570 resultValue = inputValue.rotl(amountValue);
3572 resultValue = inputValue.rotr(amountValue);
3574 return IntAttr::get(input.getContext(), input.getType(), resultValue);
3581void cir::InlineAsmOp::print(OpAsmPrinter &p) {
3582 p <<
'(' << getAsmFlavor() <<
", ";
3587 auto *nameIt = names.begin();
3588 auto *attrIt = getOperandAttrs().begin();
3590 for (mlir::OperandRange ops : getAsmOperands()) {
3591 p << *nameIt <<
" = ";
3594 llvm::interleaveComma(llvm::make_range(ops.begin(), ops.end()), p,
3596 p.printOperand(value);
3597 p <<
" : " << value.getType();
3599 p <<
" (maybe_memory)";
3608 p.printString(getAsmString());
3610 p.printString(getConstraints());
3614 if (getSideEffects())
3615 p <<
" side_effects";
3617 std::array elidedAttrs{
3618 llvm::StringRef(
"asm_flavor"), llvm::StringRef(
"asm_string"),
3619 llvm::StringRef(
"constraints"), llvm::StringRef(
"operand_attrs"),
3620 llvm::StringRef(
"operands_segments"), llvm::StringRef(
"side_effects")};
3621 p.printOptionalAttrDict(getOperation()->getAttrs(), elidedAttrs);
3623 if (
auto v = getRes())
3624 p <<
" -> " << v.getType();
3627void cir::InlineAsmOp::build(OpBuilder &odsBuilder, OperationState &odsState,
3629 StringRef asmString, StringRef constraints,
3630 bool sideEffects, cir::AsmFlavor asmFlavor,
3634 for (
auto operandRange : asmOperands) {
3635 segments.push_back(operandRange.size());
3636 odsState.addOperands(operandRange);
3639 odsState.addAttribute(
3640 "operands_segments",
3641 DenseI32ArrayAttr::get(odsBuilder.getContext(), segments));
3642 odsState.addAttribute(
"asm_string", odsBuilder.getStringAttr(asmString));
3643 odsState.addAttribute(
"constraints", odsBuilder.getStringAttr(constraints));
3644 odsState.addAttribute(
"asm_flavor",
3645 AsmFlavorAttr::get(odsBuilder.getContext(), asmFlavor));
3648 odsState.addAttribute(
"side_effects", odsBuilder.getUnitAttr());
3650 odsState.addAttribute(
"operand_attrs", odsBuilder.getArrayAttr(operandAttrs));
3653ParseResult cir::InlineAsmOp::parse(OpAsmParser &parser,
3654 OperationState &result) {
3657 std::string asmString, constraints;
3659 MLIRContext *ctxt = parser.getBuilder().getContext();
3661 auto error = [&](
const Twine &msg) -> LogicalResult {
3662 return parser.emitError(parser.getCurrentLocation(), msg);
3665 auto expected = [&](
const std::string &
c) {
3666 return error(
"expected '" +
c +
"'");
3669 if (parser.parseLParen().failed())
3670 return expected(
"(");
3672 auto flavor = FieldParser<AsmFlavor, AsmFlavor>::parse(parser);
3674 return error(
"Unknown AsmFlavor");
3676 if (parser.parseComma().failed())
3677 return expected(
",");
3679 auto parseValue = [&](
Value &v) {
3680 OpAsmParser::UnresolvedOperand op;
3682 if (parser.parseOperand(op) || parser.parseColon())
3683 return error(
"can't parse operand");
3686 if (parser.parseType(typ).failed())
3687 return error(
"can't parse operand type");
3689 if (parser.resolveOperand(op, typ, tmp))
3690 return error(
"can't resolve operand");
3692 return mlir::success();
3695 auto parseOperands = [&](llvm::StringRef
name) {
3696 if (parser.parseKeyword(name).failed())
3697 return error(
"expected " + name +
" operands here");
3698 if (parser.parseEqual().failed())
3699 return expected(
"=");
3700 if (parser.parseLSquare().failed())
3701 return expected(
"[");
3704 if (parser.parseOptionalRSquare().succeeded()) {
3705 operandsGroupSizes.push_back(size);
3706 if (parser.parseComma())
3707 return expected(
",");
3708 return mlir::success();
3711 auto parseOperand = [&]() {
3713 if (parseValue(val).succeeded()) {
3714 result.operands.push_back(val);
3717 if (parser.parseOptionalLParen().failed()) {
3718 operandAttrs.push_back(mlir::Attribute());
3719 return mlir::success();
3722 if (parser.parseKeyword(
"maybe_memory").succeeded()) {
3723 operandAttrs.push_back(mlir::UnitAttr::get(ctxt));
3724 if (parser.parseRParen())
3725 return expected(
")");
3726 return mlir::success();
3728 return expected(
"maybe_memory");
3731 return mlir::failure();
3734 if (parser.parseCommaSeparatedList(parseOperand).failed())
3735 return mlir::failure();
3737 if (parser.parseRSquare().failed() || parser.parseComma().failed())
3738 return expected(
"]");
3739 operandsGroupSizes.push_back(size);
3740 return mlir::success();
3743 if (parseOperands(
"out").failed() || parseOperands(
"in").failed() ||
3744 parseOperands(
"in_out").failed())
3745 return error(
"failed to parse operands");
3747 if (parser.parseLBrace())
3748 return expected(
"{");
3749 if (parser.parseString(&asmString))
3750 return error(
"asm string parsing failed");
3751 if (parser.parseString(&constraints))
3752 return error(
"constraints string parsing failed");
3753 if (parser.parseRBrace())
3754 return expected(
"}");
3755 if (parser.parseRParen())
3756 return expected(
")");
3758 if (parser.parseOptionalKeyword(
"side_effects").succeeded())
3759 result.attributes.set(
"side_effects", UnitAttr::get(ctxt));
3761 if (parser.parseOptionalArrow().succeeded() &&
3762 parser.parseType(resType).failed())
3763 return mlir::failure();
3765 if (parser.parseOptionalAttrDict(result.attributes).failed())
3766 return mlir::failure();
3768 result.attributes.set(
"asm_flavor", AsmFlavorAttr::get(ctxt, *flavor));
3769 result.attributes.set(
"asm_string", StringAttr::get(ctxt, asmString));
3770 result.attributes.set(
"constraints", StringAttr::get(ctxt, constraints));
3771 result.attributes.set(
"operand_attrs", ArrayAttr::get(ctxt, operandAttrs));
3772 result.getOrAddProperties<InlineAsmOp::Properties>().operands_segments =
3773 parser.getBuilder().getDenseI32ArrayAttr(operandsGroupSizes);
3775 result.addTypes(TypeRange{resType});
3777 return mlir::success();
3784mlir::LogicalResult cir::ThrowOp::verify() {
3789 if (getNumOperands() != 0) {
3792 return emitOpError() <<
"'type_info' symbol attribute missing";
3802LogicalResult cir::AtomicFetchOp::verify() {
3803 if (getBinop() != cir::AtomicFetchKind::Add &&
3804 getBinop() != cir::AtomicFetchKind::Sub &&
3805 getBinop() != cir::AtomicFetchKind::Max &&
3806 getBinop() != cir::AtomicFetchKind::Min &&
3807 !mlir::isa<cir::IntType>(getVal().
getType()))
3808 return emitError(
"only atomic add, sub, max, and min operation could "
3809 "operate on floating-point values");
3817LogicalResult cir::TypeInfoAttr::verify(
3818 ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
3819 ::mlir::Type type, ::mlir::ArrayAttr typeInfoData) {
3821 if (cir::ConstRecordAttr::verify(emitError, type, typeInfoData).failed())
3831void cir::TryOp::getSuccessorRegions(
3832 mlir::RegionBranchPoint point,
3835 if (!point.isParent()) {
3836 regions.push_back(RegionSuccessor::parent());
3840 regions.push_back(mlir::RegionSuccessor(&getTryRegion()));
3844 for (mlir::Region &handlerRegion : this->getHandlerRegions())
3845 regions.push_back(mlir::RegionSuccessor(&handlerRegion));
3848mlir::ValueRange cir::TryOp::getSuccessorInputs(RegionSuccessor successor) {
3849 return successor.isParent() ? ValueRange(getOperation()->getResults())
3853LogicalResult cir::TryOp::verify() {
3854 mlir::ArrayAttr handlerTypes = getHandlerTypes();
3855 if (!handlerTypes) {
3856 if (!getHandlerRegions().empty())
3858 "handler regions must be empty when no handler types are present");
3862 mlir::MutableArrayRef<mlir::Region> handlerRegions = getHandlerRegions();
3866 if (handlerRegions.size() != handlerTypes.size())
3868 "number of handler regions and handler types must match");
3870 for (
const auto &[typeAttr, handlerRegion] :
3871 llvm::zip(handlerTypes, handlerRegions)) {
3873 mlir::Block &entryBlock = handlerRegion.front();
3874 if (entryBlock.getNumArguments() != 1 ||
3875 !mlir::isa<cir::EhTokenType>(entryBlock.getArgument(0).getType()))
3877 "handler region must have a single '!cir.eh_token' argument");
3880 if (mlir::isa<cir::UnwindAttr>(typeAttr))
3883 if (entryBlock.empty() || !mlir::isa<cir::BeginCatchOp>(entryBlock.front()))
3885 "catch handler region must start with 'cir.begin_catch'");
3893 mlir::MutableArrayRef<mlir::Region> handlerRegions,
3894 mlir::ArrayAttr handlerTypes) {
3898 for (
const auto [typeIdx, typeAttr] : llvm::enumerate(handlerTypes)) {
3902 if (mlir::isa<cir::CatchAllAttr>(typeAttr)) {
3903 printer <<
"catch all ";
3904 }
else if (mlir::isa<cir::UnwindAttr>(typeAttr)) {
3905 printer <<
"unwind ";
3907 printer <<
"catch [type ";
3908 printer.printAttribute(typeAttr);
3913 mlir::Region ®ion = handlerRegions[typeIdx];
3914 if (!region.empty() && region.front().getNumArguments() > 0) {
3916 printer.printRegionArgument(region.front().getArgument(0));
3920 printer.printRegion(region,
3927 mlir::OpAsmParser &parser,
3929 mlir::ArrayAttr &handlerTypes) {
3931 auto parseCheckedCatcherRegion = [&]() -> mlir::ParseResult {
3932 handlerRegions.emplace_back(
new mlir::Region);
3934 mlir::Region &currRegion = *handlerRegions.back();
3938 if (parser.parseLParen())
3940 mlir::OpAsmParser::Argument arg;
3941 if (parser.parseArgument(arg,
true))
3943 regionArgs.push_back(arg);
3944 if (parser.parseRParen())
3947 mlir::SMLoc regionLoc = parser.getCurrentLocation();
3948 if (parser.parseRegion(currRegion, regionArgs)) {
3949 handlerRegions.clear();
3953 if (currRegion.empty())
3954 return parser.emitError(regionLoc,
"handler region shall not be empty");
3956 if (!(currRegion.back().mightHaveTerminator() &&
3957 currRegion.back().getTerminator()))
3958 return parser.emitError(
3959 regionLoc,
"blocks are expected to be explicitly terminated");
3964 bool hasCatchAll =
false;
3966 while (parser.parseOptionalKeyword(
"catch").succeeded()) {
3967 bool hasLSquare = parser.parseOptionalLSquare().succeeded();
3969 llvm::StringRef attrStr;
3970 if (parser.parseOptionalKeyword(&attrStr, {
"all",
"type"}).failed())
3971 return parser.emitError(parser.getCurrentLocation(),
3972 "expected 'all' or 'type' keyword");
3974 bool isCatchAll = attrStr ==
"all";
3977 return parser.emitError(parser.getCurrentLocation(),
3978 "can't have more than one catch all");
3982 mlir::Attribute exceptionRTTIAttr;
3983 if (!isCatchAll && parser.parseAttribute(exceptionRTTIAttr).failed())
3984 return parser.emitError(parser.getCurrentLocation(),
3985 "expected valid RTTI info attribute");
3987 catcherAttrs.push_back(isCatchAll
3988 ? cir::CatchAllAttr::get(parser.getContext())
3989 : exceptionRTTIAttr);
3991 if (hasLSquare && isCatchAll)
3992 return parser.emitError(parser.getCurrentLocation(),
3993 "catch all dosen't need RTTI info attribute");
3995 if (hasLSquare && parser.parseRSquare().failed())
3996 return parser.emitError(parser.getCurrentLocation(),
3997 "expected `]` after RTTI info attribute");
3999 if (parseCheckedCatcherRegion().failed())
4000 return mlir::failure();
4003 if (parser.parseOptionalKeyword(
"unwind").succeeded()) {
4005 return parser.emitError(parser.getCurrentLocation(),
4006 "unwind can't be used with catch all");
4008 catcherAttrs.push_back(cir::UnwindAttr::get(parser.getContext()));
4009 if (parseCheckedCatcherRegion().failed())
4010 return mlir::failure();
4013 handlerTypes = parser.getBuilder().getArrayAttr(catcherAttrs);
4014 return mlir::success();
4022cir::EhTypeIdOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
4023 Operation *op = symbolTable.lookupNearestSymbolFrom(*
this, getTypeSymAttr());
4024 if (!isa_and_nonnull<GlobalOp>(op))
4025 return emitOpError(
"'")
4026 << getTypeSym() <<
"' does not reference a valid cir.global";
4036 SmallVectorImpl<Block *> &catchDestinations,
4037 Block *&defaultDestination,
4038 mlir::UnitAttr &defaultIsCatchAll) {
4040 if (parser.parseLSquare())
4044 bool hasCatchAll =
false;
4045 bool hasUnwind =
false;
4048 auto parseHandler = [&]() -> ParseResult {
4050 if (succeeded(parser.parseOptionalKeyword(
"catch_all"))) {
4052 return parser.emitError(parser.getCurrentLocation(),
4053 "duplicate 'catch_all' handler");
4055 return parser.emitError(parser.getCurrentLocation(),
4056 "cannot have both 'catch_all' and 'unwind'");
4059 if (parser.parseColon().failed())
4062 if (parser.parseSuccessor(defaultDestination).failed())
4068 if (succeeded(parser.parseOptionalKeyword(
"unwind"))) {
4070 return parser.emitError(parser.getCurrentLocation(),
4071 "duplicate 'unwind' handler");
4073 return parser.emitError(parser.getCurrentLocation(),
4074 "cannot have both 'catch_all' and 'unwind'");
4077 if (parser.parseColon().failed())
4080 if (parser.parseSuccessor(defaultDestination).failed())
4088 if (parser.parseKeyword(
"catch").failed())
4091 if (parser.parseLParen().failed())
4094 mlir::Attribute catchTypeAttr;
4095 if (parser.parseAttribute(catchTypeAttr).failed())
4097 handlerTypes.push_back(catchTypeAttr);
4099 if (parser.parseRParen().failed())
4102 if (parser.parseColon().failed())
4106 if (parser.parseSuccessor(dest).failed())
4108 catchDestinations.push_back(dest);
4112 if (parser.parseCommaSeparatedList(parseHandler).failed())
4115 if (parser.parseRSquare().failed())
4119 if (!hasCatchAll && !hasUnwind)
4120 return parser.emitError(parser.getCurrentLocation(),
4121 "must have either 'catch_all' or 'unwind' handler");
4124 if (!handlerTypes.empty())
4125 catchTypes = parser.getBuilder().getArrayAttr(handlerTypes);
4128 defaultIsCatchAll = parser.getBuilder().getUnitAttr();
4134 mlir::ArrayAttr catchTypes,
4135 SuccessorRange catchDestinations,
4136 Block *defaultDestination,
4137 mlir::UnitAttr defaultIsCatchAll) {
4145 llvm::zip(catchTypes, catchDestinations),
4148 p.printAttribute(std::get<0>(i));
4150 p.printSuccessor(std::get<1>(i));
4162 if (defaultIsCatchAll)
4163 p <<
" catch_all : ";
4166 p.printSuccessor(defaultDestination);
4176#define GET_OP_CLASSES
4177#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)
void printVisibilityAttr(OpAsmPrinter &printer, cir::VisibilityAttr &visibility)
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)
void parseVisibilityAttr(OpAsmParser &parser, cir::VisibilityAttr &visibility)
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 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',...
const half4 dst(half4 Src0, half4 Src1)
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
static bool memberFuncPtrCast()
static bool opCallCallConv()
static bool opScopeCleanupRegion()
static bool supportIFuncAttr()