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 return AliasResult::NoAlias;
88void cir::CIRDialect::initialize() {
93#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
95 addInterfaces<CIROpAsmDialectInterface>();
98Operation *cir::CIRDialect::materializeConstant(mlir::OpBuilder &builder,
99 mlir::Attribute value,
101 mlir::Location loc) {
102 return cir::ConstantOp::create(builder, loc, type,
103 mlir::cast<mlir::TypedAttr>(value));
115 for (
auto en : llvm::enumerate(keywords)) {
116 if (succeeded(parser.parseOptionalKeyword(en.value())))
123template <
typename Ty>
struct EnumTraits {};
125#define REGISTER_ENUM_TYPE(Ty) \
126 template <> struct EnumTraits<cir::Ty> { \
127 static llvm::StringRef stringify(cir::Ty value) { \
128 return stringify##Ty(value); \
130 static unsigned getMaxEnumVal() { return cir::getMaxEnumValFor##Ty(); } \
141template <
typename EnumTy,
typename RetTy = EnumTy>
144 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
145 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
149 return static_cast<RetTy
>(defaultValue);
150 return static_cast<RetTy
>(index);
154template <
typename EnumTy,
typename RetTy = EnumTy>
157 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
158 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
163 result =
static_cast<RetTy
>(index);
171 Location eLoc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
172 OpBuilder builder(parser.getBuilder().getContext());
177 builder.createBlock(®ion);
179 Block &block = region.back();
181 if (!block.empty() && block.back().hasTrait<OpTrait::IsTerminator>())
185 if (!region.hasOneBlock())
186 return parser.emitError(errLoc,
187 "multi-block region must not omit terminator");
190 builder.setInsertionPointToEnd(&block);
191 cir::YieldOp::create(builder, eLoc);
197 const auto singleNonEmptyBlock = r.hasOneBlock() && !r.back().empty();
198 const auto yieldsNothing = [&r]() {
199 auto y = dyn_cast<cir::YieldOp>(r.back().getTerminator());
200 return y && y.getArgs().empty();
202 return singleNonEmptyBlock && yieldsNothing();
206 cir::VisibilityAttr &visibility) {
207 switch (visibility.getValue()) {
208 case cir::VisibilityKind::Hidden:
211 case cir::VisibilityKind::Protected:
212 printer <<
"protected";
214 case cir::VisibilityKind::Default:
220 cir::VisibilityKind visibilityKind =
222 visibility = cir::VisibilityAttr::get(parser.getContext(), visibilityKind);
230 cir::InlineKindAttr &inlineKindAttr) {
232 static constexpr llvm::StringRef keywords[] = {
"no_inline",
"always_inline",
236 llvm::StringRef keyword;
237 if (parser.parseOptionalKeyword(&keyword, keywords).failed()) {
243 auto inlineKindResult = ::cir::symbolizeEnum<::cir::InlineKind>(keyword);
244 if (!inlineKindResult) {
245 return parser.emitError(parser.getCurrentLocation(),
"expected one of [")
247 <<
"] for inlineKind, got: " << keyword;
251 ::cir::InlineKindAttr::get(parser.getContext(), *inlineKindResult);
256 if (inlineKindAttr) {
257 p <<
" " << stringifyInlineKind(inlineKindAttr.getValue());
265 mlir::Region ®ion) {
266 auto regionLoc = parser.getCurrentLocation();
267 if (parser.parseRegion(region))
276 mlir::Region ®ion) {
277 printer.printRegion(region,
286void cir::AllocaOp::build(mlir::OpBuilder &odsBuilder,
287 mlir::OperationState &odsState, mlir::Type addr,
288 mlir::Type allocaType, llvm::StringRef name,
289 mlir::IntegerAttr alignment) {
290 odsState.addAttribute(getAllocaTypeAttrName(odsState.name),
291 mlir::TypeAttr::get(allocaType));
292 odsState.addAttribute(getNameAttrName(odsState.name),
293 odsBuilder.getStringAttr(name));
295 odsState.addAttribute(getAlignmentAttrName(odsState.name), alignment);
297 odsState.addTypes(addr);
304LogicalResult cir::BreakOp::verify() {
305 if (!getOperation()->getParentOfType<LoopOpInterface>() &&
306 !getOperation()->getParentOfType<SwitchOp>())
307 return emitOpError(
"must be within a loop");
319void cir::ConditionOp::getSuccessorRegions(
325 if (
auto loopOp = dyn_cast<LoopOpInterface>(getOperation()->getParentOp())) {
326 regions.emplace_back(&loopOp.getBody());
327 regions.push_back(RegionSuccessor::parent());
331 auto await = cast<AwaitOp>(getOperation()->getParentOp());
332 regions.emplace_back(&await.getResume());
333 regions.emplace_back(&await.getSuspend());
337cir::ConditionOp::getMutableSuccessorOperands(RegionSuccessor point) {
339 return MutableOperandRange(getOperation(), 0, 0);
343cir::ResumeOp::getMutableSuccessorOperands(RegionSuccessor point) {
345 return MutableOperandRange(getOperation(), 0, 0);
348LogicalResult cir::ConditionOp::verify() {
349 if (!isa<LoopOpInterface, AwaitOp>(getOperation()->getParentOp()))
350 return emitOpError(
"condition must be within a conditional region");
359 mlir::Attribute attrType) {
360 if (isa<cir::ConstPtrAttr>(attrType)) {
361 if (!mlir::isa<cir::PointerType>(opType))
362 return op->emitOpError(
363 "pointer constant initializing a non-pointer type");
367 if (isa<cir::DataMemberAttr, cir::MethodAttr>(attrType)) {
373 if (isa<cir::ZeroAttr>(attrType)) {
374 if (isa<cir::RecordType, cir::ArrayType, cir::VectorType, cir::ComplexType>(
377 return op->emitOpError(
378 "zero expects struct, array, vector, or complex type");
381 if (mlir::isa<cir::UndefAttr>(attrType)) {
382 if (!mlir::isa<cir::VoidType>(opType))
384 return op->emitOpError(
"undef expects non-void type");
387 if (mlir::isa<cir::BoolAttr>(attrType)) {
388 if (!mlir::isa<cir::BoolType>(opType))
389 return op->emitOpError(
"result type (")
390 << opType <<
") must be '!cir.bool' for '" << attrType <<
"'";
394 if (mlir::isa<cir::IntAttr, cir::FPAttr>(attrType)) {
395 auto at = cast<TypedAttr>(attrType);
396 if (at.getType() != opType) {
397 return op->emitOpError(
"result type (")
398 << opType <<
") does not match value type (" << at.getType()
404 if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
405 cir::ConstComplexAttr, cir::ConstRecordAttr,
406 cir::GlobalViewAttr, cir::PoisonAttr, cir::TypeInfoAttr,
407 cir::VTableAttr>(attrType))
410 assert(isa<TypedAttr>(attrType) &&
"What else could we be looking at here?");
411 return op->emitOpError(
"global with type ")
412 << cast<TypedAttr>(attrType).getType() <<
" not yet supported";
415LogicalResult cir::ConstantOp::verify() {
422OpFoldResult cir::ConstantOp::fold(FoldAdaptor ) {
430LogicalResult cir::ContinueOp::verify() {
431 if (!getOperation()->getParentOfType<LoopOpInterface>())
432 return emitOpError(
"must be within a loop");
440LogicalResult cir::CastOp::verify() {
441 mlir::Type resType =
getType();
442 mlir::Type srcType = getSrc().getType();
446 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
447 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
448 if (srcPtrTy && resPtrTy && (
getKind() != cir::CastKind::address_space))
449 if (srcPtrTy.getAddrSpace() != resPtrTy.getAddrSpace()) {
450 return emitOpError() <<
"result type address space does not match the "
451 "address space of the operand";
454 if (mlir::isa<cir::VectorType>(srcType) &&
455 mlir::isa<cir::VectorType>(resType)) {
458 srcType = mlir::dyn_cast<cir::VectorType>(srcType).getElementType();
459 resType = mlir::dyn_cast<cir::VectorType>(resType).getElementType();
463 case cir::CastKind::int_to_bool: {
464 if (!mlir::isa<cir::BoolType>(resType))
465 return emitOpError() <<
"requires !cir.bool type for result";
466 if (!mlir::isa<cir::IntType>(srcType))
467 return emitOpError() <<
"requires !cir.int type for source";
470 case cir::CastKind::ptr_to_bool: {
471 if (!mlir::isa<cir::BoolType>(resType))
472 return emitOpError() <<
"requires !cir.bool type for result";
473 if (!mlir::isa<cir::PointerType>(srcType))
474 return emitOpError() <<
"requires !cir.ptr type for source";
477 case cir::CastKind::integral: {
478 if (!mlir::isa<cir::IntType>(resType))
479 return emitOpError() <<
"requires !cir.int type for result";
480 if (!mlir::isa<cir::IntType>(srcType))
481 return emitOpError() <<
"requires !cir.int type for source";
484 case cir::CastKind::array_to_ptrdecay: {
485 const auto arrayPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
486 const auto flatPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
487 if (!arrayPtrTy || !flatPtrTy)
488 return emitOpError() <<
"requires !cir.ptr type for source and result";
493 case cir::CastKind::bitcast: {
495 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
496 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
498 if (srcPtrTy && resPtrTy) {
504 case cir::CastKind::floating: {
505 if (!mlir::isa<cir::FPTypeInterface>(srcType) ||
506 !mlir::isa<cir::FPTypeInterface>(resType))
507 return emitOpError() <<
"requires !cir.float type for source and result";
510 case cir::CastKind::float_to_int: {
511 if (!mlir::isa<cir::FPTypeInterface>(srcType))
512 return emitOpError() <<
"requires !cir.float type for source";
513 if (!mlir::dyn_cast<cir::IntType>(resType))
514 return emitOpError() <<
"requires !cir.int type for result";
517 case cir::CastKind::int_to_ptr: {
518 if (!mlir::dyn_cast<cir::IntType>(srcType))
519 return emitOpError() <<
"requires !cir.int type for source";
520 if (!mlir::dyn_cast<cir::PointerType>(resType))
521 return emitOpError() <<
"requires !cir.ptr type for result";
524 case cir::CastKind::ptr_to_int: {
525 if (!mlir::dyn_cast<cir::PointerType>(srcType))
526 return emitOpError() <<
"requires !cir.ptr type for source";
527 if (!mlir::dyn_cast<cir::IntType>(resType))
528 return emitOpError() <<
"requires !cir.int type for result";
531 case cir::CastKind::float_to_bool: {
532 if (!mlir::isa<cir::FPTypeInterface>(srcType))
533 return emitOpError() <<
"requires !cir.float type for source";
534 if (!mlir::isa<cir::BoolType>(resType))
535 return emitOpError() <<
"requires !cir.bool type for result";
538 case cir::CastKind::bool_to_int: {
539 if (!mlir::isa<cir::BoolType>(srcType))
540 return emitOpError() <<
"requires !cir.bool type for source";
541 if (!mlir::isa<cir::IntType>(resType))
542 return emitOpError() <<
"requires !cir.int type for result";
545 case cir::CastKind::int_to_float: {
546 if (!mlir::isa<cir::IntType>(srcType))
547 return emitOpError() <<
"requires !cir.int type for source";
548 if (!mlir::isa<cir::FPTypeInterface>(resType))
549 return emitOpError() <<
"requires !cir.float type for result";
552 case cir::CastKind::bool_to_float: {
553 if (!mlir::isa<cir::BoolType>(srcType))
554 return emitOpError() <<
"requires !cir.bool type for source";
555 if (!mlir::isa<cir::FPTypeInterface>(resType))
556 return emitOpError() <<
"requires !cir.float type for result";
559 case cir::CastKind::address_space: {
560 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
561 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
562 if (!srcPtrTy || !resPtrTy)
563 return emitOpError() <<
"requires !cir.ptr type for source and result";
564 if (srcPtrTy.getPointee() != resPtrTy.getPointee())
565 return emitOpError() <<
"requires two types differ in addrspace only";
568 case cir::CastKind::float_to_complex: {
569 if (!mlir::isa<cir::FPTypeInterface>(srcType))
570 return emitOpError() <<
"requires !cir.float type for source";
571 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
573 return emitOpError() <<
"requires !cir.complex type for result";
574 if (srcType != resComplexTy.getElementType())
575 return emitOpError() <<
"requires source type match result element type";
578 case cir::CastKind::int_to_complex: {
579 if (!mlir::isa<cir::IntType>(srcType))
580 return emitOpError() <<
"requires !cir.int type for source";
581 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
583 return emitOpError() <<
"requires !cir.complex type for result";
584 if (srcType != resComplexTy.getElementType())
585 return emitOpError() <<
"requires source type match result element type";
588 case cir::CastKind::float_complex_to_real: {
589 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
591 return emitOpError() <<
"requires !cir.complex type for source";
592 if (!mlir::isa<cir::FPTypeInterface>(resType))
593 return emitOpError() <<
"requires !cir.float type for result";
594 if (srcComplexTy.getElementType() != resType)
595 return emitOpError() <<
"requires source element type match result type";
598 case cir::CastKind::int_complex_to_real: {
599 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
601 return emitOpError() <<
"requires !cir.complex type for source";
602 if (!mlir::isa<cir::IntType>(resType))
603 return emitOpError() <<
"requires !cir.int type for result";
604 if (srcComplexTy.getElementType() != resType)
605 return emitOpError() <<
"requires source element type match result type";
608 case cir::CastKind::float_complex_to_bool: {
609 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
610 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
612 <<
"requires floating point !cir.complex type for source";
613 if (!mlir::isa<cir::BoolType>(resType))
614 return emitOpError() <<
"requires !cir.bool type for result";
617 case cir::CastKind::int_complex_to_bool: {
618 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
619 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
621 <<
"requires floating point !cir.complex type for source";
622 if (!mlir::isa<cir::BoolType>(resType))
623 return emitOpError() <<
"requires !cir.bool type for result";
626 case cir::CastKind::float_complex: {
627 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
628 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
630 <<
"requires floating point !cir.complex type for source";
631 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
632 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
634 <<
"requires floating point !cir.complex type for result";
637 case cir::CastKind::float_complex_to_int_complex: {
638 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
639 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
641 <<
"requires floating point !cir.complex type for source";
642 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
643 if (!resComplexTy || !resComplexTy.isIntegerComplex())
644 return emitOpError() <<
"requires integer !cir.complex type for result";
647 case cir::CastKind::int_complex: {
648 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
649 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
650 return emitOpError() <<
"requires integer !cir.complex type for source";
651 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
652 if (!resComplexTy || !resComplexTy.isIntegerComplex())
653 return emitOpError() <<
"requires integer !cir.complex type for result";
656 case cir::CastKind::int_complex_to_float_complex: {
657 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
658 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
659 return emitOpError() <<
"requires integer !cir.complex type for source";
660 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
661 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
663 <<
"requires floating point !cir.complex type for result";
666 case cir::CastKind::member_ptr_to_bool: {
667 if (!mlir::isa<cir::DataMemberType, cir::MethodType>(srcType))
669 <<
"requires !cir.data_member or !cir.method type for source";
670 if (!mlir::isa<cir::BoolType>(resType))
671 return emitOpError() <<
"requires !cir.bool type for result";
675 llvm_unreachable(
"Unknown CastOp kind?");
679 auto kind = op.getKind();
680 return kind == cir::CastKind::bool_to_int ||
681 kind == cir::CastKind::int_to_bool ||
kind == cir::CastKind::integral;
685 cir::CastOp head = op, tail = op;
691 op = head.getSrc().getDefiningOp<cir::CastOp>();
699 if (head.getKind() == cir::CastKind::bool_to_int &&
700 tail.getKind() == cir::CastKind::int_to_bool)
701 return head.getSrc();
706 if (head.getKind() == cir::CastKind::int_to_bool &&
707 tail.getKind() == cir::CastKind::int_to_bool)
708 return head.getResult();
713OpFoldResult cir::CastOp::fold(FoldAdaptor adaptor) {
714 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getSrc())) {
716 return cir::PoisonAttr::get(getContext(),
getType());
721 case cir::CastKind::integral: {
723 auto foldOrder = getSrc().getDefiningOp()->fold(foldResults);
724 if (foldOrder.succeeded() && mlir::isa<mlir::Attribute>(foldResults[0]))
725 return mlir::cast<mlir::Attribute>(foldResults[0]);
728 case cir::CastKind::bitcast:
729 case cir::CastKind::address_space:
730 case cir::CastKind::float_complex:
731 case cir::CastKind::int_complex: {
745 if (
auto srcConst = getSrc().getDefiningOp<cir::ConstantOp>()) {
747 case cir::CastKind::integral: {
748 mlir::Type srcTy = getSrc().getType();
750 assert(mlir::isa<cir::VectorType>(srcTy) ==
751 mlir::isa<cir::VectorType>(
getType()));
752 if (mlir::isa<cir::VectorType>(srcTy))
755 auto srcIntTy = mlir::cast<cir::IntType>(srcTy);
756 auto dstIntTy = mlir::cast<cir::IntType>(
getType());
759 ? srcConst.getIntValue().sextOrTrunc(dstIntTy.getWidth())
760 : srcConst.getIntValue().zextOrTrunc(dstIntTy.getWidth());
761 return cir::IntAttr::get(dstIntTy, newVal);
774mlir::OperandRange cir::CallOp::getArgOperands() {
776 return getArgs().drop_front(1);
780mlir::MutableOperandRange cir::CallOp::getArgOperandsMutable() {
781 mlir::MutableOperandRange args = getArgsMutable();
783 return args.slice(1, args.size() - 1);
787mlir::Value cir::CallOp::getIndirectCall() {
788 assert(isIndirect());
789 return getOperand(0);
793Value cir::CallOp::getArgOperand(
unsigned i) {
796 return getOperand(i);
800unsigned cir::CallOp::getNumArgOperands() {
802 return this->getOperation()->getNumOperands() - 1;
803 return this->getOperation()->getNumOperands();
806static mlir::ParseResult
808 mlir::OperationState &result) {
809 mlir::Block *normalDestSuccessor;
810 if (parser.parseSuccessor(normalDestSuccessor))
811 return mlir::failure();
813 if (parser.parseComma())
814 return mlir::failure();
816 mlir::Block *unwindDestSuccessor;
817 if (parser.parseSuccessor(unwindDestSuccessor))
818 return mlir::failure();
820 result.addSuccessors(normalDestSuccessor);
821 result.addSuccessors(unwindDestSuccessor);
822 return mlir::success();
826 mlir::OperationState &result,
827 bool hasDestinationBlocks =
false) {
830 mlir::FlatSymbolRefAttr calleeAttr;
834 .parseOptionalAttribute(calleeAttr, CIRDialect::getCalleeAttrName(),
837 OpAsmParser::UnresolvedOperand indirectVal;
839 if (parser.parseOperand(indirectVal).failed())
841 ops.push_back(indirectVal);
844 if (parser.parseLParen())
845 return mlir::failure();
847 opsLoc = parser.getCurrentLocation();
848 if (parser.parseOperandList(ops))
849 return mlir::failure();
850 if (parser.parseRParen())
851 return mlir::failure();
853 if (hasDestinationBlocks &&
855 return ::mlir::failure();
858 if (parser.parseOptionalKeyword(
"nothrow").succeeded())
859 result.addAttribute(CIRDialect::getNoThrowAttrName(),
860 mlir::UnitAttr::get(parser.getContext()));
862 if (parser.parseOptionalKeyword(
"side_effect").succeeded()) {
863 if (parser.parseLParen().failed())
865 cir::SideEffect sideEffect;
868 if (parser.parseRParen().failed())
870 auto attr = cir::SideEffectAttr::get(parser.getContext(), sideEffect);
871 result.addAttribute(CIRDialect::getSideEffectAttrName(), attr);
874 if (parser.parseOptionalAttrDict(result.attributes))
875 return ::mlir::failure();
877 if (parser.parseColon())
878 return ::mlir::failure();
884 if (call_interface_impl::parseFunctionSignature(parser, argTypes, argAttrs,
885 resultTypes, resultAttrs))
886 return mlir::failure();
888 if (resultTypes.size() > 1 || resultAttrs.size() > 1)
889 return parser.emitError(
890 parser.getCurrentLocation(),
891 "functions with multiple return types are not supported");
893 result.addTypes(resultTypes);
895 if (parser.resolveOperands(ops, argTypes, opsLoc, result.operands))
896 return mlir::failure();
898 if (!resultAttrs.empty() && resultAttrs[0])
900 CIRDialect::getResAttrsAttrName(),
901 mlir::ArrayAttr::get(parser.getContext(), {resultAttrs[0]}));
906 bool argAttrsEmpty =
true;
908 llvm::transform(argAttrs, std::back_inserter(convertedArgAttrs),
909 [&](DictionaryAttr da) -> mlir::Attribute {
911 argAttrsEmpty =
false;
915 if (!argAttrsEmpty) {
920 argAttrsRef = argAttrsRef.drop_front();
922 result.addAttribute(CIRDialect::getArgAttrsAttrName(),
923 mlir::ArrayAttr::get(parser.getContext(), argAttrsRef));
926 return mlir::success();
931 mlir::Value indirectCallee, mlir::OpAsmPrinter &printer,
932 bool isNothrow, cir::SideEffect sideEffect, ArrayAttr argAttrs,
933 ArrayAttr resAttrs, mlir::Block *normalDest =
nullptr,
934 mlir::Block *unwindDest =
nullptr) {
937 auto callLikeOp = mlir::cast<cir::CIRCallOpInterface>(op);
938 auto ops = callLikeOp.getArgOperands();
942 printer.printAttributeWithoutType(calleeSym);
945 assert(indirectCallee);
946 printer << indirectCallee;
949 printer <<
"(" << ops <<
")";
952 assert(unwindDest &&
"expected two successors");
953 auto tryCall = cast<cir::TryCallOp>(op);
954 printer <<
' ' << tryCall.getNormalDest();
957 printer << tryCall.getUnwindDest();
961 printer <<
" nothrow";
963 if (sideEffect != cir::SideEffect::All) {
964 printer <<
" side_effect(";
965 printer << stringifySideEffect(sideEffect);
970 CIRDialect::getCalleeAttrName(),
971 CIRDialect::getNoThrowAttrName(),
972 CIRDialect::getSideEffectAttrName(),
973 CIRDialect::getOperandSegmentSizesAttrName(),
974 llvm::StringRef(
"res_attrs"),
975 llvm::StringRef(
"arg_attrs")};
976 printer.printOptionalAttrDict(op->getAttrs(), elidedAttrs);
978 if (calleeSym || !argAttrs) {
979 call_interface_impl::printFunctionSignature(
980 printer, op->getOperands().getTypes(), argAttrs,
981 false, op->getResultTypes(), resAttrs);
989 shimmedArgAttrs.push_back(mlir::DictionaryAttr::get(op->getContext(), {}));
990 shimmedArgAttrs.append(argAttrs.begin(), argAttrs.end());
991 call_interface_impl::printFunctionSignature(
992 printer, op->getOperands().getTypes(),
993 mlir::ArrayAttr::get(op->getContext(), shimmedArgAttrs),
994 false, op->getResultTypes(), resAttrs);
998mlir::ParseResult cir::CallOp::parse(mlir::OpAsmParser &parser,
999 mlir::OperationState &result) {
1003void cir::CallOp::print(mlir::OpAsmPrinter &p) {
1004 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
1005 cir::SideEffect sideEffect = getSideEffect();
1006 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
1007 sideEffect, getArgAttrsAttr(), getResAttrsAttr());
1012 SymbolTableCollection &symbolTable) {
1014 op->getAttrOfType<FlatSymbolRefAttr>(CIRDialect::getCalleeAttrName());
1017 return mlir::success();
1020 auto fn = symbolTable.lookupNearestSymbolFrom<cir::FuncOp>(op, fnAttr);
1022 return op->emitOpError() <<
"'" << fnAttr.getValue()
1023 <<
"' does not reference a valid function";
1025 auto callIf = dyn_cast<cir::CIRCallOpInterface>(op);
1026 assert(callIf &&
"expected CIR call interface to be always available");
1030 auto fnType = fn.getFunctionType();
1031 if (!fn.getNoProto()) {
1032 unsigned numCallOperands = callIf.getNumArgOperands();
1033 unsigned numFnOpOperands = fnType.getNumInputs();
1035 if (!fnType.isVarArg() && numCallOperands != numFnOpOperands)
1036 return op->emitOpError(
"incorrect number of operands for callee");
1037 if (fnType.isVarArg() && numCallOperands < numFnOpOperands)
1038 return op->emitOpError(
"too few operands for callee");
1040 for (
unsigned i = 0, e = numFnOpOperands; i != e; ++i)
1041 if (callIf.getArgOperand(i).getType() != fnType.getInput(i))
1042 return op->emitOpError(
"operand type mismatch: expected operand type ")
1043 << fnType.getInput(i) <<
", but provided "
1044 << op->getOperand(i).getType() <<
" for operand number " << i;
1050 if (fnType.hasVoidReturn() && op->getNumResults() != 0)
1051 return op->emitOpError(
"callee returns void but call has results");
1054 if (!fnType.hasVoidReturn() && op->getNumResults() != 1)
1055 return op->emitOpError(
"incorrect number of results for callee");
1058 if (!fnType.hasVoidReturn() &&
1059 op->getResultTypes().front() != fnType.getReturnType()) {
1060 return op->emitOpError(
"result type mismatch: expected ")
1061 << fnType.getReturnType() <<
", but provided "
1062 << op->getResult(0).getType();
1065 return mlir::success();
1069cir::CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1077mlir::OperandRange cir::TryCallOp::getArgOperands() {
1079 return getArgs().drop_front(1);
1083mlir::MutableOperandRange cir::TryCallOp::getArgOperandsMutable() {
1084 mlir::MutableOperandRange args = getArgsMutable();
1086 return args.slice(1, args.size() - 1);
1090mlir::Value cir::TryCallOp::getIndirectCall() {
1091 assert(isIndirect());
1092 return getOperand(0);
1096Value cir::TryCallOp::getArgOperand(
unsigned i) {
1099 return getOperand(i);
1103unsigned cir::TryCallOp::getNumArgOperands() {
1105 return this->getOperation()->getNumOperands() - 1;
1106 return this->getOperation()->getNumOperands();
1110cir::TryCallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1114mlir::ParseResult cir::TryCallOp::parse(mlir::OpAsmParser &parser,
1115 mlir::OperationState &result) {
1119void cir::TryCallOp::print(::mlir::OpAsmPrinter &p) {
1120 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
1121 cir::SideEffect sideEffect = getSideEffect();
1122 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
1123 sideEffect, getArgAttrsAttr(), getResAttrsAttr(),
1124 getNormalDest(), getUnwindDest());
1132 cir::FuncOp function) {
1134 if (op.getNumOperands() > 1)
1135 return op.emitOpError() <<
"expects at most 1 return operand";
1138 auto expectedTy = function.getFunctionType().getReturnType();
1140 (op.getNumOperands() == 0 ? cir::VoidType::get(op.getContext())
1141 : op.getOperand(0).getType());
1142 if (actualTy != expectedTy)
1143 return op.emitOpError() <<
"returns " << actualTy
1144 <<
" but enclosing function returns " << expectedTy;
1146 return mlir::success();
1149mlir::LogicalResult cir::ReturnOp::verify() {
1152 auto *fnOp = getOperation()->getParentOp();
1153 while (!isa<cir::FuncOp>(fnOp))
1154 fnOp = fnOp->getParentOp();
1167ParseResult cir::IfOp::parse(OpAsmParser &parser, OperationState &result) {
1169 result.regions.reserve(2);
1170 Region *thenRegion = result.addRegion();
1171 Region *elseRegion = result.addRegion();
1173 mlir::Builder &builder = parser.getBuilder();
1174 OpAsmParser::UnresolvedOperand cond;
1175 Type boolType = cir::BoolType::get(builder.getContext());
1177 if (parser.parseOperand(cond) ||
1178 parser.resolveOperand(cond, boolType, result.operands))
1182 mlir::SMLoc parseThenLoc = parser.getCurrentLocation();
1183 if (parser.parseRegion(*thenRegion, {}, {}))
1190 if (!parser.parseOptionalKeyword(
"else")) {
1191 mlir::SMLoc parseElseLoc = parser.getCurrentLocation();
1192 if (parser.parseRegion(*elseRegion, {}, {}))
1199 if (parser.parseOptionalAttrDict(result.attributes))
1204void cir::IfOp::print(OpAsmPrinter &p) {
1205 p <<
" " << getCondition() <<
" ";
1206 mlir::Region &thenRegion = this->getThenRegion();
1207 p.printRegion(thenRegion,
1212 mlir::Region &elseRegion = this->getElseRegion();
1213 if (!elseRegion.empty()) {
1215 p.printRegion(elseRegion,
1220 p.printOptionalAttrDict(getOperation()->getAttrs());
1226 cir::YieldOp::create(builder, loc);
1234void cir::IfOp::getSuccessorRegions(mlir::RegionBranchPoint point,
1235 SmallVectorImpl<RegionSuccessor> ®ions) {
1237 if (!point.isParent()) {
1238 regions.push_back(RegionSuccessor::parent());
1243 Region *elseRegion = &this->getElseRegion();
1244 if (elseRegion->empty())
1245 elseRegion =
nullptr;
1248 regions.push_back(RegionSuccessor(&getThenRegion()));
1251 regions.push_back(RegionSuccessor(elseRegion));
1256mlir::ValueRange cir::IfOp::getSuccessorInputs(RegionSuccessor successor) {
1257 return successor.isParent() ? ValueRange(getOperation()->getResults())
1261void cir::IfOp::build(OpBuilder &builder, OperationState &result,
Value cond,
1264 assert(thenBuilder &&
"the builder callback for 'then' must be present");
1265 result.addOperands(cond);
1267 OpBuilder::InsertionGuard guard(builder);
1268 Region *thenRegion = result.addRegion();
1269 builder.createBlock(thenRegion);
1270 thenBuilder(builder, result.location);
1272 Region *elseRegion = result.addRegion();
1273 if (!withElseRegion)
1276 builder.createBlock(elseRegion);
1277 elseBuilder(builder, result.location);
1289void cir::ScopeOp::getSuccessorRegions(
1290 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1292 if (!point.isParent()) {
1293 regions.push_back(RegionSuccessor::parent());
1298 regions.push_back(RegionSuccessor(&getScopeRegion()));
1301mlir::ValueRange cir::ScopeOp::getSuccessorInputs(RegionSuccessor successor) {
1302 return successor.isParent() ? ValueRange(getOperation()->getResults())
1306void cir::ScopeOp::build(
1307 OpBuilder &builder, OperationState &result,
1308 function_ref<
void(OpBuilder &, Type &, Location)> scopeBuilder) {
1309 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1311 OpBuilder::InsertionGuard guard(builder);
1312 Region *scopeRegion = result.addRegion();
1313 builder.createBlock(scopeRegion);
1317 scopeBuilder(builder, yieldTy, result.location);
1320 result.addTypes(TypeRange{yieldTy});
1323void cir::ScopeOp::build(
1324 OpBuilder &builder, OperationState &result,
1325 function_ref<
void(OpBuilder &, Location)> scopeBuilder) {
1326 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1327 OpBuilder::InsertionGuard guard(builder);
1328 Region *scopeRegion = result.addRegion();
1329 builder.createBlock(scopeRegion);
1331 scopeBuilder(builder, result.location);
1334LogicalResult cir::ScopeOp::verify() {
1336 return emitOpError() <<
"cir.scope must not be empty since it should "
1337 "include at least an implicit cir.yield ";
1340 mlir::Block &lastBlock =
getRegion().back();
1341 if (lastBlock.empty() || !lastBlock.mightHaveTerminator() ||
1342 !lastBlock.getTerminator()->hasTrait<OpTrait::IsTerminator>())
1343 return emitOpError() <<
"last block of cir.scope must be terminated";
1347LogicalResult cir::ScopeOp::fold(FoldAdaptor ,
1348 SmallVectorImpl<OpFoldResult> &results) {
1353 if (block.getOperations().size() != 1)
1356 auto yield = dyn_cast<cir::YieldOp>(block.front());
1361 if (getNumResults() != 1 || yield.getNumOperands() != 1)
1364 results.push_back(yield.getOperand(0));
1372void cir::CleanupScopeOp::getSuccessorRegions(
1373 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1374 if (!point.isParent()) {
1375 regions.push_back(RegionSuccessor::parent());
1380 regions.push_back(RegionSuccessor(&getBodyRegion()));
1381 regions.push_back(RegionSuccessor(&getCleanupRegion()));
1385cir::CleanupScopeOp::getSuccessorInputs(RegionSuccessor successor) {
1386 return ValueRange();
1389void cir::CleanupScopeOp::build(
1390 OpBuilder &builder, OperationState &result, CleanupKind cleanupKind,
1391 function_ref<
void(OpBuilder &, Location)> bodyBuilder,
1392 function_ref<
void(OpBuilder &, Location)> cleanupBuilder) {
1393 result.addAttribute(getCleanupKindAttrName(result.name),
1394 CleanupKindAttr::get(builder.getContext(), cleanupKind));
1396 OpBuilder::InsertionGuard guard(builder);
1399 Region *bodyRegion = result.addRegion();
1400 builder.createBlock(bodyRegion);
1402 bodyBuilder(builder, result.location);
1405 Region *cleanupRegion = result.addRegion();
1406 builder.createBlock(cleanupRegion);
1408 cleanupBuilder(builder, result.location);
1423LogicalResult cir::BrOp::canonicalize(BrOp op, PatternRewriter &rewriter) {
1424 Block *src = op->getBlock();
1425 Block *
dst = op.getDest();
1432 if (src->getNumSuccessors() != 1 ||
dst->getSinglePredecessor() != src)
1437 if (isa<cir::LabelOp, cir::IndirectBrOp>(
dst->front()))
1440 auto operands = op.getDestOperands();
1441 rewriter.eraseOp(op);
1442 rewriter.mergeBlocks(dst, src, operands);
1446mlir::SuccessorOperands cir::BrOp::getSuccessorOperands(
unsigned index) {
1447 assert(index == 0 &&
"invalid successor index");
1448 return mlir::SuccessorOperands(getDestOperandsMutable());
1459mlir::SuccessorOperands
1460cir::IndirectBrOp::getSuccessorOperands(
unsigned index) {
1461 assert(index < getNumSuccessors() &&
"invalid successor index");
1462 return mlir::SuccessorOperands(getSuccOperandsMutable()[index]);
1466 OpAsmParser &parser, Type &flagType,
1467 SmallVectorImpl<Block *> &succOperandBlocks,
1470 if (failed(parser.parseCommaSeparatedList(
1471 OpAsmParser::Delimiter::Square,
1473 Block *destination = nullptr;
1474 SmallVector<OpAsmParser::UnresolvedOperand> operands;
1475 SmallVector<Type> operandTypes;
1477 if (parser.parseSuccessor(destination).failed())
1480 if (succeeded(parser.parseOptionalLParen())) {
1481 if (failed(parser.parseOperandList(
1482 operands, OpAsmParser::Delimiter::None)) ||
1483 failed(parser.parseColonTypeList(operandTypes)) ||
1484 failed(parser.parseRParen()))
1487 succOperandBlocks.push_back(destination);
1488 succOperands.emplace_back(operands);
1489 succOperandsTypes.emplace_back(operandTypes);
1492 "successor blocks")))
1498 Type flagType, SuccessorRange succs,
1499 OperandRangeRange succOperands,
1500 const TypeRangeRange &succOperandsTypes) {
1503 llvm::zip(succs, succOperands),
1506 p.printSuccessorAndUseList(std::get<0>(i), std::get<1>(i));
1509 if (!succOperands.empty())
1518mlir::SuccessorOperands cir::BrCondOp::getSuccessorOperands(
unsigned index) {
1519 assert(index < getNumSuccessors() &&
"invalid successor index");
1520 return SuccessorOperands(index == 0 ? getDestOperandsTrueMutable()
1521 : getDestOperandsFalseMutable());
1525 if (IntegerAttr condAttr = dyn_cast_if_present<IntegerAttr>(operands.front()))
1526 return condAttr.getValue().isOne() ? getDestTrue() : getDestFalse();
1534void cir::CaseOp::getSuccessorRegions(
1535 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1536 if (!point.isParent()) {
1537 regions.push_back(RegionSuccessor::parent());
1540 regions.push_back(RegionSuccessor(&getCaseRegion()));
1543mlir::ValueRange cir::CaseOp::getSuccessorInputs(RegionSuccessor successor) {
1544 return successor.isParent() ? ValueRange(getOperation()->getResults())
1548void cir::CaseOp::build(OpBuilder &builder, OperationState &result,
1549 ArrayAttr value, CaseOpKind
kind,
1550 OpBuilder::InsertPoint &insertPoint) {
1551 OpBuilder::InsertionGuard guardSwitch(builder);
1552 result.addAttribute(
"value", value);
1553 result.getOrAddProperties<Properties>().
kind =
1554 cir::CaseOpKindAttr::get(builder.getContext(),
kind);
1555 Region *caseRegion = result.addRegion();
1556 builder.createBlock(caseRegion);
1558 insertPoint = builder.saveInsertionPoint();
1565void cir::SwitchOp::getSuccessorRegions(
1566 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ion) {
1567 if (!point.isParent()) {
1568 region.push_back(RegionSuccessor::parent());
1572 region.push_back(RegionSuccessor(&getBody()));
1575mlir::ValueRange cir::SwitchOp::getSuccessorInputs(RegionSuccessor successor) {
1576 return successor.isParent() ? ValueRange(getOperation()->getResults())
1580void cir::SwitchOp::build(OpBuilder &builder, OperationState &result,
1582 assert(switchBuilder &&
"the builder callback for regions must be present");
1583 OpBuilder::InsertionGuard guardSwitch(builder);
1584 Region *switchRegion = result.addRegion();
1585 builder.createBlock(switchRegion);
1586 result.addOperands({cond});
1587 switchBuilder(builder, result.location, result);
1591 walk<mlir::WalkOrder::PreOrder>([&](mlir::Operation *op) {
1593 if (isa<cir::SwitchOp>(op) && op != *
this)
1594 return WalkResult::skip();
1596 if (
auto caseOp = dyn_cast<cir::CaseOp>(op))
1597 cases.push_back(caseOp);
1599 return WalkResult::advance();
1604 collectCases(cases);
1606 if (getBody().empty())
1609 if (!isa<YieldOp>(getBody().front().back()))
1612 if (!llvm::all_of(getBody().front(),
1613 [](Operation &op) {
return isa<CaseOp, YieldOp>(op); }))
1616 return llvm::all_of(cases, [
this](CaseOp op) {
1617 return op->getParentOfType<SwitchOp>() == *
this;
1625void cir::SwitchFlatOp::build(OpBuilder &builder, OperationState &result,
1626 Value value, Block *defaultDestination,
1627 ValueRange defaultOperands,
1629 BlockRange caseDestinations,
1632 std::vector<mlir::Attribute> caseValuesAttrs;
1633 for (
const APInt &val : caseValues)
1634 caseValuesAttrs.push_back(cir::IntAttr::get(value.getType(), val));
1635 mlir::ArrayAttr attrs = ArrayAttr::get(builder.getContext(), caseValuesAttrs);
1637 build(builder, result, value, defaultOperands, caseOperands, attrs,
1638 defaultDestination, caseDestinations);
1644 OpAsmParser &parser, Type flagType, mlir::ArrayAttr &caseValues,
1645 SmallVectorImpl<Block *> &caseDestinations,
1649 if (failed(parser.parseLSquare()))
1651 if (succeeded(parser.parseOptionalRSquare()))
1655 auto parseCase = [&]() {
1657 if (failed(parser.parseInteger(value)))
1660 values.push_back(cir::IntAttr::get(flagType, value));
1665 if (parser.parseColon() || parser.parseSuccessor(destination))
1667 if (!parser.parseOptionalLParen()) {
1668 if (parser.parseOperandList(operands, OpAsmParser::Delimiter::None,
1670 parser.parseColonTypeList(operandTypes) || parser.parseRParen())
1673 caseDestinations.push_back(destination);
1674 caseOperands.emplace_back(operands);
1675 caseOperandTypes.emplace_back(operandTypes);
1678 if (failed(parser.parseCommaSeparatedList(parseCase)))
1681 caseValues = ArrayAttr::get(flagType.getContext(), values);
1683 return parser.parseRSquare();
1687 Type flagType, mlir::ArrayAttr caseValues,
1688 SuccessorRange caseDestinations,
1689 OperandRangeRange caseOperands,
1690 const TypeRangeRange &caseOperandTypes) {
1700 llvm::zip(caseValues, caseDestinations),
1703 mlir::Attribute a = std::get<0>(i);
1704 p << mlir::cast<cir::IntAttr>(a).getValue();
1706 p.printSuccessorAndUseList(std::get<1>(i), caseOperands[index++]);
1721 mlir::Attribute &valueAttr) {
1723 return parser.parseAttribute(valueAttr,
"value", attr);
1727 p.printAttribute(value);
1730mlir::LogicalResult cir::GlobalOp::verify() {
1733 if (getInitialValue().has_value()) {
1745void cir::GlobalOp::build(
1746 OpBuilder &odsBuilder, OperationState &odsState, llvm::StringRef sym_name,
1747 mlir::Type sym_type,
bool isConstant, cir::GlobalLinkageKind linkage,
1748 function_ref<
void(OpBuilder &, Location)> ctorBuilder,
1749 function_ref<
void(OpBuilder &, Location)> dtorBuilder) {
1750 odsState.addAttribute(getSymNameAttrName(odsState.name),
1751 odsBuilder.getStringAttr(sym_name));
1752 odsState.addAttribute(getSymTypeAttrName(odsState.name),
1753 mlir::TypeAttr::get(sym_type));
1755 odsState.addAttribute(getConstantAttrName(odsState.name),
1756 odsBuilder.getUnitAttr());
1758 cir::GlobalLinkageKindAttr linkageAttr =
1759 cir::GlobalLinkageKindAttr::get(odsBuilder.getContext(), linkage);
1760 odsState.addAttribute(getLinkageAttrName(odsState.name), linkageAttr);
1762 Region *ctorRegion = odsState.addRegion();
1764 odsBuilder.createBlock(ctorRegion);
1765 ctorBuilder(odsBuilder, odsState.location);
1768 Region *dtorRegion = odsState.addRegion();
1770 odsBuilder.createBlock(dtorRegion);
1771 dtorBuilder(odsBuilder, odsState.location);
1774 odsState.addAttribute(getGlobalVisibilityAttrName(odsState.name),
1775 cir::VisibilityAttr::get(odsBuilder.getContext()));
1783void cir::GlobalOp::getSuccessorRegions(
1784 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1786 if (!point.isParent()) {
1787 regions.push_back(RegionSuccessor::parent());
1792 Region *ctorRegion = &this->getCtorRegion();
1793 if (ctorRegion->empty())
1794 ctorRegion =
nullptr;
1797 Region *dtorRegion = &this->getDtorRegion();
1798 if (dtorRegion->empty())
1799 dtorRegion =
nullptr;
1803 regions.push_back(RegionSuccessor(ctorRegion));
1805 regions.push_back(RegionSuccessor(dtorRegion));
1808mlir::ValueRange cir::GlobalOp::getSuccessorInputs(RegionSuccessor successor) {
1809 return successor.isParent() ? ValueRange(getOperation()->getResults())
1814 TypeAttr type, Attribute initAttr,
1815 mlir::Region &ctorRegion,
1816 mlir::Region &dtorRegion) {
1817 auto printType = [&]() { p <<
": " << type; };
1818 if (!op.isDeclaration()) {
1820 if (!ctorRegion.empty()) {
1824 p.printRegion(ctorRegion,
1833 if (!dtorRegion.empty()) {
1835 p.printRegion(dtorRegion,
1846 Attribute &initialValueAttr,
1847 mlir::Region &ctorRegion,
1848 mlir::Region &dtorRegion) {
1850 if (parser.parseOptionalEqual().failed()) {
1853 if (parser.parseColonType(opTy))
1858 if (!parser.parseOptionalKeyword(
"ctor")) {
1859 if (parser.parseColonType(opTy))
1861 auto parseLoc = parser.getCurrentLocation();
1862 if (parser.parseRegion(ctorRegion, {}, {}))
1873 assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
1874 "Non-typed attrs shouldn't appear here.");
1875 auto typedAttr = mlir::cast<mlir::TypedAttr>(initialValueAttr);
1876 opTy = typedAttr.getType();
1881 if (!parser.parseOptionalKeyword(
"dtor")) {
1882 auto parseLoc = parser.getCurrentLocation();
1883 if (parser.parseRegion(dtorRegion, {}, {}))
1890 typeAttr = TypeAttr::get(opTy);
1899cir::GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1902 mlir::Operation *op =
1903 symbolTable.lookupNearestSymbolFrom(*
this, getNameAttr());
1904 if (op ==
nullptr || !(isa<GlobalOp>(op) || isa<FuncOp>(op)))
1905 return emitOpError(
"'")
1907 <<
"' does not reference a valid cir.global or cir.func";
1910 if (
auto g = dyn_cast<GlobalOp>(op)) {
1911 symTy = g.getSymType();
1915 if (getTls() && !g.getTlsModel())
1916 return emitOpError(
"access to global not marked thread local");
1921 bool getGlobalIsStaticLocal = getStaticLocal();
1922 bool globalIsStaticLocal = g.getStaticLocalGuard().has_value();
1923 if (getGlobalIsStaticLocal != globalIsStaticLocal &&
1924 !getOperation()->getParentOfType<cir::GlobalOp>())
1925 return emitOpError(
"static_local attribute mismatch");
1926 }
else if (
auto f = dyn_cast<FuncOp>(op)) {
1927 symTy = f.getFunctionType();
1929 llvm_unreachable(
"Unexpected operation for GetGlobalOp");
1932 auto resultType = dyn_cast<PointerType>(getAddr().
getType());
1933 if (!resultType || symTy != resultType.getPointee())
1934 return emitOpError(
"result type pointee type '")
1935 << resultType.getPointee() <<
"' does not match type " << symTy
1936 <<
" of the global @" <<
getName();
1946cir::VTableAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1952 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
1954 return emitOpError(
"'")
1955 <<
name <<
"' does not reference a valid cir.global";
1956 std::optional<mlir::Attribute> init = op.getInitialValue();
1959 if (!isa<cir::VTableAttr>(*init))
1960 return emitOpError(
"Expected #cir.vtable in initializer for global '")
1970cir::VTTAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1979 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
1981 return emitOpError(
"'")
1982 <<
name <<
"' does not reference a valid cir.global";
1983 std::optional<mlir::Attribute> init = op.getInitialValue();
1986 if (!isa<cir::ConstArrayAttr>(*init))
1988 "Expected constant array in initializer for global VTT '")
1993LogicalResult cir::VTTAddrPointOp::verify() {
1995 if (
getName() && getSymAddr())
1996 return emitOpError(
"should use either a symbol or value, but not both");
2002 mlir::Type resultType = getAddr().getType();
2003 mlir::Type resTy = cir::PointerType::get(
2004 cir::PointerType::get(cir::VoidType::get(getContext())));
2006 if (resultType != resTy)
2007 return emitOpError(
"result type must be ")
2008 << resTy <<
", but provided result type is " << resultType;
2020void cir::FuncOp::build(OpBuilder &builder, OperationState &result,
2021 StringRef name, FuncType type,
2022 GlobalLinkageKind linkage) {
2024 result.addAttribute(SymbolTable::getSymbolAttrName(),
2025 builder.getStringAttr(name));
2026 result.addAttribute(getFunctionTypeAttrName(result.name),
2027 TypeAttr::get(type));
2028 result.addAttribute(
2030 GlobalLinkageKindAttr::get(builder.getContext(), linkage));
2031 result.addAttribute(getGlobalVisibilityAttrName(result.name),
2032 cir::VisibilityAttr::get(builder.getContext()));
2035ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
2036 llvm::SMLoc loc = parser.getCurrentLocation();
2037 mlir::Builder &builder = parser.getBuilder();
2039 mlir::StringAttr builtinNameAttr = getBuiltinAttrName(state.name);
2040 mlir::StringAttr coroutineNameAttr = getCoroutineAttrName(state.name);
2041 mlir::StringAttr inlineKindNameAttr = getInlineKindAttrName(state.name);
2042 mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
2043 mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
2044 mlir::StringAttr comdatNameAttr = getComdatAttrName(state.name);
2045 mlir::StringAttr visNameAttr = getSymVisibilityAttrName(state.name);
2046 mlir::StringAttr visibilityNameAttr = getGlobalVisibilityAttrName(state.name);
2047 mlir::StringAttr dsoLocalNameAttr = getDsoLocalAttrName(state.name);
2048 mlir::StringAttr specialMemberAttr = getCxxSpecialMemberAttrName(state.name);
2050 if (::mlir::succeeded(parser.parseOptionalKeyword(builtinNameAttr.strref())))
2051 state.addAttribute(builtinNameAttr, parser.getBuilder().getUnitAttr());
2052 if (::mlir::succeeded(
2053 parser.parseOptionalKeyword(coroutineNameAttr.strref())))
2054 state.addAttribute(coroutineNameAttr, parser.getBuilder().getUnitAttr());
2057 cir::InlineKindAttr inlineKindAttr;
2061 state.addAttribute(inlineKindNameAttr, inlineKindAttr);
2063 if (::mlir::succeeded(parser.parseOptionalKeyword(lambdaNameAttr.strref())))
2064 state.addAttribute(lambdaNameAttr, parser.getBuilder().getUnitAttr());
2065 if (parser.parseOptionalKeyword(noProtoNameAttr).succeeded())
2066 state.addAttribute(noProtoNameAttr, parser.getBuilder().getUnitAttr());
2068 if (parser.parseOptionalKeyword(comdatNameAttr).succeeded())
2069 state.addAttribute(comdatNameAttr, parser.getBuilder().getUnitAttr());
2073 GlobalLinkageKindAttr::get(
2074 parser.getContext(),
2076 parser, GlobalLinkageKind::ExternalLinkage)));
2078 ::llvm::StringRef visAttrStr;
2079 if (parser.parseOptionalKeyword(&visAttrStr, {
"private",
"public",
"nested"})
2081 state.addAttribute(visNameAttr,
2082 parser.getBuilder().getStringAttr(visAttrStr));
2085 cir::VisibilityAttr cirVisibilityAttr;
2087 state.addAttribute(visibilityNameAttr, cirVisibilityAttr);
2089 if (parser.parseOptionalKeyword(dsoLocalNameAttr).succeeded())
2090 state.addAttribute(dsoLocalNameAttr, parser.getBuilder().getUnitAttr());
2092 StringAttr nameAttr;
2093 if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
2099 bool isVariadic =
false;
2100 if (function_interface_impl::parseFunctionSignatureWithArguments(
2101 parser,
true, arguments, isVariadic, resultTypes,
2106 bool argAttrsEmpty =
true;
2107 for (OpAsmParser::Argument &arg : arguments) {
2108 argTypes.push_back(
arg.type);
2112 argAttrs.push_back(
arg.attrs);
2114 argAttrsEmpty =
false;
2118 if (resultTypes.size() > 1 || resultAttrs.size() > 1)
2119 return parser.emitError(
2120 loc,
"functions with multiple return types are not supported");
2122 mlir::Type returnType =
2123 (resultTypes.empty() ? cir::VoidType::get(builder.getContext())
2124 : resultTypes.front());
2126 cir::FuncType fnType = cir::FuncType::get(argTypes, returnType, isVariadic);
2130 state.addAttribute(getFunctionTypeAttrName(state.name),
2131 TypeAttr::get(fnType));
2133 if (!resultAttrs.empty() && resultAttrs[0])
2135 getResAttrsAttrName(state.name),
2136 mlir::ArrayAttr::get(parser.getContext(), {resultAttrs[0]}));
2139 state.addAttribute(getArgAttrsAttrName(state.name),
2140 mlir::ArrayAttr::get(parser.getContext(), argAttrs));
2142 bool hasAlias =
false;
2143 mlir::StringAttr aliaseeNameAttr = getAliaseeAttrName(state.name);
2144 if (parser.parseOptionalKeyword(
"alias").succeeded()) {
2145 if (parser.parseLParen().failed())
2147 mlir::StringAttr aliaseeAttr;
2148 if (parser.parseOptionalSymbolName(aliaseeAttr).failed())
2150 state.addAttribute(aliaseeNameAttr, FlatSymbolRefAttr::get(aliaseeAttr));
2151 if (parser.parseRParen().failed())
2156 mlir::StringAttr personalityNameAttr = getPersonalityAttrName(state.name);
2157 if (parser.parseOptionalKeyword(
"personality").succeeded()) {
2158 if (parser.parseLParen().failed())
2160 mlir::StringAttr personalityAttr;
2161 if (parser.parseOptionalSymbolName(personalityAttr).failed())
2163 state.addAttribute(personalityNameAttr,
2164 FlatSymbolRefAttr::get(personalityAttr));
2165 if (parser.parseRParen().failed())
2169 auto parseGlobalDtorCtor =
2170 [&](StringRef keyword,
2171 llvm::function_ref<void(std::optional<int> prio)> createAttr)
2172 -> mlir::LogicalResult {
2173 if (mlir::succeeded(parser.parseOptionalKeyword(keyword))) {
2174 std::optional<int> priority;
2175 if (mlir::succeeded(parser.parseOptionalLParen())) {
2176 auto parsedPriority = mlir::FieldParser<int>::parse(parser);
2177 if (mlir::failed(parsedPriority))
2178 return parser.emitError(parser.getCurrentLocation(),
2179 "failed to parse 'priority', of type 'int'");
2180 priority = parsedPriority.value_or(
int());
2182 if (parser.parseRParen())
2185 createAttr(priority);
2191 if (parser.parseOptionalKeyword(
"special_member").succeeded()) {
2192 cir::CXXCtorAttr ctorAttr;
2193 cir::CXXDtorAttr dtorAttr;
2194 cir::CXXAssignAttr assignAttr;
2195 if (parser.parseLess().failed())
2197 if (parser.parseOptionalAttribute(ctorAttr).has_value())
2198 state.addAttribute(specialMemberAttr, ctorAttr);
2199 else if (parser.parseOptionalAttribute(dtorAttr).has_value())
2200 state.addAttribute(specialMemberAttr, dtorAttr);
2201 else if (parser.parseOptionalAttribute(assignAttr).has_value())
2202 state.addAttribute(specialMemberAttr, assignAttr);
2203 if (parser.parseGreater().failed())
2207 if (parseGlobalDtorCtor(
"global_ctor", [&](std::optional<int> priority) {
2208 mlir::IntegerAttr globalCtorPriorityAttr =
2209 builder.getI32IntegerAttr(priority.value_or(65535));
2210 state.addAttribute(getGlobalCtorPriorityAttrName(state.name),
2211 globalCtorPriorityAttr);
2215 if (parseGlobalDtorCtor(
"global_dtor", [&](std::optional<int> priority) {
2216 mlir::IntegerAttr globalDtorPriorityAttr =
2217 builder.getI32IntegerAttr(priority.value_or(65535));
2218 state.addAttribute(getGlobalDtorPriorityAttrName(state.name),
2219 globalDtorPriorityAttr);
2223 if (parser.parseOptionalKeyword(
"side_effect").succeeded()) {
2224 cir::SideEffect sideEffect;
2226 if (parser.parseLParen().failed() ||
2228 parser.parseRParen().failed())
2231 auto attr = cir::SideEffectAttr::get(parser.getContext(), sideEffect);
2232 state.addAttribute(CIRDialect::getSideEffectAttrName(), attr);
2236 NamedAttrList parsedAttrs;
2237 if (parser.parseOptionalAttrDictWithKeyword(parsedAttrs))
2240 for (StringRef disallowed : cir::FuncOp::getAttributeNames()) {
2241 if (parsedAttrs.get(disallowed))
2242 return parser.emitError(loc,
"attribute '")
2244 <<
"' should not be specified in the explicit attribute list";
2247 state.attributes.append(parsedAttrs);
2250 auto *body = state.addRegion();
2251 OptionalParseResult parseResult = parser.parseOptionalRegion(
2252 *body, arguments,
false);
2253 if (parseResult.has_value()) {
2255 return parser.emitError(loc,
"function alias shall not have a body");
2256 if (failed(*parseResult))
2260 return parser.emitError(loc,
"expected non-empty function body");
2269bool cir::FuncOp::isDeclaration() {
2272 std::optional<StringRef> aliasee = getAliasee();
2274 return getFunctionBody().empty();
2280bool cir::FuncOp::isCXXSpecialMemberFunction() {
2281 return getCxxSpecialMemberAttr() !=
nullptr;
2284bool cir::FuncOp::isCxxConstructor() {
2285 auto attr = getCxxSpecialMemberAttr();
2286 return attr && dyn_cast<CXXCtorAttr>(attr);
2289bool cir::FuncOp::isCxxDestructor() {
2290 auto attr = getCxxSpecialMemberAttr();
2291 return attr && dyn_cast<CXXDtorAttr>(attr);
2294bool cir::FuncOp::isCxxSpecialAssignment() {
2295 auto attr = getCxxSpecialMemberAttr();
2296 return attr && dyn_cast<CXXAssignAttr>(attr);
2299std::optional<CtorKind> cir::FuncOp::getCxxConstructorKind() {
2300 mlir::Attribute
attr = getCxxSpecialMemberAttr();
2302 if (
auto ctor = dyn_cast<CXXCtorAttr>(attr))
2303 return ctor.getCtorKind();
2305 return std::nullopt;
2308std::optional<AssignKind> cir::FuncOp::getCxxSpecialAssignKind() {
2309 mlir::Attribute
attr = getCxxSpecialMemberAttr();
2311 if (
auto assign = dyn_cast<CXXAssignAttr>(attr))
2312 return assign.getAssignKind();
2314 return std::nullopt;
2317bool cir::FuncOp::isCxxTrivialMemberFunction() {
2318 mlir::Attribute
attr = getCxxSpecialMemberAttr();
2320 if (
auto ctor = dyn_cast<CXXCtorAttr>(attr))
2321 return ctor.getIsTrivial();
2322 if (
auto dtor = dyn_cast<CXXDtorAttr>(attr))
2323 return dtor.getIsTrivial();
2324 if (
auto assign = dyn_cast<CXXAssignAttr>(attr))
2325 return assign.getIsTrivial();
2330mlir::Region *cir::FuncOp::getCallableRegion() {
2336void cir::FuncOp::print(OpAsmPrinter &p) {
2354 if (getLinkage() != GlobalLinkageKind::ExternalLinkage)
2355 p <<
' ' << stringifyGlobalLinkageKind(getLinkage());
2357 mlir::SymbolTable::Visibility vis = getVisibility();
2358 if (vis != mlir::SymbolTable::Visibility::Public)
2361 cir::VisibilityAttr cirVisibilityAttr = getGlobalVisibilityAttr();
2362 if (!cirVisibilityAttr.isDefault()) {
2371 p.printSymbolName(getSymName());
2372 cir::FuncType fnType = getFunctionType();
2373 function_interface_impl::printFunctionSignature(
2374 p, *
this, fnType.getInputs(), fnType.isVarArg(), fnType.getReturnTypes());
2376 if (std::optional<StringRef> aliaseeName = getAliasee()) {
2378 p.printSymbolName(*aliaseeName);
2382 if (std::optional<StringRef> personalityName = getPersonality()) {
2383 p <<
" personality(";
2384 p.printSymbolName(*personalityName);
2388 if (
auto specialMemberAttr = getCxxSpecialMember()) {
2389 p <<
" special_member<";
2390 p.printAttribute(*specialMemberAttr);
2394 if (
auto globalCtorPriority = getGlobalCtorPriority()) {
2395 p <<
" global_ctor";
2396 if (globalCtorPriority.value() != 65535)
2397 p <<
"(" << globalCtorPriority.value() <<
")";
2400 if (
auto globalDtorPriority = getGlobalDtorPriority()) {
2401 p <<
" global_dtor";
2402 if (globalDtorPriority.value() != 65535)
2403 p <<
"(" << globalDtorPriority.value() <<
")";
2406 if (std::optional<cir::SideEffect> sideEffect = getSideEffect();
2407 sideEffect && *sideEffect != cir::SideEffect::All) {
2408 p <<
" side_effect(";
2409 p << stringifySideEffect(*sideEffect);
2413 function_interface_impl::printFunctionAttributes(
2414 p, *
this, cir::FuncOp::getAttributeNames());
2417 Region &body = getOperation()->getRegion(0);
2418 if (!body.empty()) {
2420 p.printRegion(body,
false,
2425mlir::LogicalResult cir::FuncOp::verify() {
2427 if (!isDeclaration() && getCoroutine()) {
2428 bool foundAwait =
false;
2429 this->walk([&](Operation *op) {
2430 if (
auto await = dyn_cast<AwaitOp>(op)) {
2436 return emitOpError()
2437 <<
"coroutine body must use at least one cir.await op";
2440 llvm::SmallSet<llvm::StringRef, 16> labels;
2441 llvm::SmallSet<llvm::StringRef, 16> gotos;
2442 llvm::SmallSet<llvm::StringRef, 16> blockAddresses;
2443 bool invalidBlockAddress =
false;
2444 getOperation()->walk([&](mlir::Operation *op) {
2445 if (
auto lab = dyn_cast<cir::LabelOp>(op)) {
2446 labels.insert(lab.getLabel());
2447 }
else if (
auto goTo = dyn_cast<cir::GotoOp>(op)) {
2448 gotos.insert(goTo.getLabel());
2449 }
else if (
auto blkAdd = dyn_cast<cir::BlockAddressOp>(op)) {
2450 if (blkAdd.getBlockAddrInfoAttr().getFunc().getAttr() != getSymName()) {
2452 invalidBlockAddress =
true;
2453 return mlir::WalkResult::interrupt();
2455 blockAddresses.insert(blkAdd.getBlockAddrInfoAttr().getLabel());
2457 return mlir::WalkResult::advance();
2460 if (invalidBlockAddress)
2461 return emitOpError() <<
"blockaddress references a different function";
2463 llvm::SmallSet<llvm::StringRef, 16> mismatched;
2464 if (!labels.empty() || !gotos.empty()) {
2465 mismatched = llvm::set_difference(gotos, labels);
2467 if (!mismatched.empty())
2468 return emitOpError() <<
"goto/label mismatch";
2473 if (!labels.empty() || !blockAddresses.empty()) {
2474 mismatched = llvm::set_difference(blockAddresses, labels);
2476 if (!mismatched.empty())
2477 return emitOpError()
2478 <<
"expects an existing label target in the referenced function";
2490 bool noUnsignedWrap,
bool saturated,
2492 bool noWrap = noSignedWrap || noUnsignedWrap;
2493 if (!isa<cir::IntType>(op->getResultTypes()[0]) && noWrap)
2494 return op->emitError()
2495 <<
"only operations on integer values may have nsw/nuw flags";
2496 if (hasSat && saturated && !isa<cir::IntType>(op->getResultTypes()[0]))
2497 return op->emitError()
2498 <<
"only operations on integer values may have sat flag";
2499 if (hasSat && noWrap && saturated)
2500 return op->emitError()
2501 <<
"the nsw/nuw flags and the saturated flag are mutually exclusive";
2502 return mlir::success();
2505LogicalResult cir::AddOp::verify() {
2507 getNoUnsignedWrap(), getSaturated(),
2511LogicalResult cir::SubOp::verify() {
2513 getNoUnsignedWrap(), getSaturated(),
2517LogicalResult cir::MulOp::verify() {
2519 getNoUnsignedWrap(),
false,
2532void cir::TernaryOp::getSuccessorRegions(
2533 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
2535 if (!point.isParent()) {
2536 regions.push_back(RegionSuccessor::parent());
2542 regions.push_back(RegionSuccessor(&getTrueRegion()));
2543 regions.push_back(RegionSuccessor(&getFalseRegion()));
2546mlir::ValueRange cir::TernaryOp::getSuccessorInputs(RegionSuccessor successor) {
2547 return successor.isParent() ? ValueRange(getOperation()->getResults())
2551void cir::TernaryOp::build(
2552 OpBuilder &builder, OperationState &result,
Value cond,
2553 function_ref<
void(OpBuilder &, Location)> trueBuilder,
2554 function_ref<
void(OpBuilder &, Location)> falseBuilder) {
2555 result.addOperands(cond);
2556 OpBuilder::InsertionGuard guard(builder);
2557 Region *trueRegion = result.addRegion();
2558 builder.createBlock(trueRegion);
2559 trueBuilder(builder, result.location);
2560 Region *falseRegion = result.addRegion();
2561 builder.createBlock(falseRegion);
2562 falseBuilder(builder, result.location);
2567 if (trueRegion->back().mightHaveTerminator())
2568 yield = dyn_cast_or_null<cir::YieldOp>(trueRegion->back().getTerminator());
2569 if (!yield && falseRegion->back().mightHaveTerminator())
2570 yield = dyn_cast_or_null<cir::YieldOp>(falseRegion->back().getTerminator());
2572 assert((!yield || yield.getNumOperands() <= 1) &&
2573 "expected zero or one result type");
2574 if (yield && yield.getNumOperands() == 1)
2575 result.addTypes(TypeRange{yield.getOperandTypes().front()});
2582OpFoldResult cir::SelectOp::fold(FoldAdaptor adaptor) {
2583 mlir::Attribute
condition = adaptor.getCondition();
2585 bool conditionValue = mlir::cast<cir::BoolAttr>(
condition).getValue();
2586 return conditionValue ? getTrueValue() : getFalseValue();
2590 mlir::Attribute trueValue = adaptor.getTrueValue();
2591 mlir::Attribute falseValue = adaptor.getFalseValue();
2592 if (trueValue == falseValue)
2594 if (getTrueValue() == getFalseValue())
2595 return getTrueValue();
2600LogicalResult cir::SelectOp::verify() {
2602 auto condTy = dyn_cast<cir::VectorType>(getCondition().
getType());
2609 if (!isa<cir::VectorType>(getTrueValue().
getType()) ||
2610 !isa<cir::VectorType>(getFalseValue().
getType())) {
2611 return emitOpError()
2612 <<
"expected both true and false operands to be vector types "
2613 "when the condition is a vector boolean type";
2622LogicalResult cir::ShiftOp::verify() {
2623 mlir::Operation *op = getOperation();
2624 auto op0VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(0).getType());
2625 auto op1VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(1).getType());
2626 if (!op0VecTy ^ !op1VecTy)
2627 return emitOpError() <<
"input types cannot be one vector and one scalar";
2630 if (op0VecTy.getSize() != op1VecTy.getSize())
2631 return emitOpError() <<
"input vector types must have the same size";
2633 auto opResultTy = mlir::dyn_cast<cir::VectorType>(
getType());
2635 return emitOpError() <<
"the type of the result must be a vector "
2636 <<
"if it is vector shift";
2638 auto op0VecEleTy = mlir::cast<cir::IntType>(op0VecTy.getElementType());
2639 auto op1VecEleTy = mlir::cast<cir::IntType>(op1VecTy.getElementType());
2640 if (op0VecEleTy.getWidth() != op1VecEleTy.getWidth())
2641 return emitOpError()
2642 <<
"vector operands do not have the same elements sizes";
2644 auto resVecEleTy = mlir::cast<cir::IntType>(opResultTy.getElementType());
2645 if (op0VecEleTy.getWidth() != resVecEleTy.getWidth())
2646 return emitOpError() <<
"vector operands and result type do not have the "
2647 "same elements sizes";
2650 return mlir::success();
2657LogicalResult cir::LabelOp::verify() {
2658 mlir::Operation *op = getOperation();
2659 mlir::Block *blk = op->getBlock();
2660 if (&blk->front() != op)
2661 return emitError() <<
"must be the first operation in a block";
2663 return mlir::success();
2670LogicalResult cir::UnaryOp::verify() {
2672 case cir::UnaryOpKind::Inc:
2673 case cir::UnaryOpKind::Dec:
2674 case cir::UnaryOpKind::Plus:
2675 case cir::UnaryOpKind::Minus:
2676 case cir::UnaryOpKind::Not:
2681 llvm_unreachable(
"Unknown UnaryOp kind?");
2685 return isa<cir::BoolType>(op.getInput().getType()) &&
2686 op.getKind() == cir::UnaryOpKind::Not;
2698OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) {
2700 mlir::dyn_cast_if_present<cir::PoisonAttr>(adaptor.getInput())) {
2706 if (
auto previous = getInput().getDefiningOp<cir::UnaryOp>())
2708 return previous.getInput();
2714 if (
auto srcConst = getInput().getDefiningOp<cir::ConstantOp>()) {
2715 if (
getKind() == cir::UnaryOpKind::Plus ||
2716 (mlir::isa<cir::BoolType>(srcConst.getType()) &&
2717 getKind() == cir::UnaryOpKind::Minus))
2718 return srcConst.getResult();
2725 if (mlir::Attribute attr = adaptor.getInput()) {
2727 OpFoldResult result =
2728 llvm::TypeSwitch<mlir::Attribute, OpFoldResult>(attr)
2729 .Case<cir::IntAttr>([&](cir::IntAttr attrT) {
2731 case cir::UnaryOpKind::Not: {
2732 APInt val = attrT.getValue();
2734 return cir::IntAttr::get(
getType(), val);
2736 case cir::UnaryOpKind::Plus:
2738 case cir::UnaryOpKind::Minus: {
2739 APInt val = attrT.getValue();
2741 return cir::IntAttr::get(
getType(), val);
2744 return cir::IntAttr{};
2747 .Case<cir::FPAttr>([&](cir::FPAttr attrT) {
2749 case cir::UnaryOpKind::Plus:
2751 case cir::UnaryOpKind::Minus: {
2752 APFloat val = attrT.getValue();
2754 return cir::FPAttr::get(
getType(), val);
2757 return cir::FPAttr{};
2760 .Case<cir::BoolAttr>([&](cir::BoolAttr attrT) {
2762 case cir::UnaryOpKind::Not:
2763 return cir::BoolAttr::get(getContext(), !attrT.getValue());
2764 case cir::UnaryOpKind::Plus:
2765 case cir::UnaryOpKind::Minus:
2768 return cir::BoolAttr{};
2771 .
Default([&](
auto attrT) {
return mlir::Attribute{}; });
2784 mlir::Type resultTy) {
2787 mlir::Type inputMemberTy;
2788 mlir::Type resultMemberTy;
2789 if (mlir::isa<cir::DataMemberType>(src.getType())) {
2791 mlir::cast<cir::DataMemberType>(src.getType()).getMemberTy();
2792 resultMemberTy = mlir::cast<cir::DataMemberType>(resultTy).getMemberTy();
2795 if (inputMemberTy != resultMemberTy)
2796 return op->emitOpError()
2797 <<
"member types of the operand and the result do not match";
2799 return mlir::success();
2802LogicalResult cir::BaseDataMemberOp::verify() {
2806LogicalResult cir::DerivedDataMemberOp::verify() {
2814LogicalResult cir::BaseMethodOp::verify() {
2818LogicalResult cir::DerivedMethodOp::verify() {
2826void cir::AwaitOp::build(OpBuilder &builder, OperationState &result,
2830 result.addAttribute(getKindAttrName(result.name),
2831 cir::AwaitKindAttr::get(builder.getContext(),
kind));
2833 OpBuilder::InsertionGuard guard(builder);
2834 Region *readyRegion = result.addRegion();
2835 builder.createBlock(readyRegion);
2836 readyBuilder(builder, result.location);
2840 OpBuilder::InsertionGuard guard(builder);
2841 Region *suspendRegion = result.addRegion();
2842 builder.createBlock(suspendRegion);
2843 suspendBuilder(builder, result.location);
2847 OpBuilder::InsertionGuard guard(builder);
2848 Region *resumeRegion = result.addRegion();
2849 builder.createBlock(resumeRegion);
2850 resumeBuilder(builder, result.location);
2854void cir::AwaitOp::getSuccessorRegions(
2855 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
2858 if (!point.isParent()) {
2859 regions.push_back(RegionSuccessor::parent());
2866 regions.push_back(RegionSuccessor(&this->getReady()));
2867 regions.push_back(RegionSuccessor(&this->getSuspend()));
2868 regions.push_back(RegionSuccessor(&this->getResume()));
2871mlir::ValueRange cir::AwaitOp::getSuccessorInputs(RegionSuccessor successor) {
2872 if (successor.isParent())
2873 return getOperation()->getResults();
2874 if (successor == &getReady())
2875 return getReady().getArguments();
2876 if (successor == &getSuspend())
2877 return getSuspend().getArguments();
2878 if (successor == &getResume())
2879 return getResume().getArguments();
2880 llvm_unreachable(
"invalid region successor");
2883LogicalResult cir::AwaitOp::verify() {
2884 if (!isa<ConditionOp>(this->getReady().back().getTerminator()))
2885 return emitOpError(
"ready region must end with cir.condition");
2893LogicalResult cir::CopyOp::verify() {
2895 if (!
getType().getPointee().hasTrait<DataLayoutTypeInterface::Trait>())
2896 return emitError() <<
"missing data layout for pointee type";
2898 if (getSrc() == getDst())
2899 return emitError() <<
"source and destination are the same";
2901 return mlir::success();
2908LogicalResult cir::GetRuntimeMemberOp::verify() {
2909 auto recordTy = mlir::cast<RecordType>(getAddr().
getType().getPointee());
2910 cir::DataMemberType memberPtrTy = getMember().getType();
2912 if (recordTy != memberPtrTy.getClassTy())
2913 return emitError() <<
"record type does not match the member pointer type";
2914 if (
getType().getPointee() != memberPtrTy.getMemberTy())
2915 return emitError() <<
"result type does not match the member pointer type";
2916 return mlir::success();
2923LogicalResult cir::GetMethodOp::verify() {
2924 cir::MethodType methodTy = getMethod().getType();
2927 cir::PointerType objectPtrTy = getObject().getType();
2928 mlir::Type objectTy = objectPtrTy.getPointee();
2930 if (methodTy.getClassTy() != objectTy)
2931 return emitError() <<
"method class type and object type do not match";
2934 auto calleeTy = mlir::cast<cir::FuncType>(getCallee().
getType().getPointee());
2935 cir::FuncType methodFuncTy = methodTy.getMemberFuncTy();
2942 if (methodFuncTy.getReturnType() != calleeTy.getReturnType())
2944 <<
"method return type and callee return type do not match";
2949 if (calleeArgsTy.empty())
2950 return emitError() <<
"callee parameter list lacks receiver object ptr";
2952 auto calleeThisArgPtrTy = mlir::dyn_cast<cir::PointerType>(calleeArgsTy[0]);
2953 if (!calleeThisArgPtrTy ||
2954 !mlir::isa<cir::VoidType>(calleeThisArgPtrTy.getPointee())) {
2956 <<
"the first parameter of callee must be a void pointer";
2959 if (calleeArgsTy.slice(1) != methodFuncArgsTy)
2961 <<
"callee parameters and method parameters do not match";
2963 return mlir::success();
2970LogicalResult cir::GetMemberOp::verify() {
2971 const auto recordTy = dyn_cast<RecordType>(getAddrTy().getPointee());
2973 return emitError() <<
"expected pointer to a record type";
2975 if (recordTy.getMembers().size() <=
getIndex())
2976 return emitError() <<
"member index out of bounds";
2979 return emitError() <<
"member type mismatch";
2981 return mlir::success();
2988LogicalResult cir::ExtractMemberOp::verify() {
2989 auto recordTy = mlir::cast<cir::RecordType>(getRecord().
getType());
2990 if (recordTy.getKind() == cir::RecordType::Union)
2992 <<
"cir.extract_member currently does not support unions";
2993 if (recordTy.getMembers().size() <=
getIndex())
2994 return emitError() <<
"member index out of bounds";
2996 return emitError() <<
"member type mismatch";
2997 return mlir::success();
3004LogicalResult cir::InsertMemberOp::verify() {
3005 auto recordTy = mlir::cast<cir::RecordType>(getRecord().
getType());
3006 if (recordTy.getKind() == cir::RecordType::Union)
3007 return emitError() <<
"cir.insert_member currently does not support unions";
3008 if (recordTy.getMembers().size() <=
getIndex())
3009 return emitError() <<
"member index out of bounds";
3011 return emitError() <<
"member type mismatch";
3013 return mlir::success();
3020OpFoldResult cir::VecCreateOp::fold(FoldAdaptor adaptor) {
3021 if (llvm::any_of(getElements(), [](mlir::Value value) {
3022 return !value.getDefiningOp<cir::ConstantOp>();
3026 return cir::ConstVectorAttr::get(
3027 getType(), mlir::ArrayAttr::get(getContext(), adaptor.getElements()));
3030LogicalResult cir::VecCreateOp::verify() {
3034 const cir::VectorType vecTy =
getType();
3035 if (getElements().size() != vecTy.getSize()) {
3036 return emitOpError() <<
"operand count of " << getElements().size()
3037 <<
" doesn't match vector type " << vecTy
3038 <<
" element count of " << vecTy.getSize();
3041 const mlir::Type elementType = vecTy.getElementType();
3042 for (
const mlir::Value element : getElements()) {
3043 if (element.getType() != elementType) {
3044 return emitOpError() <<
"operand type " << element.getType()
3045 <<
" doesn't match vector element type "
3057OpFoldResult cir::VecExtractOp::fold(FoldAdaptor adaptor) {
3058 const auto vectorAttr =
3059 llvm::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec());
3063 const auto indexAttr =
3064 llvm::dyn_cast_if_present<cir::IntAttr>(adaptor.getIndex());
3068 const mlir::ArrayAttr elements = vectorAttr.getElts();
3069 const uint64_t index = indexAttr.getUInt();
3070 if (index >= elements.size())
3073 return elements[index];
3080OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
3082 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getLhs());
3084 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getRhs());
3085 if (!lhsVecAttr || !rhsVecAttr)
3088 mlir::Type inputElemTy =
3089 mlir::cast<cir::VectorType>(lhsVecAttr.getType()).getElementType();
3090 if (!isAnyIntegerOrFloatingPointType(inputElemTy))
3093 cir::CmpOpKind opKind = adaptor.getKind();
3094 mlir::ArrayAttr lhsVecElhs = lhsVecAttr.getElts();
3095 mlir::ArrayAttr rhsVecElhs = rhsVecAttr.getElts();
3096 uint64_t vecSize = lhsVecElhs.size();
3099 bool isIntAttr = vecSize && mlir::isa<cir::IntAttr>(lhsVecElhs[0]);
3100 for (uint64_t i = 0; i < vecSize; i++) {
3101 mlir::Attribute lhsAttr = lhsVecElhs[i];
3102 mlir::Attribute rhsAttr = rhsVecElhs[i];
3105 case cir::CmpOpKind::lt: {
3107 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <
3108 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3110 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <
3111 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3115 case cir::CmpOpKind::le: {
3117 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <=
3118 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3120 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <=
3121 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3125 case cir::CmpOpKind::gt: {
3127 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >
3128 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3130 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >
3131 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3135 case cir::CmpOpKind::ge: {
3137 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >=
3138 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3140 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >=
3141 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3145 case cir::CmpOpKind::eq: {
3147 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() ==
3148 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3150 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() ==
3151 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3155 case cir::CmpOpKind::ne: {
3157 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() !=
3158 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
3160 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() !=
3161 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
3167 elements[i] = cir::IntAttr::get(
getType().getElementType(), cmpResult);
3170 return cir::ConstVectorAttr::get(
3171 getType(), mlir::ArrayAttr::get(getContext(), elements));
3178OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor adaptor) {
3180 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec1());
3182 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec2());
3183 if (!vec1Attr || !vec2Attr)
3186 mlir::Type vec1ElemTy =
3187 mlir::cast<cir::VectorType>(vec1Attr.getType()).getElementType();
3189 mlir::ArrayAttr vec1Elts = vec1Attr.getElts();
3190 mlir::ArrayAttr vec2Elts = vec2Attr.getElts();
3191 mlir::ArrayAttr indicesElts = adaptor.getIndices();
3194 elements.reserve(indicesElts.size());
3196 uint64_t vec1Size = vec1Elts.size();
3197 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
3198 if (idxAttr.getSInt() == -1) {
3199 elements.push_back(cir::UndefAttr::get(vec1ElemTy));
3203 uint64_t idxValue = idxAttr.getUInt();
3204 elements.push_back(idxValue < vec1Size ? vec1Elts[idxValue]
3205 : vec2Elts[idxValue - vec1Size]);
3208 return cir::ConstVectorAttr::get(
3209 getType(), mlir::ArrayAttr::get(getContext(), elements));
3212LogicalResult cir::VecShuffleOp::verify() {
3215 if (getIndices().size() != getResult().
getType().getSize()) {
3216 return emitOpError() <<
": the number of elements in " << getIndices()
3217 <<
" and " << getResult().getType() <<
" don't match";
3222 if (getVec1().
getType().getElementType() !=
3223 getResult().
getType().getElementType()) {
3224 return emitOpError() <<
": element types of " << getVec1().getType()
3225 <<
" and " << getResult().getType() <<
" don't match";
3228 const uint64_t maxValidIndex =
3229 getVec1().getType().getSize() + getVec2().getType().getSize() - 1;
3231 getIndices().getAsRange<cir::IntAttr>(), [&](cir::IntAttr idxAttr) {
3232 return idxAttr.getSInt() != -1 && idxAttr.getUInt() > maxValidIndex;
3234 return emitOpError() <<
": index for __builtin_shufflevector must be "
3235 "less than the total number of vector elements";
3244OpFoldResult cir::VecShuffleDynamicOp::fold(FoldAdaptor adaptor) {
3245 mlir::Attribute vec = adaptor.getVec();
3246 mlir::Attribute indices = adaptor.getIndices();
3247 if (mlir::isa_and_nonnull<cir::ConstVectorAttr>(vec) &&
3248 mlir::isa_and_nonnull<cir::ConstVectorAttr>(indices)) {
3249 auto vecAttr = mlir::cast<cir::ConstVectorAttr>(vec);
3250 auto indicesAttr = mlir::cast<cir::ConstVectorAttr>(indices);
3252 mlir::ArrayAttr vecElts = vecAttr.getElts();
3253 mlir::ArrayAttr indicesElts = indicesAttr.getElts();
3255 const uint64_t numElements = vecElts.size();
3258 elements.reserve(numElements);
3260 const uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
3261 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
3262 uint64_t idxValue = idxAttr.getUInt();
3263 uint64_t newIdx = idxValue & maskBits;
3264 elements.push_back(vecElts[newIdx]);
3267 return cir::ConstVectorAttr::get(
3268 getType(), mlir::ArrayAttr::get(getContext(), elements));
3274LogicalResult cir::VecShuffleDynamicOp::verify() {
3276 if (getVec().
getType().getSize() !=
3277 mlir::cast<cir::VectorType>(getIndices().
getType()).getSize()) {
3278 return emitOpError() <<
": the number of elements in " << getVec().getType()
3279 <<
" and " << getIndices().getType() <<
" don't match";
3288LogicalResult cir::VecTernaryOp::verify() {
3293 if (getCond().
getType().getSize() != getLhs().
getType().getSize()) {
3294 return emitOpError() <<
": the number of elements in "
3295 << getCond().getType() <<
" and " << getLhs().getType()
3301OpFoldResult cir::VecTernaryOp::fold(FoldAdaptor adaptor) {
3302 mlir::Attribute cond = adaptor.getCond();
3303 mlir::Attribute lhs = adaptor.getLhs();
3304 mlir::Attribute rhs = adaptor.getRhs();
3306 if (!mlir::isa_and_nonnull<cir::ConstVectorAttr>(cond) ||
3307 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(lhs) ||
3308 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(rhs))
3310 auto condVec = mlir::cast<cir::ConstVectorAttr>(cond);
3311 auto lhsVec = mlir::cast<cir::ConstVectorAttr>(lhs);
3312 auto rhsVec = mlir::cast<cir::ConstVectorAttr>(rhs);
3314 mlir::ArrayAttr condElts = condVec.getElts();
3317 elements.reserve(condElts.size());
3319 for (
const auto &[idx, condAttr] :
3320 llvm::enumerate(condElts.getAsRange<cir::IntAttr>())) {
3321 if (condAttr.getSInt()) {
3322 elements.push_back(lhsVec.getElts()[idx]);
3324 elements.push_back(rhsVec.getElts()[idx]);
3328 cir::VectorType vecTy = getLhs().getType();
3329 return cir::ConstVectorAttr::get(
3330 vecTy, mlir::ArrayAttr::get(getContext(), elements));
3337LogicalResult cir::ComplexCreateOp::verify() {
3340 <<
"operand type of cir.complex.create does not match its result type";
3347OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) {
3348 mlir::Attribute real = adaptor.getReal();
3349 mlir::Attribute imag = adaptor.getImag();
3355 auto realAttr = mlir::cast<mlir::TypedAttr>(real);
3356 auto imagAttr = mlir::cast<mlir::TypedAttr>(imag);
3357 return cir::ConstComplexAttr::get(realAttr, imagAttr);
3364LogicalResult cir::ComplexRealOp::verify() {
3365 mlir::Type operandTy = getOperand().getType();
3366 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
3367 operandTy = complexOperandTy.getElementType();
3370 emitOpError() <<
": result type does not match operand type";
3377OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) {
3378 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
3381 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
3382 return complexCreateOp.getOperand(0);
3385 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
3386 return complex ? complex.getReal() :
nullptr;
3393LogicalResult cir::ComplexImagOp::verify() {
3394 mlir::Type operandTy = getOperand().getType();
3395 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
3396 operandTy = complexOperandTy.getElementType();
3399 emitOpError() <<
": result type does not match operand type";
3406OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) {
3407 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
3410 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
3411 return complexCreateOp.getOperand(1);
3414 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
3415 return complex ? complex.getImag() :
nullptr;
3422LogicalResult cir::ComplexRealPtrOp::verify() {
3423 mlir::Type resultPointeeTy =
getType().getPointee();
3424 cir::PointerType operandPtrTy = getOperand().getType();
3425 auto operandPointeeTy =
3426 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
3428 if (resultPointeeTy != operandPointeeTy.getElementType()) {
3429 return emitOpError() <<
": result type does not match operand type";
3439LogicalResult cir::ComplexImagPtrOp::verify() {
3440 mlir::Type resultPointeeTy =
getType().getPointee();
3441 cir::PointerType operandPtrTy = getOperand().getType();
3442 auto operandPointeeTy =
3443 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
3445 if (resultPointeeTy != operandPointeeTy.getElementType()) {
3446 return emitOpError()
3447 <<
"cir.complex.imag_ptr result type does not match operand type";
3458 llvm::function_ref<llvm::APInt(
const llvm::APInt &)> func,
3459 bool poisonZero =
false) {
3460 if (mlir::isa_and_present<cir::PoisonAttr>(inputAttr)) {
3465 auto input = mlir::dyn_cast_if_present<IntAttr>(inputAttr);
3469 llvm::APInt inputValue = input.getValue();
3470 if (poisonZero && inputValue.isZero())
3471 return cir::PoisonAttr::get(input.getType());
3473 llvm::APInt resultValue = func(inputValue);
3474 return IntAttr::get(input.getType(), resultValue);
3477OpFoldResult BitClrsbOp::fold(FoldAdaptor adaptor) {
3478 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3479 unsigned resultValue =
3480 inputValue.getBitWidth() - inputValue.getSignificantBits();
3481 return llvm::APInt(inputValue.getBitWidth(), resultValue);
3485OpFoldResult BitClzOp::fold(FoldAdaptor adaptor) {
3488 [](
const llvm::APInt &inputValue) {
3489 unsigned resultValue = inputValue.countLeadingZeros();
3490 return llvm::APInt(inputValue.getBitWidth(), resultValue);
3495OpFoldResult BitCtzOp::fold(FoldAdaptor adaptor) {
3498 [](
const llvm::APInt &inputValue) {
3499 return llvm::APInt(inputValue.getBitWidth(),
3500 inputValue.countTrailingZeros());
3505OpFoldResult BitFfsOp::fold(FoldAdaptor adaptor) {
3506 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3507 unsigned trailingZeros = inputValue.countTrailingZeros();
3509 trailingZeros == inputValue.getBitWidth() ? 0 : trailingZeros + 1;
3510 return llvm::APInt(inputValue.getBitWidth(), result);
3514OpFoldResult BitParityOp::fold(FoldAdaptor adaptor) {
3515 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3516 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount() % 2);
3520OpFoldResult BitPopcountOp::fold(FoldAdaptor adaptor) {
3521 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3522 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount());
3526OpFoldResult BitReverseOp::fold(FoldAdaptor adaptor) {
3527 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3528 return inputValue.reverseBits();
3532OpFoldResult ByteSwapOp::fold(FoldAdaptor adaptor) {
3533 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
3534 return inputValue.byteSwap();
3538OpFoldResult RotateOp::fold(FoldAdaptor adaptor) {
3539 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()) ||
3540 mlir::isa_and_present<cir::PoisonAttr>(adaptor.getAmount())) {
3542 return cir::PoisonAttr::get(
getType());
3545 auto input = mlir::dyn_cast_if_present<IntAttr>(adaptor.getInput());
3546 auto amount = mlir::dyn_cast_if_present<IntAttr>(adaptor.getAmount());
3547 if (!input && !amount)
3556 llvm::APInt inputValue;
3558 inputValue = input.getValue();
3559 if (inputValue.isZero() || inputValue.isAllOnes()) {
3565 uint64_t amountValue;
3567 amountValue = amount.getValue().urem(getInput().
getType().getWidth());
3568 if (amountValue == 0) {
3574 if (!input || !amount)
3577 assert(inputValue.getBitWidth() == getInput().
getType().getWidth() &&
3578 "input value must have the same bit width as the input type");
3580 llvm::APInt resultValue;
3582 resultValue = inputValue.rotl(amountValue);
3584 resultValue = inputValue.rotr(amountValue);
3586 return IntAttr::get(input.getContext(), input.getType(), resultValue);
3593void cir::InlineAsmOp::print(OpAsmPrinter &p) {
3594 p <<
'(' << getAsmFlavor() <<
", ";
3599 auto *nameIt = names.begin();
3600 auto *attrIt = getOperandAttrs().begin();
3602 for (mlir::OperandRange ops : getAsmOperands()) {
3603 p << *nameIt <<
" = ";
3606 llvm::interleaveComma(llvm::make_range(ops.begin(), ops.end()), p,
3608 p.printOperand(value);
3609 p <<
" : " << value.getType();
3611 p <<
" (maybe_memory)";
3620 p.printString(getAsmString());
3622 p.printString(getConstraints());
3626 if (getSideEffects())
3627 p <<
" side_effects";
3629 std::array elidedAttrs{
3630 llvm::StringRef(
"asm_flavor"), llvm::StringRef(
"asm_string"),
3631 llvm::StringRef(
"constraints"), llvm::StringRef(
"operand_attrs"),
3632 llvm::StringRef(
"operands_segments"), llvm::StringRef(
"side_effects")};
3633 p.printOptionalAttrDict(getOperation()->getAttrs(), elidedAttrs);
3635 if (
auto v = getRes())
3636 p <<
" -> " << v.getType();
3639void cir::InlineAsmOp::build(OpBuilder &odsBuilder, OperationState &odsState,
3641 StringRef asmString, StringRef constraints,
3642 bool sideEffects, cir::AsmFlavor asmFlavor,
3646 for (
auto operandRange : asmOperands) {
3647 segments.push_back(operandRange.size());
3648 odsState.addOperands(operandRange);
3651 odsState.addAttribute(
3652 "operands_segments",
3653 DenseI32ArrayAttr::get(odsBuilder.getContext(), segments));
3654 odsState.addAttribute(
"asm_string", odsBuilder.getStringAttr(asmString));
3655 odsState.addAttribute(
"constraints", odsBuilder.getStringAttr(constraints));
3656 odsState.addAttribute(
"asm_flavor",
3657 AsmFlavorAttr::get(odsBuilder.getContext(), asmFlavor));
3660 odsState.addAttribute(
"side_effects", odsBuilder.getUnitAttr());
3662 odsState.addAttribute(
"operand_attrs", odsBuilder.getArrayAttr(operandAttrs));
3665ParseResult cir::InlineAsmOp::parse(OpAsmParser &parser,
3666 OperationState &result) {
3669 std::string asmString, constraints;
3671 MLIRContext *ctxt = parser.getBuilder().getContext();
3673 auto error = [&](
const Twine &msg) -> LogicalResult {
3674 return parser.emitError(parser.getCurrentLocation(), msg);
3677 auto expected = [&](
const std::string &
c) {
3678 return error(
"expected '" +
c +
"'");
3681 if (parser.parseLParen().failed())
3682 return expected(
"(");
3684 auto flavor = FieldParser<AsmFlavor, AsmFlavor>::parse(parser);
3686 return error(
"Unknown AsmFlavor");
3688 if (parser.parseComma().failed())
3689 return expected(
",");
3691 auto parseValue = [&](
Value &v) {
3692 OpAsmParser::UnresolvedOperand op;
3694 if (parser.parseOperand(op) || parser.parseColon())
3695 return error(
"can't parse operand");
3698 if (parser.parseType(typ).failed())
3699 return error(
"can't parse operand type");
3701 if (parser.resolveOperand(op, typ, tmp))
3702 return error(
"can't resolve operand");
3704 return mlir::success();
3707 auto parseOperands = [&](llvm::StringRef
name) {
3708 if (parser.parseKeyword(name).failed())
3709 return error(
"expected " + name +
" operands here");
3710 if (parser.parseEqual().failed())
3711 return expected(
"=");
3712 if (parser.parseLSquare().failed())
3713 return expected(
"[");
3716 if (parser.parseOptionalRSquare().succeeded()) {
3717 operandsGroupSizes.push_back(size);
3718 if (parser.parseComma())
3719 return expected(
",");
3720 return mlir::success();
3723 auto parseOperand = [&]() {
3725 if (parseValue(val).succeeded()) {
3726 result.operands.push_back(val);
3729 if (parser.parseOptionalLParen().failed()) {
3730 operandAttrs.push_back(mlir::Attribute());
3731 return mlir::success();
3734 if (parser.parseKeyword(
"maybe_memory").succeeded()) {
3735 operandAttrs.push_back(mlir::UnitAttr::get(ctxt));
3736 if (parser.parseRParen())
3737 return expected(
")");
3738 return mlir::success();
3740 return expected(
"maybe_memory");
3743 return mlir::failure();
3746 if (parser.parseCommaSeparatedList(parseOperand).failed())
3747 return mlir::failure();
3749 if (parser.parseRSquare().failed() || parser.parseComma().failed())
3750 return expected(
"]");
3751 operandsGroupSizes.push_back(size);
3752 return mlir::success();
3755 if (parseOperands(
"out").failed() || parseOperands(
"in").failed() ||
3756 parseOperands(
"in_out").failed())
3757 return error(
"failed to parse operands");
3759 if (parser.parseLBrace())
3760 return expected(
"{");
3761 if (parser.parseString(&asmString))
3762 return error(
"asm string parsing failed");
3763 if (parser.parseString(&constraints))
3764 return error(
"constraints string parsing failed");
3765 if (parser.parseRBrace())
3766 return expected(
"}");
3767 if (parser.parseRParen())
3768 return expected(
")");
3770 if (parser.parseOptionalKeyword(
"side_effects").succeeded())
3771 result.attributes.set(
"side_effects", UnitAttr::get(ctxt));
3773 if (parser.parseOptionalArrow().succeeded() &&
3774 parser.parseType(resType).failed())
3775 return mlir::failure();
3777 if (parser.parseOptionalAttrDict(result.attributes).failed())
3778 return mlir::failure();
3780 result.attributes.set(
"asm_flavor", AsmFlavorAttr::get(ctxt, *flavor));
3781 result.attributes.set(
"asm_string", StringAttr::get(ctxt, asmString));
3782 result.attributes.set(
"constraints", StringAttr::get(ctxt, constraints));
3783 result.attributes.set(
"operand_attrs", ArrayAttr::get(ctxt, operandAttrs));
3784 result.getOrAddProperties<InlineAsmOp::Properties>().operands_segments =
3785 parser.getBuilder().getDenseI32ArrayAttr(operandsGroupSizes);
3787 result.addTypes(TypeRange{resType});
3789 return mlir::success();
3796mlir::LogicalResult cir::ThrowOp::verify() {
3801 if (getNumOperands() != 0) {
3804 return emitOpError() <<
"'type_info' symbol attribute missing";
3814LogicalResult cir::AtomicFetchOp::verify() {
3815 if (getBinop() != cir::AtomicFetchKind::Add &&
3816 getBinop() != cir::AtomicFetchKind::Sub &&
3817 getBinop() != cir::AtomicFetchKind::Max &&
3818 getBinop() != cir::AtomicFetchKind::Min &&
3819 !mlir::isa<cir::IntType>(getVal().
getType()))
3820 return emitError(
"only atomic add, sub, max, and min operation could "
3821 "operate on floating-point values");
3829LogicalResult cir::TypeInfoAttr::verify(
3830 ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
3831 ::mlir::Type type, ::mlir::ArrayAttr typeInfoData) {
3833 if (cir::ConstRecordAttr::verify(emitError, type, typeInfoData).failed())
3843void cir::TryOp::getSuccessorRegions(
3844 mlir::RegionBranchPoint point,
3847 if (!point.isParent()) {
3848 regions.push_back(RegionSuccessor::parent());
3852 regions.push_back(mlir::RegionSuccessor(&getTryRegion()));
3856 for (mlir::Region &handlerRegion : this->getHandlerRegions())
3857 regions.push_back(mlir::RegionSuccessor(&handlerRegion));
3860mlir::ValueRange cir::TryOp::getSuccessorInputs(RegionSuccessor successor) {
3861 return successor.isParent() ? ValueRange(getOperation()->getResults())
3865LogicalResult cir::TryOp::verify() {
3866 mlir::ArrayAttr handlerTypes = getHandlerTypes();
3867 if (!handlerTypes) {
3868 if (!getHandlerRegions().empty())
3870 "handler regions must be empty when no handler types are present");
3874 mlir::MutableArrayRef<mlir::Region> handlerRegions = getHandlerRegions();
3878 if (handlerRegions.size() != handlerTypes.size())
3880 "number of handler regions and handler types must match");
3882 for (
const auto &[typeAttr, handlerRegion] :
3883 llvm::zip(handlerTypes, handlerRegions)) {
3885 mlir::Block &entryBlock = handlerRegion.front();
3886 if (entryBlock.getNumArguments() != 1 ||
3887 !mlir::isa<cir::EhTokenType>(entryBlock.getArgument(0).getType()))
3889 "handler region must have a single '!cir.eh_token' argument");
3892 if (mlir::isa<cir::UnwindAttr>(typeAttr))
3895 if (entryBlock.empty() || !mlir::isa<cir::BeginCatchOp>(entryBlock.front()))
3897 "catch handler region must start with 'cir.begin_catch'");
3905 mlir::MutableArrayRef<mlir::Region> handlerRegions,
3906 mlir::ArrayAttr handlerTypes) {
3910 for (
const auto [typeIdx, typeAttr] : llvm::enumerate(handlerTypes)) {
3914 if (mlir::isa<cir::CatchAllAttr>(typeAttr)) {
3915 printer <<
"catch all ";
3916 }
else if (mlir::isa<cir::UnwindAttr>(typeAttr)) {
3917 printer <<
"unwind ";
3919 printer <<
"catch [type ";
3920 printer.printAttribute(typeAttr);
3925 mlir::Region ®ion = handlerRegions[typeIdx];
3926 if (!region.empty() && region.front().getNumArguments() > 0) {
3928 printer.printRegionArgument(region.front().getArgument(0));
3932 printer.printRegion(region,
3939 mlir::OpAsmParser &parser,
3941 mlir::ArrayAttr &handlerTypes) {
3943 auto parseCheckedCatcherRegion = [&]() -> mlir::ParseResult {
3944 handlerRegions.emplace_back(
new mlir::Region);
3946 mlir::Region &currRegion = *handlerRegions.back();
3950 if (parser.parseLParen())
3952 mlir::OpAsmParser::Argument arg;
3953 if (parser.parseArgument(arg,
true))
3955 regionArgs.push_back(arg);
3956 if (parser.parseRParen())
3959 mlir::SMLoc regionLoc = parser.getCurrentLocation();
3960 if (parser.parseRegion(currRegion, regionArgs)) {
3961 handlerRegions.clear();
3965 if (currRegion.empty())
3966 return parser.emitError(regionLoc,
"handler region shall not be empty");
3968 if (!(currRegion.back().mightHaveTerminator() &&
3969 currRegion.back().getTerminator()))
3970 return parser.emitError(
3971 regionLoc,
"blocks are expected to be explicitly terminated");
3976 bool hasCatchAll =
false;
3978 while (parser.parseOptionalKeyword(
"catch").succeeded()) {
3979 bool hasLSquare = parser.parseOptionalLSquare().succeeded();
3981 llvm::StringRef attrStr;
3982 if (parser.parseOptionalKeyword(&attrStr, {
"all",
"type"}).failed())
3983 return parser.emitError(parser.getCurrentLocation(),
3984 "expected 'all' or 'type' keyword");
3986 bool isCatchAll = attrStr ==
"all";
3989 return parser.emitError(parser.getCurrentLocation(),
3990 "can't have more than one catch all");
3994 mlir::Attribute exceptionRTTIAttr;
3995 if (!isCatchAll && parser.parseAttribute(exceptionRTTIAttr).failed())
3996 return parser.emitError(parser.getCurrentLocation(),
3997 "expected valid RTTI info attribute");
3999 catcherAttrs.push_back(isCatchAll
4000 ? cir::CatchAllAttr::get(parser.getContext())
4001 : exceptionRTTIAttr);
4003 if (hasLSquare && isCatchAll)
4004 return parser.emitError(parser.getCurrentLocation(),
4005 "catch all dosen't need RTTI info attribute");
4007 if (hasLSquare && parser.parseRSquare().failed())
4008 return parser.emitError(parser.getCurrentLocation(),
4009 "expected `]` after RTTI info attribute");
4011 if (parseCheckedCatcherRegion().failed())
4012 return mlir::failure();
4015 if (parser.parseOptionalKeyword(
"unwind").succeeded()) {
4017 return parser.emitError(parser.getCurrentLocation(),
4018 "unwind can't be used with catch all");
4020 catcherAttrs.push_back(cir::UnwindAttr::get(parser.getContext()));
4021 if (parseCheckedCatcherRegion().failed())
4022 return mlir::failure();
4025 handlerTypes = parser.getBuilder().getArrayAttr(catcherAttrs);
4026 return mlir::success();
4034cir::EhTypeIdOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
4035 Operation *op = symbolTable.lookupNearestSymbolFrom(*
this, getTypeSymAttr());
4036 if (!isa_and_nonnull<GlobalOp>(op))
4037 return emitOpError(
"'")
4038 << getTypeSym() <<
"' does not reference a valid cir.global";
4048 SmallVectorImpl<Block *> &catchDestinations,
4049 Block *&defaultDestination,
4050 mlir::UnitAttr &defaultIsCatchAll) {
4052 if (parser.parseLSquare())
4056 bool hasCatchAll =
false;
4057 bool hasUnwind =
false;
4060 auto parseHandler = [&]() -> ParseResult {
4062 if (succeeded(parser.parseOptionalKeyword(
"catch_all"))) {
4064 return parser.emitError(parser.getCurrentLocation(),
4065 "duplicate 'catch_all' handler");
4067 return parser.emitError(parser.getCurrentLocation(),
4068 "cannot have both 'catch_all' and 'unwind'");
4071 if (parser.parseColon().failed())
4074 if (parser.parseSuccessor(defaultDestination).failed())
4080 if (succeeded(parser.parseOptionalKeyword(
"unwind"))) {
4082 return parser.emitError(parser.getCurrentLocation(),
4083 "duplicate 'unwind' handler");
4085 return parser.emitError(parser.getCurrentLocation(),
4086 "cannot have both 'catch_all' and 'unwind'");
4089 if (parser.parseColon().failed())
4092 if (parser.parseSuccessor(defaultDestination).failed())
4100 if (parser.parseKeyword(
"catch").failed())
4103 if (parser.parseLParen().failed())
4106 mlir::Attribute catchTypeAttr;
4107 if (parser.parseAttribute(catchTypeAttr).failed())
4109 handlerTypes.push_back(catchTypeAttr);
4111 if (parser.parseRParen().failed())
4114 if (parser.parseColon().failed())
4118 if (parser.parseSuccessor(dest).failed())
4120 catchDestinations.push_back(dest);
4124 if (parser.parseCommaSeparatedList(parseHandler).failed())
4127 if (parser.parseRSquare().failed())
4131 if (!hasCatchAll && !hasUnwind)
4132 return parser.emitError(parser.getCurrentLocation(),
4133 "must have either 'catch_all' or 'unwind' handler");
4136 if (!handlerTypes.empty())
4137 catchTypes = parser.getBuilder().getArrayAttr(handlerTypes);
4140 defaultIsCatchAll = parser.getBuilder().getUnitAttr();
4146 mlir::ArrayAttr catchTypes,
4147 SuccessorRange catchDestinations,
4148 Block *defaultDestination,
4149 mlir::UnitAttr defaultIsCatchAll) {
4157 llvm::zip(catchTypes, catchDestinations),
4160 p.printAttribute(std::get<0>(i));
4162 p.printSuccessor(std::get<1>(i));
4174 if (defaultIsCatchAll)
4175 p <<
" catch_all : ";
4178 p.printSuccessor(defaultDestination);
4188#define GET_OP_CLASSES
4189#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 bool isBoolNot(cir::UnaryOp op)
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 )* )?
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.
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)
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 addressSpace()
static bool opCallCallConv()
static bool opScopeCleanupRegion()
static bool supportIFuncAttr()