19#include "mlir/IR/Attributes.h"
20#include "mlir/IR/BuiltinOps.h"
21#include "mlir/IR/BuiltinTypes.h"
22#include "mlir/IR/DialectImplementation.h"
23#include "mlir/IR/PatternMatch.h"
24#include "mlir/IR/Value.h"
25#include "mlir/Interfaces/ControlFlowInterfaces.h"
26#include "mlir/Interfaces/FunctionImplementation.h"
27#include "mlir/Support/LLVM.h"
29#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
30#include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc"
32#include "llvm/ADT/SetOperations.h"
33#include "llvm/ADT/SmallSet.h"
34#include "llvm/ADT/TypeSwitch.h"
35#include "llvm/Support/Casting.h"
36#include "llvm/Support/LogicalResult.h"
47struct CIROpAsmDialectInterface :
public OpAsmDialectInterface {
48 using OpAsmDialectInterface::OpAsmDialectInterface;
50 AliasResult getAlias(Type type, raw_ostream &os)
const final {
51 if (
auto recordType = dyn_cast<cir::RecordType>(type)) {
54 os <<
"rec_anon_" <<
recordType.getKindAsStr();
56 os <<
"rec_" << nameAttr.getValue();
57 return AliasResult::OverridableAlias;
59 if (
auto intType = dyn_cast<cir::IntType>(type)) {
62 unsigned width = intType.getWidth();
63 if (width < 8 || !llvm::isPowerOf2_32(width))
64 return AliasResult::NoAlias;
65 os << intType.getAlias();
66 return AliasResult::OverridableAlias;
68 if (
auto voidType = dyn_cast<cir::VoidType>(type)) {
69 os << voidType.getAlias();
70 return AliasResult::OverridableAlias;
73 return AliasResult::NoAlias;
76 AliasResult getAlias(Attribute attr, raw_ostream &os)
const final {
77 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr)) {
78 os << (boolAttr.getValue() ?
"true" :
"false");
79 return AliasResult::FinalAlias;
81 if (
auto bitfield = mlir::dyn_cast<cir::BitfieldInfoAttr>(attr)) {
82 os <<
"bfi_" << bitfield.getName().str();
83 return AliasResult::FinalAlias;
85 if (
auto dynCastInfoAttr = mlir::dyn_cast<cir::DynamicCastInfoAttr>(attr)) {
86 os << dynCastInfoAttr.getAlias();
87 return AliasResult::FinalAlias;
89 if (
auto cmpThreeWayInfoAttr =
90 mlir::dyn_cast<cir::CmpThreeWayInfoAttr>(attr)) {
91 os << cmpThreeWayInfoAttr.getAlias();
92 return AliasResult::FinalAlias;
94 return AliasResult::NoAlias;
99void cir::CIRDialect::initialize() {
101 registerAttributes();
104#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
106 addInterfaces<CIROpAsmDialectInterface>();
110Operation *cir::CIRDialect::materializeConstant(mlir::OpBuilder &builder,
111 mlir::Attribute value,
113 mlir::Location loc) {
114 return cir::ConstantOp::create(builder, loc, type,
115 mlir::cast<mlir::TypedAttr>(value));
119 return attrName == CIRDialect::getOpenCLVersionAttrName() ||
120 attrName == CIRDialect::getOpenCLCXXVersionAttrName() ||
121 attrName == CIRDialect::getOpenCLSPIRVersionAttrName();
125 NamedAttribute attr) {
126 StringRef attrName = attr.getName().getValue();
127 if (isa<ModuleOp>(op))
130 return op->emitError() << attrName
131 <<
" attribute must be attached to a module";
135 cir::OpenCLVersionAttr cxxVersion) {
136 return (openCLVersion.getMajor() == 2 && openCLVersion.getMinor() == 0 &&
137 cxxVersion.getMajor() == 1 && cxxVersion.getMinor() == 0) ||
138 (openCLVersion.getMajor() == 3 && openCLVersion.getMinor() == 0 &&
139 cxxVersion.getMajor() == 2021 && cxxVersion.getMinor() == 0);
143 cir::OpenCLVersionAttr cxxVersion) {
144 Attribute openCLAttr =
145 module->getAttr(CIRDialect::getOpenCLVersionAttrName());
147 return module.emitError()
148 << "module attribute '" << CIRDialect::getOpenCLCXXVersionAttrName()
149 << "' requires the companion attribute '"
150 << CIRDialect::getOpenCLVersionAttrName() << "'";
152 auto openCLVersion = dyn_cast<cir::OpenCLVersionAttr>(openCLAttr);
157 return module.emitError("incompatible OpenCL and C++ for OpenCL versions");
163 NamedAttribute attr) {
167 StringRef attrName = attr.getName().getValue();
168 auto version = dyn_cast<cir::OpenCLVersionAttr>(attr.getValue());
170 return op->emitError() <<
"expected " << attrName
171 <<
" to be #cir.cl.version";
174 if (attrName == CIRDialect::getOpenCLCXXVersionAttrName())
180LogicalResult cir::CIRDialect::verifyRegionArgAttribute(
181 Operation *op,
unsigned ,
unsigned ,
182 NamedAttribute attr) {
189LogicalResult cir::CIRDialect::verifyRegionResultAttribute(
190 Operation *op,
unsigned ,
unsigned ,
191 NamedAttribute attr) {
203 cir::OffloadKind expected) {
204 auto attr =
module->getAttrOfType<cir::OffloadKindAttr>(
205 cir::CIRDialect::getOffloadKindAttrName());
207 return module.emitOpError()
208 << "expects '" << cir::CIRDialect::getOffloadKindAttrName()
209 << "' offload kind attribute";
210 if (attr.getValue() != expected)
211 return module.emitOpError()
212 << "expects '" << cir::CIRDialect::getOffloadKindAttrName()
213 << "' value '" << cir::stringifyOffloadKind(expected) << "'";
222 auto container = mlir::dyn_cast<mlir::ModuleOp>(op);
224 return op->emitOpError()
225 <<
"expects '" << cir::CIRDialect::getOffloadContainerAttrName()
226 <<
"' attribute to be attached to '"
227 << mlir::ModuleOp::getOperationName() <<
"'";
229 mlir::Block &body = *container.getBody();
231 return container.emitOpError()
232 <<
"expects host module as the first nested op";
234 auto host = mlir::dyn_cast<mlir::ModuleOp>(body.front());
236 return container.emitOpError()
237 <<
"expects host module as the first nested op";
242 if (std::next(body.begin()) == body.end())
243 return container.emitOpError() <<
"expects at least one device module";
245 for (
auto &op : llvm::drop_begin(body)) {
246 auto module = mlir::dyn_cast<mlir::ModuleOp>(op);
248 return container.emitOpError()
249 <<
"expects only nested builtin.module ops";
257cir::CIRDialect::verifyOperationAttribute(mlir::Operation *op,
258 mlir::NamedAttribute attr) {
259 llvm::StringRef attrName =
attr.getName().getValue();
263 if (attrName == getOffloadContainerAttrName()) {
264 if (!mlir::isa<mlir::UnitAttr>(
attr.getValue()))
265 return op->emitOpError() <<
"expects '" << getOffloadContainerAttrName()
266 <<
"' to be a unit attribute";
273 if (attrName == getOffloadKindAttrName() && !mlir::isa<mlir::ModuleOp>(op))
274 return op->emitOpError() <<
"expects '" << getOffloadKindAttrName()
275 <<
"' attribute to be attached to '"
276 << mlir::ModuleOp::getOperationName() <<
"'";
278 if (attrName == getModuleFramePointerAttrName()) {
279 if (!mlir::isa<mlir::ModuleOp>(op))
280 return op->emitOpError() <<
"expects '" << getModuleFramePointerAttrName()
281 <<
"' attribute to be attached to '"
282 << mlir::ModuleOp::getOperationName() <<
"'";
283 if (!mlir::isa<cir::FramePointerKindAttr>(
attr.getValue()))
284 return op->emitOpError() <<
"expects '" << getModuleFramePointerAttrName()
285 <<
"' to be a #cir.frame_pointer attribute";
291 if (attrName == getCUDADeviceBinaryAttrName()) {
292 auto bytes = mlir::dyn_cast<mlir::StringAttr>(
attr.getValue());
295 if (!arrayTy || arrayTy.getSize() !=
bytes.size())
296 return op->emitOpError()
297 <<
"expects '" << getCUDADeviceBinaryAttrName()
298 <<
"' to be a string typed as an array of its length";
299 return cir::ConstArrayAttr::verify([&] {
return op->emitOpError(); },
316 for (
auto en : llvm::enumerate(keywords)) {
317 if (succeeded(parser.parseOptionalKeyword(en.value())))
324template <
typename Ty>
struct EnumTraits {};
326#define REGISTER_ENUM_TYPE(Ty) \
327 template <> struct EnumTraits<cir::Ty> { \
328 static llvm::StringRef stringify(cir::Ty value) { \
329 return stringify##Ty(value); \
331 static unsigned getMaxEnumVal() { return cir::getMaxEnumValFor##Ty(); } \
342template <
typename EnumTy,
typename RetTy = EnumTy>
345 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
346 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
350 return static_cast<RetTy
>(defaultValue);
351 return static_cast<RetTy
>(index);
355template <
typename EnumTy,
typename RetTy = EnumTy>
358 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
359 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
364 result =
static_cast<RetTy
>(index);
372 Location eLoc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
373 OpBuilder builder(parser.getBuilder().getContext());
378 builder.createBlock(®ion);
380 Block &block = region.back();
382 if (!block.empty() && block.back().hasTrait<OpTrait::IsTerminator>())
386 if (!region.hasOneBlock())
387 return parser.emitError(errLoc,
388 "multi-block region must not omit terminator");
391 builder.setInsertionPointToEnd(&block);
392 cir::YieldOp::create(builder, eLoc);
398 const auto singleNonEmptyBlock = r.hasOneBlock() && !r.back().empty();
399 const auto yieldsNothing = [&r]() {
400 auto y = dyn_cast<cir::YieldOp>(r.back().getTerminator());
401 return y && y.getArgs().empty();
403 return singleNonEmptyBlock && yieldsNothing();
408template <
typename ExpectedProducerOp>
410 StringRef operandName) {
411 Operation *producer = operand.getDefiningOp();
412 if (!producer || !isa<ExpectedProducerOp>(producer))
413 return op->emitOpError()
414 <<
"operand '" << operandName <<
"' must be produced by '"
415 << ExpectedProducerOp::getOperationName() <<
"'";
424 cir::InlineKindAttr &inlineKindAttr) {
426 static constexpr llvm::StringRef keywords[] = {
"no_inline",
"always_inline",
430 llvm::StringRef keyword;
431 if (parser.parseOptionalKeyword(&keyword, keywords).failed()) {
437 auto inlineKindResult = ::cir::symbolizeEnum<::cir::InlineKind>(keyword);
438 if (!inlineKindResult) {
439 return parser.emitError(parser.getCurrentLocation(),
"expected one of [")
441 <<
"] for inlineKind, got: " << keyword;
445 ::cir::InlineKindAttr::get(parser.getContext(), *inlineKindResult);
450 if (inlineKindAttr) {
451 p <<
" " << stringifyInlineKind(inlineKindAttr.getValue());
460 mlir::Region ®ion) {
461 auto regionLoc = parser.getCurrentLocation();
462 if (parser.parseRegion(region))
471 mlir::Region ®ion) {
472 printer.printRegion(region,
477mlir::OptionalParseResult
479 mlir::ptr::MemorySpaceAttrInterface &attr);
482 mlir::ptr::MemorySpaceAttrInterface attr);
488void cir::AllocaOp::build(mlir::OpBuilder &odsBuilder,
489 mlir::OperationState &odsState, mlir::Type addr,
490 llvm::StringRef name, mlir::IntegerAttr alignment) {
491 odsState.addAttribute(getNameAttrName(odsState.name),
492 odsBuilder.getStringAttr(name));
494 odsState.addAttribute(getAlignmentAttrName(odsState.name), alignment);
496 odsState.addTypes(addr);
500 mlir::Value ptr = addr;
501 while (cir::CastOp castOp = ptr.getDefiningOp<cir::CastOp>()) {
502 if (!castOp.isAllocaPreservingCast())
504 ptr = castOp.getSrc();
506 return ptr.getDefiningOp<cir::AllocaOp>();
514 auto ptrTy = mlir::cast<cir::PointerType>(op.getAddr().getType());
515 mlir::Type pointeeTy = ptrTy.getPointee();
517 mlir::Block &body = op.getBody().front();
518 if (body.getNumArguments() != 1)
519 return op.emitOpError(
"body must have exactly one block argument");
521 auto expectedEltPtrTy =
522 mlir::dyn_cast<cir::PointerType>(body.getArgument(0).getType());
523 if (!expectedEltPtrTy)
524 return op.emitOpError(
"block argument must be a !cir.ptr type");
526 if (op.getNumElements()) {
527 auto recTy = mlir::dyn_cast<cir::RecordType>(pointeeTy);
529 return op.emitOpError(
530 "when 'num_elements' is present, 'addr' must be a pointer to a "
531 "!cir.struct or !cir.union type");
533 if (expectedEltPtrTy != ptrTy)
534 return op.emitOpError(
"when 'num_elements' is present, 'addr' type must "
535 "match the block argument type");
537 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(pointeeTy);
539 return op.emitOpError(
540 "when 'num_elements' is absent, 'addr' must be a pointer to a "
543 mlir::Type innerEltTy = arrayTy.getElementType();
544 while (
auto nested = mlir::dyn_cast<cir::ArrayType>(innerEltTy))
545 innerEltTy = nested.getElementType();
547 auto recTy = mlir::dyn_cast<cir::RecordType>(innerEltTy);
549 return op.emitOpError(
"the block argument type must be a pointer to a "
550 "!cir.struct or !cir.union type");
552 if (expectedEltPtrTy.getPointee() != innerEltTy)
553 return op.emitOpError(
554 "block argument pointee type must match the innermost array "
561LogicalResult cir::ArrayCtor::verify() {
565 mlir::Region &partialDtor = getPartialDtor();
566 if (!partialDtor.empty()) {
567 mlir::Block &dtorBlock = partialDtor.front();
568 if (dtorBlock.getNumArguments() != 1)
569 return emitOpError(
"partial_dtor must have exactly one block argument");
571 auto bodyArgTy = getBody().front().getArgument(0).getType();
572 if (dtorBlock.getArgument(0).getType() != bodyArgTy)
573 return emitOpError(
"partial_dtor block argument type must match "
574 "the body block argument type");
584LogicalResult cir::DeleteArrayOp::verify() {
585 if (getDtorMayThrow() && !getElementDtorAttr())
587 "'dtor_may_throw' requires an 'element_dtor' to be present");
596 cir::AssumeBundleKindAttr kindAttr,
597 OperandRange bundleArgs,
598 TypeRange bundleArgTypes) {
599 cir::AssumeBundleKind
kind = kindAttr.getValue();
600 if (
kind == cir::AssumeBundleKind::None)
603 p <<
" " << cir::stringifyAssumeBundleKind(
kind);
604 if (bundleArgs.empty())
608 p.printOperands(bundleArgs);
610 llvm::interleaveComma(bundleArgTypes, p);
615 OpAsmParser &p, cir::AssumeBundleKindAttr &bundleKindAttr,
619 auto loc = p.getCurrentLocation();
620 if (failed(p.parseOptionalKeyword(&keyword))) {
621 bundleKindAttr = cir::AssumeBundleKindAttr::get(
622 p.getContext(), cir::AssumeBundleKind::None);
626 std::optional<cir::AssumeBundleKind> parsedKind =
627 cir::symbolizeAssumeBundleKind(keyword);
629 return p.emitError(loc,
"unknown assume bundle kind '") << keyword <<
"'";
631 bundleKindAttr = cir::AssumeBundleKindAttr::get(p.getContext(), *parsedKind);
633 if (p.parseOptionalLParen())
636 if (p.parseOperandList(bundleArgs) || p.parseColon() ||
637 p.parseTypeList(bundleArgTypes) || p.parseRParen())
643LogicalResult cir::AssumeOp::verify() {
644 cir::AssumeBundleKind
kind = getBundleKind();
645 size_t numArgs = getBundleArgs().size();
647 if (
kind == cir::AssumeBundleKind::None) {
649 return emitOpError(
"unexpected bundle operands for kind 'none'");
654 return emitOpError(
"expected bundle operands for kind '")
655 << cir::stringifyAssumeBundleKind(
kind) <<
"'";
658 case cir::AssumeBundleKind::Align:
659 if (numArgs != 2 && numArgs != 3)
660 return emitOpError(
"align bundle expects 2 or 3 operands");
662 case cir::AssumeBundleKind::SeparateStorage:
664 return emitOpError(
"separate_storage bundle expects 2 operands");
666 case cir::AssumeBundleKind::Dereferenceable:
668 return emitOpError(
"dereferenceable bundle expects 2 operands");
681cir::LocalInitOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
682 cir::GlobalOp global = getReferencedGlobal(symbolTable);
684 return emitOpError(
"'")
685 << getGlobalName() <<
"' does not reference a valid cir.global";
687 if (getTls() && !global.getTlsModel())
688 return emitOpError(
"access to global not marked thread local");
690 if (!global.getDynamicInitGuard().has_value())
691 return emitOpError(
"static_local attribute mismatch");
703 for (mlir::Operation *parent = op->getParentOp(); parent;
704 parent = parent->getParentOp()) {
705 mlir::Region *ctorRegion =
nullptr;
706 if (
auto global = mlir::dyn_cast<cir::GlobalOp>(parent))
707 ctorRegion = &global.getCtorRegion();
708 else if (
auto localInit = mlir::dyn_cast<cir::LocalInitOp>(parent))
709 ctorRegion = &localInit.getCtorRegion();
710 else if (mlir::isa<cir::FuncOp, cir::RegisterExitDtorOp>(parent))
713 return ctorRegion->isAncestor(op->getParentRegion());
718LogicalResult cir::RegisterExitDtorOp::verify() {
719 mlir::Block &body = getBody().front();
720 if (body.without_terminator().empty())
721 return emitOpError(
"body must destroy the object");
722 if (body.getTerminator()->getNumOperands())
723 return emitOpError(
"body must not yield a value");
725 return emitOpError(
"must be in the ctor region of a cir.global or "
731cir::RegisterExitDtorOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
732 auto global = symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(
733 *
this, getObjectAttr());
735 return emitOpError(
"'")
736 << getObject() <<
"' does not reference a valid cir.global";
737 if (!global.getCtorRegion().empty() || !global.getDtorRegion().empty())
738 return emitOpError(
"object must not have ctor or dtor regions");
750void cir::ConditionOp::getSuccessorRegions(
757 if (
auto loopOp = dyn_cast<LoopOpInterface>(getOperation()->getParentOp())) {
758 regions.emplace_back(&loopOp.getBody());
759 if (mlir::Region *cleanup = loopOp.maybeGetCleanup())
760 regions.emplace_back(cleanup);
762 regions.emplace_back(getOperation());
767 auto await = cast<AwaitOp>(getOperation()->getParentOp());
768 regions.emplace_back(&await.getResume());
769 regions.emplace_back(&await.getSuspend());
773cir::ConditionOp::getMutableSuccessorOperands(RegionSuccessor point) {
775 return MutableOperandRange(getOperation(), 0, 0);
779cir::ResumeOp::getMutableSuccessorOperands(RegionSuccessor point) {
781 return MutableOperandRange(getOperation(), 0, 0);
785cir::CoroSuspendPoint::getMutableSuccessorOperands(RegionSuccessor point) {
787 return MutableOperandRange(getOperation(), 0, 0);
790LogicalResult cir::ConditionOp::verify() {
791 if (!isa<LoopOpInterface, AwaitOp>(getOperation()->getParentOp()))
792 return emitOpError(
"condition must be within a conditional region");
800template <
typename LoopOpTy>
802 std::optional<cir::CleanupKind> cleanupKind = op.getCleanupKind();
806 if (cleanupKind.has_value() == op.getCleanup().empty())
807 return op.emitOpError(
"cleanup kind must be present if and only if the "
808 "cleanup region is non-empty");
813 if (cleanupKind == cir::CleanupKind::EH)
814 return op.emitOpError(
"loop cleanup kind must be 'normal' or 'all', "
829 mlir::Attribute attrType) {
830 if (isa<cir::ConstPtrAttr>(attrType)) {
831 if (!mlir::isa<cir::PointerType>(opType))
832 return op->emitOpError(
833 "pointer constant initializing a non-pointer type");
837 if (isa<cir::DataMemberAttr, cir::DataMemberOffsetAttr, cir::MethodAttr>(
844 if (isa<cir::ZeroAttr>(attrType)) {
845 if (isa<
cir::RecordType, cir::ArrayType, cir::MatrixType, cir::VectorType,
846 cir::ComplexType>(opType))
848 return op->emitOpError(
849 "zero expects struct, array, vector, or complex type");
852 if (mlir::isa<cir::UndefAttr>(attrType)) {
853 if (!mlir::isa<cir::VoidType>(opType))
855 return op->emitOpError(
"undef expects non-void type");
858 if (mlir::isa<cir::BoolAttr>(attrType)) {
859 if (!mlir::isa<cir::BoolType>(opType))
860 return op->emitOpError(
"result type (")
861 << opType <<
") must be '!cir.bool' for '" << attrType <<
"'";
865 if (mlir::isa<cir::IntAttr, cir::FPAttr>(attrType)) {
866 auto at = cast<TypedAttr>(attrType);
867 if (at.getType() != opType) {
868 return op->emitOpError(
"result type (")
869 << opType <<
") does not match value type (" << at.getType()
875 if (mlir::isa<cir::BlockAddrDiffAttr, cir::BlockAddrInfoAttr,
876 cir::ConstArrayAttr, cir::ConstVectorAttr,
877 cir::ConstComplexAttr, cir::ConstRecordAttr,
878 cir::GlobalOffsetAttr, cir::GlobalViewAttr, cir::PoisonAttr,
879 cir::TypeInfoAttr, cir::VTableAttr>(attrType))
882 assert(isa<TypedAttr>(attrType) &&
"What else could we be looking at here?");
883 return op->emitOpError(
"global with type ")
884 << cast<TypedAttr>(attrType).getType() <<
" not yet supported";
887LogicalResult cir::ConstantOp::verify() {
894OpFoldResult cir::ConstantOp::fold(FoldAdaptor ) {
904 case cir::CastKind::floating:
905 case cir::CastKind::int_to_float:
906 case cir::CastKind::float_to_int:
907 case cir::CastKind::float_to_bool:
908 case cir::CastKind::bool_to_float:
909 case cir::CastKind::float_to_complex:
910 case cir::CastKind::float_complex_to_real:
911 case cir::CastKind::float_complex_to_bool:
912 case cir::CastKind::float_complex:
913 case cir::CastKind::float_complex_to_int_complex:
914 case cir::CastKind::int_complex_to_float_complex:
921LogicalResult cir::CastOp::verify() {
922 mlir::Type resType =
getType();
923 mlir::Type srcType = getSrc().getType();
928 <<
"'fenv' is only valid for floating-point cast kinds";
932 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
933 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
934 if (srcPtrTy && resPtrTy && (
kind != cir::CastKind::address_space))
935 if (srcPtrTy.getAddrSpace() != resPtrTy.getAddrSpace()) {
936 return emitOpError() <<
"result type address space does not match the "
937 "address space of the operand";
940 auto srcVTy = mlir::dyn_cast<cir::VectorType>(srcType);
941 auto resVTy = mlir::dyn_cast<cir::VectorType>(resType);
942 if (srcVTy && resVTy) {
943 if ((
kind == cir::CastKind::int_to_float ||
944 kind == cir::CastKind::float_to_int) &&
945 srcVTy.getSize() != resVTy.getSize()) {
947 <<
"vector float-to-int and int-to-float casts require "
948 "source and destination vectors to have the same number of "
953 srcType = srcVTy.getElementType();
954 resType = resVTy.getElementType();
958 case cir::CastKind::int_to_bool: {
959 if (!mlir::isa<cir::BoolType>(resType))
960 return emitOpError() <<
"requires !cir.bool type for result";
961 if (!mlir::isa<cir::IntType>(srcType))
962 return emitOpError() <<
"requires !cir.int type for source";
965 case cir::CastKind::ptr_to_bool: {
966 if (!mlir::isa<cir::BoolType>(resType))
967 return emitOpError() <<
"requires !cir.bool type for result";
968 if (!mlir::isa<cir::PointerType>(srcType))
969 return emitOpError() <<
"requires !cir.ptr type for source";
972 case cir::CastKind::integral: {
973 if (!mlir::isa<cir::IntType>(resType))
974 return emitOpError() <<
"requires !cir.int type for result";
975 if (!mlir::isa<cir::IntType>(srcType))
976 return emitOpError() <<
"requires !cir.int type for source";
979 case cir::CastKind::array_to_ptrdecay: {
980 const auto arrayPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
981 const auto flatPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
982 if (!arrayPtrTy || !flatPtrTy)
983 return emitOpError() <<
"requires !cir.ptr type for source and result";
988 case cir::CastKind::bitcast: {
990 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
991 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
993 if (srcPtrTy && resPtrTy) {
999 case cir::CastKind::floating: {
1000 if (!mlir::isa<cir::FPTypeInterface>(srcType) ||
1001 !mlir::isa<cir::FPTypeInterface>(resType))
1002 return emitOpError() <<
"requires !cir.float type for source and result";
1005 case cir::CastKind::float_to_int: {
1006 if (!mlir::isa<cir::FPTypeInterface>(srcType))
1007 return emitOpError() <<
"requires !cir.float type for source";
1008 if (!mlir::dyn_cast<cir::IntType>(resType))
1009 return emitOpError() <<
"requires !cir.int type for result";
1012 case cir::CastKind::int_to_ptr: {
1013 if (!mlir::dyn_cast<cir::IntType>(srcType))
1014 return emitOpError() <<
"requires !cir.int type for source";
1015 if (!mlir::dyn_cast<cir::PointerType>(resType))
1016 return emitOpError() <<
"requires !cir.ptr type for result";
1019 case cir::CastKind::ptr_to_int: {
1020 if (!mlir::dyn_cast<cir::PointerType>(srcType))
1021 return emitOpError() <<
"requires !cir.ptr type for source";
1022 if (!mlir::dyn_cast<cir::IntType>(resType))
1023 return emitOpError() <<
"requires !cir.int type for result";
1026 case cir::CastKind::float_to_bool: {
1027 if (!mlir::isa<cir::FPTypeInterface>(srcType))
1028 return emitOpError() <<
"requires !cir.float type for source";
1029 if (!mlir::isa<cir::BoolType>(resType))
1030 return emitOpError() <<
"requires !cir.bool type for result";
1033 case cir::CastKind::bool_to_int: {
1034 if (!mlir::isa<cir::BoolType>(srcType))
1035 return emitOpError() <<
"requires !cir.bool type for source";
1036 if (!mlir::isa<cir::IntType>(resType))
1037 return emitOpError() <<
"requires !cir.int type for result";
1040 case cir::CastKind::int_to_float: {
1041 if (!mlir::isa<cir::IntType>(srcType))
1042 return emitOpError() <<
"requires !cir.int type for source";
1043 if (!mlir::isa<cir::FPTypeInterface>(resType))
1044 return emitOpError() <<
"requires !cir.float type for result";
1047 case cir::CastKind::bool_to_float: {
1048 if (!mlir::isa<cir::BoolType>(srcType))
1049 return emitOpError() <<
"requires !cir.bool type for source";
1050 if (!mlir::isa<cir::FPTypeInterface>(resType))
1051 return emitOpError() <<
"requires !cir.float type for result";
1054 case cir::CastKind::address_space: {
1055 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
1056 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
1057 if (!srcPtrTy || !resPtrTy)
1058 return emitOpError() <<
"requires !cir.ptr type for source and result";
1059 if (srcPtrTy.getPointee() != resPtrTy.getPointee())
1060 return emitOpError() <<
"requires two types differ in addrspace only";
1063 case cir::CastKind::float_to_complex: {
1064 if (!mlir::isa<cir::FPTypeInterface>(srcType))
1065 return emitOpError() <<
"requires !cir.float type for source";
1066 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
1068 return emitOpError() <<
"requires !cir.complex type for result";
1069 if (srcType != resComplexTy.getElementType())
1070 return emitOpError() <<
"requires source type match result element type";
1073 case cir::CastKind::int_to_complex: {
1074 if (!mlir::isa<cir::IntType>(srcType))
1075 return emitOpError() <<
"requires !cir.int type for source";
1076 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
1078 return emitOpError() <<
"requires !cir.complex type for result";
1079 if (srcType != resComplexTy.getElementType())
1080 return emitOpError() <<
"requires source type match result element type";
1083 case cir::CastKind::float_complex_to_real: {
1084 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1086 return emitOpError() <<
"requires !cir.complex type for source";
1087 if (!mlir::isa<cir::FPTypeInterface>(resType))
1088 return emitOpError() <<
"requires !cir.float type for result";
1089 if (srcComplexTy.getElementType() != resType)
1090 return emitOpError() <<
"requires source element type match result type";
1093 case cir::CastKind::int_complex_to_real: {
1094 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1096 return emitOpError() <<
"requires !cir.complex type for source";
1097 if (!mlir::isa<cir::IntType>(resType))
1098 return emitOpError() <<
"requires !cir.int type for result";
1099 if (srcComplexTy.getElementType() != resType)
1100 return emitOpError() <<
"requires source element type match result type";
1103 case cir::CastKind::float_complex_to_bool: {
1104 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1105 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
1106 return emitOpError()
1107 <<
"requires floating point !cir.complex type for source";
1108 if (!mlir::isa<cir::BoolType>(resType))
1109 return emitOpError() <<
"requires !cir.bool type for result";
1112 case cir::CastKind::int_complex_to_bool: {
1113 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1114 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
1115 return emitOpError()
1116 <<
"requires floating point !cir.complex type for source";
1117 if (!mlir::isa<cir::BoolType>(resType))
1118 return emitOpError() <<
"requires !cir.bool type for result";
1121 case cir::CastKind::float_complex: {
1122 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1123 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
1124 return emitOpError()
1125 <<
"requires floating point !cir.complex type for source";
1126 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
1127 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
1128 return emitOpError()
1129 <<
"requires floating point !cir.complex type for result";
1132 case cir::CastKind::float_complex_to_int_complex: {
1133 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1134 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
1135 return emitOpError()
1136 <<
"requires floating point !cir.complex type for source";
1137 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
1138 if (!resComplexTy || !resComplexTy.isIntegerComplex())
1139 return emitOpError() <<
"requires integer !cir.complex type for result";
1142 case cir::CastKind::int_complex: {
1143 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1144 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
1145 return emitOpError() <<
"requires integer !cir.complex type for source";
1146 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
1147 if (!resComplexTy || !resComplexTy.isIntegerComplex())
1148 return emitOpError() <<
"requires integer !cir.complex type for result";
1151 case cir::CastKind::int_complex_to_float_complex: {
1152 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
1153 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
1154 return emitOpError() <<
"requires integer !cir.complex type for source";
1155 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
1156 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
1157 return emitOpError()
1158 <<
"requires floating point !cir.complex type for result";
1161 case cir::CastKind::member_ptr_to_bool: {
1162 if (!mlir::isa<cir::DataMemberType, cir::MethodType>(srcType))
1163 return emitOpError()
1164 <<
"requires !cir.data_member or !cir.method type for source";
1165 if (!mlir::isa<cir::BoolType>(resType))
1166 return emitOpError() <<
"requires !cir.bool type for result";
1170 llvm_unreachable(
"Unknown CastOp kind?");
1174 auto kind = op.getKind();
1175 return kind == cir::CastKind::bool_to_int ||
1176 kind == cir::CastKind::int_to_bool ||
kind == cir::CastKind::integral;
1180 const auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty);
1181 return ptrTy && mlir::isa<cir::FuncType>(ptrTy.getPointee());
1185 cir::CastOp head = op, tail = op;
1191 op = head.getSrc().getDefiningOp<cir::CastOp>();
1197 if (head.getKind() == cir::CastKind::bool_to_int &&
1198 tail.getKind() == cir::CastKind::int_to_bool)
1199 return head.getSrc();
1204 if (head.getKind() == cir::CastKind::int_to_bool &&
1205 tail.getKind() == cir::CastKind::int_to_bool)
1206 return head.getResult();
1214 if (tail.getKind() == cir::CastKind::bitcast) {
1215 auto *inner = tail.getSrc().getDefiningOp();
1217 auto innerCast = mlir::dyn_cast<cir::CastOp>(inner);
1218 if (innerCast && innerCast.getKind() == cir::CastKind::bitcast &&
1219 innerCast.getSrc().getType() == tail.getType() &&
1220 innerCast.getType() == tail.getSrc().getType()) {
1221 return innerCast.getSrc();
1229OpFoldResult cir::CastOp::fold(FoldAdaptor adaptor) {
1230 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getSrc())) {
1232 return cir::PoisonAttr::get(getContext(),
getType());
1236 if (mlir::isa_and_present<cir::UndefAttr>(adaptor.getSrc()))
1237 return cir::UndefAttr::get(
getType());
1241 case cir::CastKind::integral: {
1243 auto foldOrder = getSrc().getDefiningOp()->fold(foldResults);
1244 if (foldOrder.succeeded() && mlir::isa<mlir::Attribute>(foldResults[0]))
1245 return mlir::cast<mlir::Attribute>(foldResults[0]);
1248 case cir::CastKind::bitcast:
1249 case cir::CastKind::address_space:
1250 case cir::CastKind::float_complex:
1251 case cir::CastKind::int_complex: {
1265 if (
auto srcConst = getSrc().getDefiningOp<cir::ConstantOp>()) {
1267 case cir::CastKind::integral: {
1268 mlir::Type srcTy = getSrc().getType();
1270 assert(mlir::isa<cir::VectorType>(srcTy) ==
1271 mlir::isa<cir::VectorType>(
getType()));
1272 if (mlir::isa<cir::VectorType>(srcTy))
1275 auto srcIntTy = mlir::cast<cir::IntType>(srcTy);
1276 auto dstIntTy = mlir::cast<cir::IntType>(
getType());
1277 auto constIntAttr = srcConst.getValueAttr<cir::IntAttr>();
1281 APInt srcValue = constIntAttr.getValue();
1282 APInt newVal = srcIntTy.isSigned()
1283 ? srcValue.sextOrTrunc(dstIntTy.getWidth())
1284 : srcValue.zextOrTrunc(dstIntTy.getWidth());
1285 return cir::IntAttr::get(dstIntTy, newVal);
1298LogicalResult cir::BuiltinIntCastOp::verify() {
1299 mlir::Type srcType = getSrc().getType();
1300 mlir::Type resType =
getType();
1302 auto srcCirInt = mlir::dyn_cast<cir::IntType>(srcType);
1303 auto resCirInt = mlir::dyn_cast<cir::IntType>(resType);
1307 if (
static_cast<bool>(srcCirInt) ==
static_cast<bool>(resCirInt))
1308 return emitOpError()
1309 <<
"requires exactly one '!cir.int' operand or result; the other "
1310 "must be a builtin integer or 'index' type";
1312 mlir::Type
builtinType = srcCirInt ? resType : srcType;
1313 if (!mlir::isa<mlir::IntegerType, mlir::IndexType>(builtinType))
1314 return emitOpError() <<
"requires a builtin integer or 'index' type on the "
1319 if (
auto builtinInt = mlir::dyn_cast<mlir::IntegerType>(builtinType)) {
1320 cir::IntType cirInt = srcCirInt ? srcCirInt : resCirInt;
1321 if (cirInt.getWidth() != builtinInt.getWidth())
1322 return emitOpError()
1323 <<
"requires the CIR and builtin integer types to have the same "
1324 "width; use 'cir.cast' for width conversions";
1330OpFoldResult cir::BuiltinIntCastOp::fold(FoldAdaptor adaptor) {
1333 if (
auto inner = getSrc().getDefiningOp<cir::BuiltinIntCastOp>())
1334 if (inner.getSrc().getType() ==
getType())
1335 return inner.getSrc();
1343mlir::OperandRange cir::CallOp::getArgOperands() {
1345 return getArgs().drop_front(1);
1349mlir::MutableOperandRange cir::CallOp::getArgOperandsMutable() {
1350 mlir::MutableOperandRange args = getArgsMutable();
1352 return args.slice(1, args.size() - 1);
1356mlir::Value cir::CallOp::getIndirectCall() {
1357 assert(isIndirect());
1358 return getOperand(0);
1362Value cir::CallOp::getArgOperand(
unsigned i) {
1365 return getOperand(i);
1369unsigned cir::CallOp::getNumArgOperands() {
1371 return this->getOperation()->getNumOperands() - 1;
1372 return this->getOperation()->getNumOperands();
1375static mlir::ParseResult
1377 mlir::OperationState &result) {
1378 mlir::Block *normalDestSuccessor;
1379 if (parser.parseSuccessor(normalDestSuccessor))
1380 return mlir::failure();
1382 if (parser.parseComma())
1383 return mlir::failure();
1385 mlir::Block *unwindDestSuccessor;
1386 if (parser.parseSuccessor(unwindDestSuccessor))
1387 return mlir::failure();
1389 result.addSuccessors(normalDestSuccessor);
1390 result.addSuccessors(unwindDestSuccessor);
1391 return mlir::success();
1400 const mlir::NamedAttrList &attrs) {
1401 if (mlir::Attribute effects =
1402 attrs.get(CIRDialect::getMemoryEffectsAttrName()))
1403 if (!mlir::isa<cir::MemoryEffectsAttr>(effects))
1404 return parser.emitError(loc,
"attribute '")
1405 << CIRDialect::getMemoryEffectsAttrName()
1406 <<
"' must be a #cir.memory_effects attribute";
1408 if (mlir::Attribute uwtable = attrs.get(CIRDialect::getUwtableAttrName()))
1409 if (!mlir::isa<cir::UnwindTableKindAttr>(uwtable))
1410 return parser.emitError(loc,
"attribute '")
1411 << CIRDialect::getUwtableAttrName()
1412 <<
"' must be a #cir.uwtable attribute";
1414 if (mlir::Attribute framePointer =
1415 attrs.get(CIRDialect::getFramePointerAttrName()))
1416 if (!mlir::isa<cir::FramePointerKindAttr>(framePointer))
1417 return parser.emitError(loc,
"attribute '")
1418 << CIRDialect::getFramePointerAttrName()
1419 <<
"' must be a #cir.frame_pointer attribute";
1421 for (llvm::StringRef name :
1422 {CIRDialect::getNoUnwindAttrName(), CIRDialect::getWillReturnAttrName(),
1423 CIRDialect::getMustProgressAttrName()})
1424 if (mlir::Attribute flag = attrs.get(name))
1425 if (!mlir::isa<mlir::UnitAttr>(flag))
1426 return parser.emitError(loc,
"attribute '")
1427 << name <<
"' must be a unit attribute";
1429 return mlir::success();
1433 mlir::OperationState &result,
1434 bool hasDestinationBlocks =
false) {
1437 mlir::FlatSymbolRefAttr calleeAttr;
1441 .parseOptionalAttribute(calleeAttr, CIRDialect::getCalleeAttrName(),
1444 OpAsmParser::UnresolvedOperand indirectVal;
1446 if (parser.parseOperand(indirectVal).failed())
1448 ops.push_back(indirectVal);
1451 if (parser.parseLParen())
1452 return mlir::failure();
1454 opsLoc = parser.getCurrentLocation();
1455 if (parser.parseOperandList(ops))
1456 return mlir::failure();
1457 if (parser.parseRParen())
1458 return mlir::failure();
1460 if (hasDestinationBlocks &&
1462 return ::mlir::failure();
1465 if (parser.parseOptionalKeyword(
"cc").succeeded()) {
1466 cir::CallingConv callingConv;
1467 if (parser.parseLParen().failed())
1470 return parser.emitError(parser.getCurrentLocation(),
1471 "unknown calling convention");
1472 if (parser.parseRParen().failed())
1474 result.addAttribute(
1475 CIRDialect::getCallingConvAttrName(),
1476 cir::CallingConvAttr::get(parser.getContext(), callingConv));
1479 if (parser.parseOptionalKeyword(
"musttail").succeeded())
1480 result.addAttribute(CIRDialect::getMustTailAttrName(),
1481 mlir::UnitAttr::get(parser.getContext()));
1483 if (parser.parseOptionalKeyword(
"nothrow").succeeded())
1484 result.addAttribute(CIRDialect::getNoThrowAttrName(),
1485 mlir::UnitAttr::get(parser.getContext()));
1487 if (parser.parseOptionalKeyword(
"nounwind").succeeded())
1488 result.addAttribute(CIRDialect::getNoUnwindAttrName(),
1489 mlir::UnitAttr::get(parser.getContext()));
1491 if (parser.parseOptionalKeyword(
"willreturn").succeeded())
1492 result.addAttribute(CIRDialect::getWillReturnAttrName(),
1493 mlir::UnitAttr::get(parser.getContext()));
1495 llvm::SMLoc attrsLoc = parser.getCurrentLocation();
1496 if (parser.parseOptionalAttrDict(result.attributes))
1497 return ::mlir::failure();
1500 return ::mlir::failure();
1502 if (parser.parseColon())
1503 return ::mlir::failure();
1509 if (call_interface_impl::parseFunctionSignature(parser, argTypes, argAttrs,
1510 resultTypes, resultAttrs))
1511 return mlir::failure();
1513 if (resultTypes.size() > 1 || resultAttrs.size() > 1)
1514 return parser.emitError(
1515 parser.getCurrentLocation(),
1516 "functions with multiple return types are not supported");
1518 result.addTypes(resultTypes);
1520 if (parser.resolveOperands(ops, argTypes, opsLoc, result.operands))
1521 return mlir::failure();
1523 if (!resultAttrs.empty() && resultAttrs[0])
1524 result.addAttribute(
1525 CIRDialect::getResAttrsAttrName(),
1526 mlir::ArrayAttr::get(parser.getContext(), {resultAttrs[0]}));
1531 bool argAttrsEmpty =
true;
1533 llvm::transform(argAttrs, std::back_inserter(convertedArgAttrs),
1534 [&](DictionaryAttr da) -> mlir::Attribute {
1536 argAttrsEmpty =
false;
1540 if (!argAttrsEmpty) {
1545 argAttrsRef = argAttrsRef.drop_front();
1547 result.addAttribute(CIRDialect::getArgAttrsAttrName(),
1548 mlir::ArrayAttr::get(parser.getContext(), argAttrsRef));
1551 return mlir::success();
1555 mlir::FlatSymbolRefAttr calleeSym,
1556 mlir::Value indirectCallee,
1557 mlir::OpAsmPrinter &printer,
bool isNothrow,
1558 ArrayAttr argAttrs, ArrayAttr resAttrs,
1559 mlir::Block *normalDest =
nullptr,
1560 mlir::Block *unwindDest =
nullptr) {
1563 auto callLikeOp = mlir::cast<cir::CIRCallOpInterface>(op);
1564 auto ops = callLikeOp.getArgOperands();
1568 printer.printAttributeWithoutType(calleeSym);
1571 assert(indirectCallee);
1572 printer << indirectCallee;
1575 printer <<
"(" << ops <<
")";
1578 assert(unwindDest &&
"expected two successors");
1579 auto tryCall = cast<cir::TryCallOp>(op);
1580 printer <<
' ' << tryCall.getNormalDest();
1583 printer << tryCall.getUnwindDest();
1586 cir::CallingConv callingConv = callLikeOp.getCallingConv();
1587 if (callingConv != cir::CallingConv::C)
1588 printer <<
" cc(" << stringifyCallingConv(callingConv) <<
")";
1590 if (op->hasAttr(CIRDialect::getMustTailAttrName()))
1591 printer <<
" musttail";
1594 printer <<
" nothrow";
1596 if (op->hasAttr(CIRDialect::getNoUnwindAttrName()))
1597 printer <<
" nounwind";
1599 if (op->hasAttr(CIRDialect::getWillReturnAttrName()))
1600 printer <<
" willreturn";
1602 llvm::StringRef elidedAttrs[] = {
1603 CIRDialect::getCalleeAttrName(),
1604 CIRDialect::getCallingConvAttrName(),
1605 CIRDialect::getMustTailAttrName(),
1606 CIRDialect::getNoThrowAttrName(),
1607 CIRDialect::getNoUnwindAttrName(),
1608 CIRDialect::getWillReturnAttrName(),
1609 CIRDialect::getOperandSegmentSizesAttrName(),
1616 for (mlir::NamedAttribute attr : op->getDiscardableAttrs())
1617 if (!llvm::is_contained(elidedAttrs, attr.getName()))
1618 attrs.push_back(attr);
1619 op->getName().walkInherentAttrs(op, [&](llvm::StringRef name,
1620 mlir::Attribute &attr) {
1621 if (!llvm::is_contained(elidedAttrs, name))
1622 attrs.emplace_back(mlir::StringAttr::get(op->getContext(), name), attr);
1624 llvm::sort(attrs, [](mlir::NamedAttribute lhs, mlir::NamedAttribute rhs) {
1625 return lhs.getName().strref() < rhs.getName().strref();
1627 printer.printOptionalAttrDict(attrs);
1629 if (calleeSym || !argAttrs) {
1630 call_interface_impl::printFunctionSignature(
1631 printer, op->getOperands().getTypes(), argAttrs,
1632 false, op->getResultTypes(), resAttrs);
1640 shimmedArgAttrs.push_back(mlir::DictionaryAttr::get(op->getContext(), {}));
1641 shimmedArgAttrs.append(argAttrs.begin(), argAttrs.end());
1642 call_interface_impl::printFunctionSignature(
1643 printer, op->getOperands().getTypes(),
1644 mlir::ArrayAttr::get(op->getContext(), shimmedArgAttrs),
1645 false, op->getResultTypes(), resAttrs);
1649mlir::ParseResult cir::CallOp::parse(mlir::OpAsmParser &parser,
1650 mlir::OperationState &result) {
1654void cir::CallOp::print(mlir::OpAsmPrinter &p) {
1655 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
1656 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
1657 getArgAttrsAttr(), getResAttrsAttr());
1662 SymbolTableCollection &symbolTable) {
1663 auto callIf = cast<cir::CIRCallOpInterface>(op);
1667 cir::FuncType fnType;
1668 bool hasPrototype =
true;
1670 op->getAttrOfType<FlatSymbolRefAttr>(CIRDialect::getCalleeAttrName());
1672 if (op->getNumOperands() == 0)
1673 return op->emitOpError(
"indirect call requires a callee operand");
1674 mlir::Type calleeTy = callIf.getIndirectCall().getType();
1675 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(calleeTy))
1676 fnType = mlir::dyn_cast<cir::FuncType>(ptrTy.getPointee());
1678 return op->emitOpError()
1679 <<
"indirect callee must be a pointer to a function, but has type "
1682 auto fn = symbolTable.lookupNearestSymbolFrom<cir::FuncOp>(op, fnAttr);
1684 return op->emitOpError() <<
"'" << fnAttr.getValue()
1685 <<
"' does not reference a valid function";
1686 fnType = fn.getFunctionType();
1687 hasPrototype = !fn.getNoProto();
1693 unsigned numCallOperands = callIf.getNumArgOperands();
1694 unsigned numFnOpOperands = fnType.getNumInputs();
1696 if (!fnType.isVarArg() && numCallOperands != numFnOpOperands)
1697 return op->emitOpError(
"incorrect number of operands for callee");
1698 if (fnType.isVarArg() && numCallOperands < numFnOpOperands)
1699 return op->emitOpError(
"too few operands for callee");
1701 for (
unsigned i = 0, e = numFnOpOperands; i != e; ++i)
1702 if (callIf.getArgOperand(i).getType() != fnType.getInput(i))
1703 return op->emitOpError(
"operand type mismatch: expected operand type ")
1704 << fnType.getInput(i) <<
", but provided "
1705 << callIf.getArgOperand(i).getType() <<
" for operand number "
1712 if (fnType.hasVoidReturn() && op->getNumResults() != 0)
1713 return op->emitOpError(
"callee returns void but call has results");
1716 if (!fnType.hasVoidReturn() && op->getNumResults() != 1)
1717 return op->emitOpError(
"incorrect number of results for callee");
1720 if (!fnType.hasVoidReturn() &&
1721 op->getResultTypes().front() != fnType.getReturnType()) {
1722 return op->emitOpError(
"result type mismatch: expected ")
1723 << fnType.getReturnType() <<
", but provided "
1724 << op->getResult(0).getType();
1727 return mlir::success();
1731cir::CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1739mlir::OperandRange cir::TryCallOp::getArgOperands() {
1741 return getArgs().drop_front(1);
1745mlir::MutableOperandRange cir::TryCallOp::getArgOperandsMutable() {
1746 mlir::MutableOperandRange args = getArgsMutable();
1748 return args.slice(1, args.size() - 1);
1752mlir::Value cir::TryCallOp::getIndirectCall() {
1753 assert(isIndirect());
1754 return getOperand(0);
1758Value cir::TryCallOp::getArgOperand(
unsigned i) {
1761 return getOperand(i);
1765unsigned cir::TryCallOp::getNumArgOperands() {
1767 return this->getOperation()->getNumOperands() - 1;
1768 return this->getOperation()->getNumOperands();
1772cir::TryCallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1776mlir::ParseResult cir::TryCallOp::parse(mlir::OpAsmParser &parser,
1777 mlir::OperationState &result) {
1781void cir::TryCallOp::print(::mlir::OpAsmPrinter &p) {
1782 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
1783 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
1784 getArgAttrsAttr(), getResAttrsAttr(), getNormalDest(),
1793 cir::FuncOp function) {
1795 if (op.getNumOperands() > 1)
1796 return op.emitOpError() <<
"expects at most 1 return operand";
1799 auto expectedTy = function.getFunctionType().getReturnType();
1801 (op.getNumOperands() == 0 ? cir::VoidType::get(op.getContext())
1802 : op.getOperand(0).getType());
1803 if (actualTy != expectedTy)
1804 return op.emitOpError() <<
"returns " << actualTy
1805 <<
" but enclosing function returns " << expectedTy;
1807 return mlir::success();
1810mlir::LogicalResult cir::ReturnOp::verify() {
1813 auto *fnOp = getOperation()->getParentOp();
1814 while (!isa<cir::FuncOp>(fnOp))
1815 fnOp = fnOp->getParentOp();
1828ParseResult cir::IfOp::parse(OpAsmParser &parser, OperationState &result) {
1830 result.regions.reserve(2);
1831 Region *thenRegion = result.addRegion();
1832 Region *elseRegion = result.addRegion();
1834 mlir::Builder &builder = parser.getBuilder();
1835 OpAsmParser::UnresolvedOperand cond;
1836 Type boolType = cir::BoolType::get(builder.getContext());
1838 if (parser.parseOperand(cond) ||
1839 parser.resolveOperand(cond, boolType, result.operands))
1843 mlir::SMLoc parseThenLoc = parser.getCurrentLocation();
1844 if (parser.parseRegion(*thenRegion, {}, {}))
1851 if (!parser.parseOptionalKeyword(
"else")) {
1852 mlir::SMLoc parseElseLoc = parser.getCurrentLocation();
1853 if (parser.parseRegion(*elseRegion, {}, {}))
1860 if (parser.parseOptionalAttrDict(result.attributes))
1865void cir::IfOp::print(OpAsmPrinter &p) {
1866 p <<
" " << getCondition() <<
" ";
1867 mlir::Region &thenRegion = this->getThenRegion();
1868 p.printRegion(thenRegion,
1873 mlir::Region &elseRegion = this->getElseRegion();
1874 if (!elseRegion.empty()) {
1876 p.printRegion(elseRegion,
1881 p.printOptionalAttrDict(
1882 getOperation()->getDiscardableAttrDictionary().getValue());
1888 cir::YieldOp::create(builder, loc);
1896void cir::IfOp::getSuccessorRegions(mlir::RegionBranchPoint point,
1897 SmallVectorImpl<RegionSuccessor> ®ions) {
1899 if (!point.isParent()) {
1900 regions.emplace_back(getOperation());
1905 Region *elseRegion = &this->getElseRegion();
1906 if (elseRegion->empty())
1907 elseRegion =
nullptr;
1910 regions.push_back(RegionSuccessor(&getThenRegion()));
1912 regions.push_back(RegionSuccessor(elseRegion));
1914 regions.emplace_back(getOperation());
1917void cir::IfOp::build(OpBuilder &builder, OperationState &result,
Value cond,
1920 assert(thenBuilder &&
"the builder callback for 'then' must be present");
1921 result.addOperands(cond);
1923 OpBuilder::InsertionGuard guard(builder);
1924 Region *thenRegion = result.addRegion();
1925 builder.createBlock(thenRegion);
1926 thenBuilder(builder, result.location);
1928 Region *elseRegion = result.addRegion();
1929 if (!withElseRegion)
1932 builder.createBlock(elseRegion);
1933 elseBuilder(builder, result.location);
1940void cir::ScopeOp::build(
1941 OpBuilder &builder, OperationState &result,
1942 function_ref<
void(OpBuilder &, Type &, Location)> scopeBuilder) {
1943 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1945 OpBuilder::InsertionGuard guard(builder);
1946 Region *scopeRegion = result.addRegion();
1947 builder.createBlock(scopeRegion);
1951 scopeBuilder(builder, yieldTy, result.location);
1954 result.addTypes(TypeRange{yieldTy});
1957void cir::ScopeOp::build(
1958 OpBuilder &builder, OperationState &result,
1959 function_ref<
void(OpBuilder &, Location)> scopeBuilder) {
1960 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1961 OpBuilder::InsertionGuard guard(builder);
1962 Region *scopeRegion = result.addRegion();
1963 builder.createBlock(scopeRegion);
1965 scopeBuilder(builder, result.location);
1968LogicalResult cir::ScopeOp::verify() {
1969 if (getRegion().empty()) {
1970 return emitOpError() <<
"cir.scope must not be empty since it should "
1971 "include at least an implicit cir.yield ";
1974 mlir::Block &lastBlock = getRegion().back();
1975 if (lastBlock.empty() || !lastBlock.mightHaveTerminator() ||
1976 !lastBlock.getTerminator()->hasTrait<OpTrait::IsTerminator>())
1977 return emitOpError() <<
"last block of cir.scope must be terminated";
1981LogicalResult cir::ScopeOp::fold(FoldAdaptor ,
1982 SmallVectorImpl<OpFoldResult> &results) {
1984 if (!getRegion().hasOneBlock())
1986 Block &block = getRegion().front();
1987 if (block.getOperations().size() != 1)
1990 auto yield = dyn_cast<cir::YieldOp>(block.front());
1995 if (getNumResults() != 1 || yield.getNumOperands() != 1)
1998 results.push_back(yield.getOperand(0));
2007 for (mlir::Block &block : cleanupRegion) {
2008 for (mlir::Operation &op : block) {
2009 if (isa<cir::YieldOp, cir::LifetimeEndOp, cir::StackRestoreOp>(op))
2012 auto loadOp = dyn_cast<cir::LoadOp>(op);
2013 if (loadOp && loadOp.getResult().hasOneUse() &&
2014 isa<cir::StackRestoreOp>(*loadOp.getResult().getUsers().begin()))
2022LogicalResult cir::CleanupScopeOp::verify() {
2026 cir::CallOp mustTailCall;
2027 getBodyRegion().walk([&](cir::CallOp callOp) {
2028 if (!callOp.getMusttail())
2029 return WalkResult::advance();
2030 mustTailCall = callOp;
2031 return WalkResult::interrupt();
2039 InFlightDiagnostic diag =
2040 emitOpError(
"cleanup is not redundant before a return, so it cannot be "
2041 "skipped by a musttail call");
2042 diag.attachNote(mustTailCall.getLoc()) <<
"musttail call is here";
2046void cir::CleanupScopeOp::getSuccessorRegions(
2047 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
2049 if (point.isParent()) {
2050 regions.emplace_back(&getBodyRegion());
2054 mlir::Operation *term = point.getTerminatorPredecessorOrNull();
2055 assert(term &&
"expected a terminator predecessor");
2057 if (term->getParentRegion() == &getBodyRegion()) {
2060 cir::CleanupKindAttr
kind = getCleanupKindAttr();
2061 if (isa<cir::ResumeOp>(term) ?
kind.isEH() :
kind.isNormal()) {
2062 regions.emplace_back(&getCleanupRegion());
2072 regions.emplace_back(getOperation());
2075LogicalResult cir::CleanupScopeOp::canonicalize(CleanupScopeOp op,
2076 PatternRewriter &rewriter) {
2077 auto isRegionTrivial = [](Region ®ion) {
2078 assert(!region.empty() &&
"CleanupScopeOp regions must not be empty");
2079 if (!region.hasOneBlock())
2081 Block &block = llvm::getSingleElement(region);
2082 return llvm::hasSingleElement(block) &&
2083 isa<cir::YieldOp>(llvm::getSingleElement(block));
2086 Region &body = op.getBodyRegion();
2087 Region &
cleanup = op.getCleanupRegion();
2091 if (op.getCleanupKind() == CleanupKind::EH && isRegionTrivial(body)) {
2092 rewriter.eraseOp(op);
2098 if (!isRegionTrivial(cleanup) || !body.hasOneBlock())
2101 Block &bodyBlock = body.front();
2102 if (!isa<cir::YieldOp>(bodyBlock.getTerminator()))
2105 Operation *yield = bodyBlock.getTerminator();
2106 rewriter.inlineBlockBefore(&bodyBlock, op);
2107 rewriter.eraseOp(yield);
2108 rewriter.eraseOp(op);
2112void cir::CleanupScopeOp::build(
2113 OpBuilder &builder, OperationState &result, CleanupKind cleanupKind,
2114 function_ref<
void(OpBuilder &, Location)> bodyBuilder,
2115 function_ref<
void(OpBuilder &, Location)> cleanupBuilder) {
2116 result.addAttribute(getCleanupKindAttrName(result.name),
2117 CleanupKindAttr::get(builder.getContext(), cleanupKind));
2119 OpBuilder::InsertionGuard guard(builder);
2122 Region *bodyRegion = result.addRegion();
2123 builder.createBlock(bodyRegion);
2125 bodyBuilder(builder, result.location);
2128 Region *cleanupRegion = result.addRegion();
2129 builder.createBlock(cleanupRegion);
2131 cleanupBuilder(builder, result.location);
2146LogicalResult cir::BrOp::canonicalize(BrOp op, PatternRewriter &rewriter) {
2147 Block *src = op->getBlock();
2148 Block *dst = op.getDest();
2155 if (src->getNumSuccessors() != 1 || dst->getSinglePredecessor() != src)
2160 if (isa<cir::LabelOp, cir::IndirectBrOp>(dst->front()))
2166 if (llvm::any_of(op.getDestOperands(), [&](
Value operand) {
2167 auto arg = dyn_cast<BlockArgument>(operand);
2168 return arg && arg.getOwner() == dst;
2174 rewriter.eraseOp(op);
2175 rewriter.mergeBlocks(dst, src, operands);
2179mlir::SuccessorOperands cir::BrOp::getSuccessorOperands(
unsigned index) {
2180 assert(index == 0 &&
"invalid successor index");
2181 return mlir::SuccessorOperands(getDestOperandsMutable());
2192mlir::SuccessorOperands
2193cir::IndirectBrOp::getSuccessorOperands(
unsigned index) {
2194 assert(index < getNumSuccessors() &&
"invalid successor index");
2195 return mlir::SuccessorOperands(getSuccOperandsMutable()[index]);
2199 OpAsmParser &parser, Type &flagType,
2200 SmallVectorImpl<Block *> &succOperandBlocks,
2203 if (failed(parser.parseCommaSeparatedList(
2204 OpAsmParser::Delimiter::Square,
2206 Block *destination = nullptr;
2207 SmallVector<OpAsmParser::UnresolvedOperand> operands;
2208 SmallVector<Type> operandTypes;
2210 if (parser.parseSuccessor(destination).failed())
2213 if (succeeded(parser.parseOptionalLParen())) {
2214 if (failed(parser.parseOperandList(
2215 operands, OpAsmParser::Delimiter::None)) ||
2216 failed(parser.parseColonTypeList(operandTypes)) ||
2217 failed(parser.parseRParen()))
2220 succOperandBlocks.push_back(destination);
2221 succOperands.emplace_back(operands);
2222 succOperandsTypes.emplace_back(operandTypes);
2225 "successor blocks")))
2231 Type flagType, SuccessorRange succs,
2232 OperandRangeRange succOperands,
2233 const TypeRangeRange &succOperandsTypes) {
2236 llvm::zip(succs, succOperands),
2239 p.printSuccessorAndUseList(std::get<0>(i), std::get<1>(i));
2242 if (!succOperands.empty())
2251mlir::SuccessorOperands cir::BrCondOp::getSuccessorOperands(
unsigned index) {
2252 assert(index < getNumSuccessors() &&
"invalid successor index");
2253 return SuccessorOperands(index == 0 ? getDestOperandsTrueMutable()
2254 : getDestOperandsFalseMutable());
2258 if (IntegerAttr condAttr = dyn_cast_if_present<IntegerAttr>(operands.front()))
2259 return condAttr.getValue().isOne() ? getDestTrue() : getDestFalse();
2267void cir::CaseOp::build(OpBuilder &builder, OperationState &result,
2268 ArrayAttr value, CaseOpKind
kind,
2269 OpBuilder::InsertPoint &insertPoint) {
2270 OpBuilder::InsertionGuard guardSwitch(builder);
2271 result.addAttribute(
"value", value);
2272 result.getOrAddProperties<Properties>().
kind =
2273 cir::CaseOpKindAttr::get(builder.getContext(),
kind);
2274 Region *caseRegion = result.addRegion();
2275 builder.createBlock(caseRegion);
2277 insertPoint = builder.saveInsertionPoint();
2284void cir::SwitchOp::build(OpBuilder &builder, OperationState &result,
2286 assert(switchBuilder &&
"the builder callback for regions must be present");
2287 OpBuilder::InsertionGuard guardSwitch(builder);
2288 Region *switchRegion = result.addRegion();
2289 builder.createBlock(switchRegion);
2290 result.addOperands({cond});
2291 switchBuilder(builder, result.location, result);
2295 walk<mlir::WalkOrder::PreOrder>([&](mlir::Operation *op) {
2297 if (isa<cir::SwitchOp>(op) && op != *
this)
2298 return WalkResult::skip();
2300 if (
auto caseOp = dyn_cast<cir::CaseOp>(op))
2301 cases.push_back(caseOp);
2303 return WalkResult::advance();
2308 collectCases(cases);
2310 if (getBody().empty())
2313 if (!isa<YieldOp>(getBody().front().back()))
2316 if (!llvm::all_of(getBody().front(),
2317 [](Operation &op) {
return isa<CaseOp, YieldOp>(op); }))
2320 return llvm::all_of(cases, [
this](CaseOp op) {
2321 return op->getParentOfType<SwitchOp>() == *
this;
2329void cir::SwitchFlatOp::build(OpBuilder &builder, OperationState &result,
2330 Value value, Block *defaultDestination,
2331 ValueRange defaultOperands,
2333 BlockRange caseDestinations,
2336 std::vector<mlir::Attribute> caseValuesAttrs;
2337 for (
const APInt &val : caseValues)
2338 caseValuesAttrs.push_back(cir::IntAttr::get(value.getType(), val));
2339 mlir::ArrayAttr attrs = ArrayAttr::get(builder.getContext(), caseValuesAttrs);
2341 build(builder, result, value, defaultOperands, caseOperands, attrs,
2342 defaultDestination, caseDestinations);
2345SuccessorOperands cir::SwitchFlatOp::getSuccessorOperands(
unsigned index) {
2346 assert(index < getNumSuccessors() &&
"invalid successor index");
2348 return SuccessorOperands(getDefaultOperandsMutable());
2349 return SuccessorOperands(getCaseOperandsMutable()[index - 1]);
2354 auto cond = dyn_cast_if_present<cir::IntAttr>(operands.front());
2357 for (
auto [value, dest] : llvm::zip(getCaseValues(), getCaseDestinations())) {
2358 const APInt &caseValue = cast<cir::IntAttr>(value).getValue();
2359 if (caseValue == cond.getValue())
2362 return getDefaultDestination();
2368 OpAsmParser &parser, Type flagType, mlir::ArrayAttr &caseValues,
2369 SmallVectorImpl<Block *> &caseDestinations,
2373 if (failed(parser.parseLSquare()))
2375 if (succeeded(parser.parseOptionalRSquare()))
2379 auto parseCase = [&]() {
2381 if (failed(parser.parseInteger(value)))
2384 values.push_back(cir::IntAttr::get(flagType, value));
2389 if (parser.parseColon() || parser.parseSuccessor(destination))
2391 if (!parser.parseOptionalLParen()) {
2392 if (parser.parseOperandList(operands, OpAsmParser::Delimiter::None,
2394 parser.parseColonTypeList(operandTypes) || parser.parseRParen())
2397 caseDestinations.push_back(destination);
2398 caseOperands.emplace_back(operands);
2399 caseOperandTypes.emplace_back(operandTypes);
2402 if (failed(parser.parseCommaSeparatedList(parseCase)))
2405 caseValues = ArrayAttr::get(flagType.getContext(), values);
2407 return parser.parseRSquare();
2411 Type flagType, mlir::ArrayAttr caseValues,
2412 SuccessorRange caseDestinations,
2413 OperandRangeRange caseOperands,
2414 const TypeRangeRange &caseOperandTypes) {
2424 llvm::zip(caseValues, caseDestinations),
2427 mlir::Attribute a = std::get<0>(i);
2428 p << mlir::cast<cir::IntAttr>(a).getValue();
2430 p.printSuccessorAndUseList(std::get<1>(i), caseOperands[index++]);
2445 mlir::Attribute &valueAttr) {
2447 return parser.parseAttribute(valueAttr,
"value", attr);
2451 p.printAttribute(value);
2454mlir::LogicalResult cir::GlobalOp::verify() {
2457 if (mlir::isa<cir::FuncType>(getSymType()))
2458 return emitOpError(
"global type cannot be a function type");
2462 if (getInitialValue().has_value()) {
2470 if (!getCtorRegion().empty() && !getInitialValue().has_value())
2472 "cannot have a constructor region without an initial value");
2474 std::optional<DynamicInitInfoAttr>
info = getDynamicInitInfo();
2476 if ((getDynamicInitGuard().has_value()) && (!info ||
info->getLocal()) &&
2477 (!getCtorRegion().empty() || !getDtorRegion().empty()))
2479 "Cannot have a static-local global-op with a constructor or "
2480 "destructor, they require in-function initialization via LocalInitOp");
2486 if (getDynamicInitGuard().has_value() != getDynamicInitInfo().has_value())
2487 return emitOpError(
"'dynamic_init_guard' and 'dynamic_init_info' must be "
2488 "present together");
2497 if (getDynamicInitGuard().has_value() && !getTlsRefs()->getGuardName())
2498 return emitOpError(
"cannot have a dynamic-init guard combined with "
2499 "ordered tls references");
2501 return emitOpError(
"'tls_refs' only valid for tls");
2504 if (getAliasee().has_value()) {
2505 if (getInitialValue().has_value() || !getCtorRegion().empty() ||
2506 !getDtorRegion().empty())
2507 return emitOpError(
"global alias shall not have an initializer or "
2508 "constructor/destructor regions");
2517void cir::GlobalOp::build(
2518 OpBuilder &odsBuilder, OperationState &odsState, llvm::StringRef sym_name,
2519 mlir::Type sym_type,
bool isConstant,
2520 mlir::ptr::MemorySpaceAttrInterface addrSpace,
2521 cir::GlobalLinkageKind linkage,
2522 function_ref<
void(OpBuilder &, Location)> ctorBuilder,
2523 function_ref<
void(OpBuilder &, Location)> dtorBuilder) {
2524 odsState.addAttribute(getSymNameAttrName(odsState.name),
2525 odsBuilder.getStringAttr(sym_name));
2526 odsState.addAttribute(getSymTypeAttrName(odsState.name),
2527 mlir::TypeAttr::get(sym_type));
2528 auto &properties = odsState.getOrAddProperties<cir::GlobalOp::Properties>();
2529 properties.setConstant(isConstant);
2533 odsState.addAttribute(getAddrSpaceAttrName(odsState.name), addrSpace);
2535 cir::GlobalLinkageKindAttr linkageAttr =
2536 cir::GlobalLinkageKindAttr::get(odsBuilder.getContext(), linkage);
2537 odsState.addAttribute(getLinkageAttrName(odsState.name), linkageAttr);
2539 Region *ctorRegion = odsState.addRegion();
2541 odsBuilder.createBlock(ctorRegion);
2542 ctorBuilder(odsBuilder, odsState.location);
2545 Region *dtorRegion = odsState.addRegion();
2547 odsBuilder.createBlock(dtorRegion);
2548 dtorBuilder(odsBuilder, odsState.location);
2557void cir::GlobalOp::getSuccessorRegions(
2558 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
2560 if (!point.isParent()) {
2561 regions.emplace_back(getOperation());
2566 Region *ctorRegion = &this->getCtorRegion();
2567 if (ctorRegion->empty())
2568 ctorRegion =
nullptr;
2571 Region *dtorRegion = &this->getDtorRegion();
2572 if (dtorRegion->empty())
2573 dtorRegion =
nullptr;
2577 regions.push_back(RegionSuccessor(ctorRegion));
2579 regions.push_back(RegionSuccessor(dtorRegion));
2586 if (!comdat.getValue().empty())
2587 p <<
"(\"" << comdat.getValue() <<
"\")";
2591 StringAttr comdat) {
2596 StringAttr &comdatAttr) {
2597 if (parser.parseOptionalKeyword(
"comdat").failed())
2599 std::string comdatKey;
2600 if (succeeded(parser.parseOptionalLParen())) {
2601 if (parser.parseString(&comdatKey).failed() ||
2602 parser.parseRParen().failed())
2605 comdatAttr = parser.getBuilder().getStringAttr(comdatKey);
2610 TypeAttr type, Attribute initAttr,
2611 mlir::Region &ctorRegion,
2612 mlir::Region &dtorRegion) {
2613 auto printType = [&]() { p <<
": " << type; };
2616 if (op.isDeclaration() || op.getAliasee()) {
2625 if (!ctorRegion.empty()) {
2627 p.printRegion(ctorRegion,
2632 if (!dtorRegion.empty()) {
2634 p.printRegion(dtorRegion,
2642 Attribute &initialValueAttr,
2643 mlir::Region &ctorRegion,
2644 mlir::Region &dtorRegion) {
2646 if (parser.parseOptionalEqual().failed()) {
2649 if (parser.parseColonType(opTy))
2658 assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
2659 "Non-typed attrs shouldn't appear here.");
2660 opTy = mlir::cast<mlir::TypedAttr>(initialValueAttr).getType();
2664 if (!parser.parseOptionalKeyword(
"ctor")) {
2665 auto parseLoc = parser.getCurrentLocation();
2666 if (parser.parseRegion(ctorRegion, {}, {}))
2674 if (!parser.parseOptionalKeyword(
"dtor")) {
2675 auto parseLoc = parser.getCurrentLocation();
2676 if (parser.parseRegion(dtorRegion, {}, {}))
2683 typeAttr = TypeAttr::get(opTy);
2692cir::GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2695 mlir::Operation *op =
2696 symbolTable.lookupNearestSymbolFrom(*
this, getNameAttr());
2697 if (op ==
nullptr || !(isa<GlobalOp>(op) || isa<FuncOp>(op)))
2698 return emitOpError(
"'")
2700 <<
"' does not reference a valid cir.global or cir.func";
2703 mlir::ptr::MemorySpaceAttrInterface symAddrSpaceAttr{};
2704 if (
auto g = dyn_cast<GlobalOp>(op)) {
2705 symTy = g.getSymType();
2706 symAddrSpaceAttr = g.getAddrSpaceAttr();
2709 if (getTls() && !g.getTlsModel())
2710 return emitOpError(
"access to global not marked thread local");
2715 bool getGlobalIsStaticLocal = getStaticLocal();
2716 bool globalIsStaticLocal =
2717 g.getDynamicInitGuard().has_value() &&
2718 (!g.getDynamicInitInfo() || g.getDynamicInitInfo()->getLocal());
2720 if (getGlobalIsStaticLocal != globalIsStaticLocal &&
2721 !getOperation()->getParentOfType<cir::GlobalOp>())
2722 return emitOpError(
"static_local attribute mismatch");
2723 }
else if (
auto f = dyn_cast<FuncOp>(op)) {
2724 symTy = f.getFunctionType();
2726 llvm_unreachable(
"Unexpected operation for GetGlobalOp");
2729 auto resultType = dyn_cast<PointerType>(getAddr().
getType());
2730 if (!resultType || symTy != resultType.getPointee())
2731 return emitOpError(
"result type pointee type '")
2732 << resultType.getPointee() <<
"' does not match type " << symTy
2733 <<
" of the global @" <<
getName();
2735 if (symAddrSpaceAttr != resultType.getAddrSpace()) {
2736 return emitOpError()
2737 <<
"result type address space does not match the address "
2738 "space of the global @"
2750cir::VTableAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2756 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
2758 return emitOpError(
"'")
2759 <<
name <<
"' does not reference a valid cir.global";
2760 std::optional<mlir::Attribute> init = op.getInitialValue();
2763 if (!isa<cir::VTableAttr>(*init))
2764 return emitOpError(
"Expected #cir.vtable in initializer for global '")
2774cir::VTTAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
2783 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
2785 return emitOpError(
"'")
2786 <<
name <<
"' does not reference a valid cir.global";
2787 std::optional<mlir::Attribute> init = op.getInitialValue();
2790 if (!isa<cir::ConstArrayAttr>(*init))
2792 "Expected constant array in initializer for global VTT '")
2797LogicalResult cir::VTTAddrPointOp::verify() {
2799 if (
getName() && getSymAddr())
2800 return emitOpError(
"should use either a symbol or value, but not both");
2806 mlir::Type resultType = getAddr().getType();
2807 mlir::Type resTy = cir::PointerType::get(
2808 cir::PointerType::get(cir::VoidType::get(getContext())));
2810 if (resultType != resTy)
2811 return emitOpError(
"result type must be ")
2812 << resTy <<
", but provided result type is " << resultType;
2827 return name == CIRDialect::getMemoryEffectsAttrName() ||
2828 name == CIRDialect::getUwtableAttrName() ||
2829 name == CIRDialect::getFramePointerAttrName();
2832void cir::FuncOp::build(OpBuilder &builder, OperationState &result,
2833 StringRef name, FuncType type,
2834 GlobalLinkageKind linkage, CallingConv callingConv) {
2836 result.addAttribute(getSymNameAttrName(result.name),
2837 builder.getStringAttr(name));
2838 result.addAttribute(getFunctionTypeAttrName(result.name),
2839 TypeAttr::get(type));
2840 result.addAttribute(
2842 GlobalLinkageKindAttr::get(builder.getContext(), linkage));
2843 result.addAttribute(getCallingConvAttrName(result.name),
2844 CallingConvAttr::get(builder.getContext(), callingConv));
2852cir::AnnotationAttr::verify(function_ref<InFlightDiagnostic()> emitError,
2853 mlir::StringAttr name, mlir::ArrayAttr args) {
2856 for (mlir::Attribute arg : args) {
2857 if (!isa<mlir::StringAttr, mlir::IntegerAttr>(arg))
2858 return emitError() <<
"annotation args must be StringAttr or IntegerAttr,"
2864ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
2865 llvm::SMLoc loc = parser.getCurrentLocation();
2866 mlir::Builder &builder = parser.getBuilder();
2868 mlir::StringAttr builtinNameAttr = getBuiltinAttrName(state.name);
2869 mlir::StringAttr coroutineNameAttr = getCoroutineAttrName(state.name);
2870 mlir::StringAttr inlineKindNameAttr = getInlineKindAttrName(state.name);
2871 mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
2872 mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
2873 mlir::StringAttr comdatNameAttr = getComdatAttrName(state.name);
2874 mlir::StringAttr alignmentNameAttr = getAlignmentAttrName(state.name);
2875 mlir::StringAttr preferredAlignmentNameAttr =
2876 getPreferredAlignmentAttrName(state.name);
2877 mlir::StringAttr visNameAttr = getSymVisibilityAttrName(state.name);
2878 mlir::StringAttr dsoLocalNameAttr = getDsoLocalAttrName(state.name);
2879 mlir::StringAttr funcInfoNameAttr = getFuncInfoAttrName(state.name);
2881 if (::mlir::succeeded(parser.parseOptionalKeyword(builtinNameAttr.strref())))
2882 state.addAttribute(builtinNameAttr, parser.getBuilder().getUnitAttr());
2883 if (::mlir::succeeded(
2884 parser.parseOptionalKeyword(coroutineNameAttr.strref())))
2885 state.addAttribute(coroutineNameAttr, parser.getBuilder().getUnitAttr());
2888 cir::InlineKindAttr inlineKindAttr;
2892 state.addAttribute(inlineKindNameAttr, inlineKindAttr);
2894 if (::mlir::succeeded(parser.parseOptionalKeyword(lambdaNameAttr.strref())))
2895 state.addAttribute(lambdaNameAttr, parser.getBuilder().getUnitAttr());
2896 if (parser.parseOptionalKeyword(noProtoNameAttr).succeeded())
2897 state.addAttribute(noProtoNameAttr, parser.getBuilder().getUnitAttr());
2900 StringAttr comdatAttr;
2904 state.addAttribute(comdatNameAttr, comdatAttr);
2907 auto parseAlignmentBody = [&](int64_t &value) {
2908 if (parser.parseLParen().failed() || parser.parseInteger(value).failed() ||
2909 parser.parseRParen().failed())
2913 return static_cast<LogicalResult
>(parser.emitError(
2914 loc,
"function alignment must be a positive integer"));
2919 if (parser.parseOptionalKeyword(alignmentNameAttr).succeeded()) {
2921 if (parseAlignmentBody(value).failed())
2923 state.addAttribute(alignmentNameAttr, builder.getI64IntegerAttr(value));
2926 if (parser.parseOptionalKeyword(preferredAlignmentNameAttr).succeeded()) {
2928 if (parseAlignmentBody(value).failed())
2930 state.addAttribute(preferredAlignmentNameAttr,
2931 builder.getI64IntegerAttr(value));
2936 GlobalLinkageKindAttr::get(
2937 parser.getContext(),
2939 parser, GlobalLinkageKind::ExternalLinkage)));
2941 ::llvm::StringRef visAttrStr;
2942 if (parser.parseOptionalKeyword(&visAttrStr, {
"private",
"public",
"nested"})
2944 state.addAttribute(visNameAttr,
2945 parser.getBuilder().getStringAttr(visAttrStr));
2948 state.getOrAddProperties<cir::FuncOp::Properties>().global_visibility =
2951 if (parser.parseOptionalKeyword(dsoLocalNameAttr).succeeded())
2952 state.addAttribute(dsoLocalNameAttr, parser.getBuilder().getUnitAttr());
2954 StringAttr nameAttr;
2955 if (parser.parseSymbolName(nameAttr, getSymNameAttrName(state.name),
2961 bool isVariadic =
false;
2962 if (function_interface_impl::parseFunctionSignatureWithArguments(
2963 parser,
true, arguments, isVariadic, resultTypes,
2968 bool argAttrsEmpty =
true;
2969 for (OpAsmParser::Argument &arg : arguments) {
2970 argTypes.push_back(
arg.type);
2974 argAttrs.push_back(
arg.attrs);
2976 argAttrsEmpty =
false;
2980 if (resultTypes.size() > 1 || resultAttrs.size() > 1)
2981 return parser.emitError(
2982 loc,
"functions with multiple return types are not supported");
2984 mlir::Type returnType =
2985 (resultTypes.empty() ? cir::VoidType::get(builder.getContext())
2986 : resultTypes.front());
2988 cir::FuncType fnType =
2989 cir::FuncType::getChecked([&]() {
return parser.emitError(loc); },
2990 argTypes, returnType, isVariadic);
2994 state.addAttribute(getFunctionTypeAttrName(state.name),
2995 TypeAttr::get(fnType));
2997 if (!resultAttrs.empty() && resultAttrs[0])
2999 getResAttrsAttrName(state.name),
3000 mlir::ArrayAttr::get(parser.getContext(), {resultAttrs[0]}));
3003 state.addAttribute(getArgAttrsAttrName(state.name),
3004 mlir::ArrayAttr::get(parser.getContext(), argAttrs));
3006 bool hasAlias =
false;
3007 mlir::StringAttr aliaseeNameAttr = getAliaseeAttrName(state.name);
3008 if (parser.parseOptionalKeyword(
"alias").succeeded()) {
3009 if (parser.parseLParen().failed())
3011 mlir::StringAttr aliaseeAttr;
3012 if (parser.parseOptionalSymbolName(aliaseeAttr).failed())
3014 state.addAttribute(aliaseeNameAttr, FlatSymbolRefAttr::get(aliaseeAttr));
3015 if (parser.parseRParen().failed())
3020 mlir::StringAttr personalityNameAttr = getPersonalityAttrName(state.name);
3021 if (parser.parseOptionalKeyword(
"personality").succeeded()) {
3022 if (parser.parseLParen().failed())
3024 mlir::StringAttr personalityAttr;
3025 if (parser.parseOptionalSymbolName(personalityAttr).failed())
3027 state.addAttribute(personalityNameAttr,
3028 FlatSymbolRefAttr::get(personalityAttr));
3029 if (parser.parseRParen().failed())
3034 mlir::StringAttr callConvNameAttr = getCallingConvAttrName(state.name);
3035 cir::CallingConv callConv = cir::CallingConv::C;
3036 if (parser.parseOptionalKeyword(
"cc").succeeded()) {
3037 if (parser.parseLParen().failed())
3040 return parser.emitError(loc) <<
"unknown calling convention";
3041 if (parser.parseRParen().failed())
3044 state.addAttribute(callConvNameAttr,
3045 cir::CallingConvAttr::get(parser.getContext(), callConv));
3047 auto parseGlobalDtorCtor =
3048 [&](StringRef keyword,
3049 llvm::function_ref<void(std::optional<int> prio)> createAttr)
3050 -> mlir::LogicalResult {
3051 if (mlir::succeeded(parser.parseOptionalKeyword(keyword))) {
3052 std::optional<int> priority;
3053 if (mlir::succeeded(parser.parseOptionalLParen())) {
3054 auto parsedPriority = mlir::FieldParser<int>::parse(parser);
3055 if (mlir::failed(parsedPriority))
3056 return parser.emitError(parser.getCurrentLocation(),
3057 "failed to parse 'priority', of type 'int'");
3058 priority = parsedPriority.value_or(
int());
3060 if (parser.parseRParen())
3063 createAttr(priority);
3069 if (parser.parseOptionalKeyword(
"func_info").succeeded()) {
3070 if (parser.parseLess().failed())
3073 llvm::SMLoc attrLoc = parser.getCurrentLocation();
3074 mlir::Attribute
attr;
3075 if (parser.parseAttribute(attr).failed())
3077 if (!mlir::isa<cir::CXXCtorAttr, cir::CXXDtorAttr, cir::CXXAssignAttr,
3078 cir::FuncIdentityAttr>(attr))
3079 return parser.emitError(attrLoc,
3080 "expected a function info attribute, got ")
3082 state.addAttribute(funcInfoNameAttr, attr);
3084 if (parser.parseGreater().failed())
3088 if (parseGlobalDtorCtor(
"global_ctor", [&](std::optional<int> priority) {
3089 mlir::IntegerAttr globalCtorPriorityAttr =
3090 builder.getI32IntegerAttr(priority.value_or(65535));
3091 state.addAttribute(getGlobalCtorPriorityAttrName(state.name),
3092 globalCtorPriorityAttr);
3096 if (parseGlobalDtorCtor(
"global_dtor", [&](std::optional<int> priority) {
3097 mlir::IntegerAttr globalDtorPriorityAttr =
3098 builder.getI32IntegerAttr(priority.value_or(65535));
3099 state.addAttribute(getGlobalDtorPriorityAttrName(state.name),
3100 globalDtorPriorityAttr);
3105 mlir::StringAttr annotationsNameAttr = getAnnotationsAttrName(state.name);
3106 mlir::ArrayAttr annotationsAttr;
3107 if (parser.parseOptionalAttribute(annotationsAttr).has_value() &&
3109 state.addAttribute(annotationsNameAttr, annotationsAttr);
3112 NamedAttrList parsedAttrs;
3113 llvm::SMLoc attrsLoc = parser.getCurrentLocation();
3114 if (parser.parseOptionalAttrDictWithKeyword(parsedAttrs))
3118 for (StringRef disallowed : cir::FuncOp::getAttributeNames()) {
3121 if (parsedAttrs.get(disallowed))
3122 return parser.emitError(loc,
"attribute '")
3124 <<
"' should not be specified in the explicit attribute list";
3130 state.attributes.append(parsedAttrs);
3133 auto *body = state.addRegion();
3134 OptionalParseResult parseResult = parser.parseOptionalRegion(
3135 *body, arguments,
false);
3136 if (parseResult.has_value()) {
3138 return parser.emitError(loc,
"function alias shall not have a body");
3139 if (failed(*parseResult))
3143 return parser.emitError(loc,
"expected non-empty function body");
3152bool cir::FuncOp::isDeclaration() {
3155 std::optional<StringRef> aliasee = getAliasee();
3157 return getFunctionBody().empty();
3163bool cir::FuncOp::isCXXSpecialMemberFunction() {
3166 mlir::Attribute
attr = getFuncInfoAttr();
3167 return attr && mlir::isa<CXXCtorAttr, CXXDtorAttr, CXXAssignAttr>(attr);
3170bool cir::FuncOp::isCxxConstructor() {
3171 auto attr = getFuncInfoAttr();
3172 return attr && dyn_cast<CXXCtorAttr>(attr);
3175bool cir::FuncOp::isCxxDestructor() {
3176 auto attr = getFuncInfoAttr();
3177 return attr && dyn_cast<CXXDtorAttr>(attr);
3180bool cir::FuncOp::isCxxSpecialAssignment() {
3181 auto attr = getFuncInfoAttr();
3182 return attr && dyn_cast<CXXAssignAttr>(attr);
3185std::optional<CtorKind> cir::FuncOp::getCxxConstructorKind() {
3186 mlir::Attribute
attr = getFuncInfoAttr();
3188 if (
auto ctor = dyn_cast<CXXCtorAttr>(attr))
3189 return ctor.getCtorKind();
3191 return std::nullopt;
3194std::optional<AssignKind> cir::FuncOp::getCxxSpecialAssignKind() {
3195 mlir::Attribute
attr = getFuncInfoAttr();
3197 if (
auto assign = dyn_cast<CXXAssignAttr>(attr))
3198 return assign.getAssignKind();
3200 return std::nullopt;
3203bool cir::FuncOp::isCxxTrivialMemberFunction() {
3204 mlir::Attribute
attr = getFuncInfoAttr();
3206 if (
auto ctor = dyn_cast<CXXCtorAttr>(attr))
3207 return ctor.getIsTrivial();
3208 if (
auto dtor = dyn_cast<CXXDtorAttr>(attr))
3209 return dtor.getIsTrivial();
3210 if (
auto assign = dyn_cast<CXXAssignAttr>(attr))
3211 return assign.getIsTrivial();
3216mlir::Region *cir::FuncOp::getCallableRegion() {
3220 if (getBody().empty())
3225void cir::FuncOp::print(OpAsmPrinter &p) {
3240 if (getComdatAttr()) {
3246 p <<
" alignment(" << *getAlignment() <<
')';
3248 if (getPreferredAlignment())
3249 p <<
" preferred_alignment(" << *getPreferredAlignment() <<
')';
3251 if (getLinkage() != GlobalLinkageKind::ExternalLinkage)
3252 p <<
' ' << stringifyGlobalLinkageKind(getLinkage());
3254 mlir::SymbolTable::Visibility vis = getVisibility();
3255 if (vis != mlir::SymbolTable::Visibility::Public)
3258 if (getGlobalVisibility() != cir::VisibilityKind::Default)
3259 p <<
' ' << stringifyVisibilityKind(getGlobalVisibility());
3265 p.printSymbolName(getSymName());
3266 cir::FuncType fnType = getFunctionType();
3267 function_interface_impl::printFunctionSignature(
3268 p, *
this, fnType.getInputs(), fnType.isVarArg(), fnType.getReturnTypes());
3270 if (std::optional<StringRef> aliaseeName = getAliasee()) {
3272 p.printSymbolName(*aliaseeName);
3276 if (getCallingConv() != cir::CallingConv::C) {
3278 p << stringifyCallingConv(getCallingConv());
3282 if (std::optional<StringRef> personalityName = getPersonality()) {
3283 p <<
" personality(";
3284 p.printSymbolName(*personalityName);
3288 if (mlir::Attribute funcInfo = getFuncInfoAttr()) {
3290 p.printAttribute(funcInfo);
3294 if (
auto globalCtorPriority = getGlobalCtorPriority()) {
3295 p <<
" global_ctor";
3296 if (globalCtorPriority.value() != 65535)
3297 p <<
"(" << globalCtorPriority.value() <<
")";
3300 if (
auto globalDtorPriority = getGlobalDtorPriority()) {
3301 p <<
" global_dtor";
3302 if (globalDtorPriority.value() != 65535)
3303 p <<
"(" << globalDtorPriority.value() <<
")";
3306 if (mlir::ArrayAttr annotations = getAnnotationsAttr()) {
3308 p.printAttribute(annotations);
3313 for (llvm::StringRef name : cir::FuncOp::getAttributeNames())
3315 elidedAttrs.push_back(name);
3316 function_interface_impl::printFunctionAttributes(p, *
this, elidedAttrs);
3319 Region &body = getOperation()->getRegion(0);
3320 if (!body.empty()) {
3322 p.printRegion(body,
false,
3327mlir::LogicalResult cir::FuncOp::verify() {
3329 if (!isDeclaration() && getCoroutine()) {
3330 int coroutineOpCount = 0;
3331 this->walk([&](Operation *op) {
3332 if (isa<CoroutineOp>(op)) {
3334 if (coroutineOpCount > 1) {
3335 return mlir::WalkResult::interrupt();
3338 return mlir::WalkResult::advance();
3340 if (coroutineOpCount != 1)
3341 return emitOpError()
3342 <<
"coroutine function must have exactly one cir.coroutine op";
3345 llvm::SmallSet<llvm::StringRef, 16> labels;
3346 llvm::SmallSet<llvm::StringRef, 16> gotos;
3347 llvm::SmallSet<llvm::StringRef, 16> blockAddresses;
3348 bool invalidBlockAddress =
false;
3349 getOperation()->walk([&](mlir::Operation *op) {
3350 if (
auto lab = dyn_cast<cir::LabelOp>(op)) {
3351 labels.insert(lab.getLabel());
3352 }
else if (
auto goTo = dyn_cast<cir::GotoOp>(op)) {
3353 gotos.insert(goTo.getLabel());
3354 }
else if (
auto blkAdd = dyn_cast<cir::BlockAddressOp>(op)) {
3355 if (blkAdd.getBlockAddrInfoAttr().getFunc().getAttr() != getSymName()) {
3357 invalidBlockAddress =
true;
3358 return mlir::WalkResult::interrupt();
3360 blockAddresses.insert(blkAdd.getBlockAddrInfoAttr().getLabel());
3362 return mlir::WalkResult::advance();
3365 if (invalidBlockAddress)
3366 return emitOpError() <<
"blockaddress references a different function";
3368 llvm::SmallSet<llvm::StringRef, 16> mismatched;
3369 if (!labels.empty() || !gotos.empty()) {
3370 mismatched = llvm::set_difference(gotos, labels);
3372 if (!mismatched.empty())
3373 return emitOpError() <<
"goto/label mismatch";
3378 if (!labels.empty() || !blockAddresses.empty()) {
3379 mismatched = llvm::set_difference(blockAddresses, labels);
3381 if (!mismatched.empty())
3382 return emitOpError()
3383 <<
"expects an existing label target in the referenced function";
3397LogicalResult cir::AddOp::verify() {
3398 if (getSaturated() && (getNoSignedWrap() || getNoUnsignedWrap()))
3399 return emitOpError()
3400 <<
"the nsw/nuw flags and the saturated flag are mutually exclusive";
3401 return mlir::success();
3404LogicalResult cir::SubOp::verify() {
3405 if (getSaturated() && (getNoSignedWrap() || getNoUnsignedWrap()))
3406 return emitOpError()
3407 <<
"the nsw/nuw flags and the saturated flag are mutually exclusive";
3408 return mlir::success();
3415void cir::TernaryOp::build(
3416 OpBuilder &builder, OperationState &result,
Value cond,
3417 function_ref<
void(OpBuilder &, Location)> trueBuilder,
3418 function_ref<
void(OpBuilder &, Location)> falseBuilder) {
3419 result.addOperands(cond);
3420 OpBuilder::InsertionGuard guard(builder);
3421 Region *trueRegion = result.addRegion();
3422 builder.createBlock(trueRegion);
3423 trueBuilder(builder, result.location);
3424 Region *falseRegion = result.addRegion();
3425 builder.createBlock(falseRegion);
3426 falseBuilder(builder, result.location);
3431 if (trueRegion->back().mightHaveTerminator())
3432 yield = dyn_cast_or_null<cir::YieldOp>(trueRegion->back().getTerminator());
3433 if (!yield && falseRegion->back().mightHaveTerminator())
3434 yield = dyn_cast_or_null<cir::YieldOp>(falseRegion->back().getTerminator());
3436 assert((!yield || yield.getNumOperands() <= 1) &&
3437 "expected zero or one result type");
3438 if (yield && yield.getNumOperands() == 1)
3439 result.addTypes(TypeRange{yield.getOperandTypes().front()});
3446OpFoldResult cir::SelectOp::fold(FoldAdaptor adaptor) {
3448 mlir::dyn_cast_if_present<cir::BoolAttr>(adaptor.getCondition()))
3449 return condition.getValue() ? getTrueValue() : getFalseValue();
3452 mlir::Attribute trueValue = adaptor.getTrueValue();
3453 mlir::Attribute falseValue = adaptor.getFalseValue();
3454 if (trueValue == falseValue)
3456 if (getTrueValue() == getFalseValue())
3457 return getTrueValue();
3462LogicalResult cir::SelectOp::verify() {
3464 auto condTy = dyn_cast<cir::VectorType>(getCondition().
getType());
3471 if (!isa<cir::VectorType>(getTrueValue().
getType()) ||
3472 !isa<cir::VectorType>(getFalseValue().
getType())) {
3473 return emitOpError()
3474 <<
"expected both true and false operands to be vector types "
3475 "when the condition is a vector boolean type";
3484LogicalResult cir::ShiftOp::verify() {
3485 mlir::Operation *op = getOperation();
3486 auto op0VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(0).getType());
3487 auto op1VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(1).getType());
3488 if (!op0VecTy ^ !op1VecTy)
3489 return emitOpError() <<
"input types cannot be one vector and one scalar";
3492 if (op0VecTy.getSize() != op1VecTy.getSize())
3493 return emitOpError() <<
"input vector types must have the same size";
3495 auto opResultTy = mlir::dyn_cast<cir::VectorType>(
getType());
3497 return emitOpError() <<
"the type of the result must be a vector "
3498 <<
"if it is vector shift";
3500 auto op0VecEleTy = mlir::cast<cir::IntType>(op0VecTy.getElementType());
3501 auto op1VecEleTy = mlir::cast<cir::IntType>(op1VecTy.getElementType());
3502 if (op0VecEleTy.getWidth() != op1VecEleTy.getWidth())
3503 return emitOpError()
3504 <<
"vector operands do not have the same elements sizes";
3506 auto resVecEleTy = mlir::cast<cir::IntType>(opResultTy.getElementType());
3507 if (op0VecEleTy.getWidth() != resVecEleTy.getWidth())
3508 return emitOpError() <<
"vector operands and result type do not have the "
3509 "same elements sizes";
3512 return mlir::success();
3519LogicalResult cir::LabelOp::verify() {
3520 mlir::Operation *op = getOperation();
3521 mlir::Block *blk = op->getBlock();
3522 if (&blk->front() != op)
3523 return emitError() <<
"must be the first operation in a block";
3525 return mlir::success();
3532OpFoldResult cir::IncOp::fold(FoldAdaptor adaptor) {
3533 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3534 return adaptor.getInput();
3542OpFoldResult cir::DecOp::fold(FoldAdaptor adaptor) {
3543 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3544 return adaptor.getInput();
3552OpFoldResult cir::MinusOp::fold(FoldAdaptor adaptor) {
3553 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3554 return adaptor.getInput();
3559 mlir::dyn_cast_if_present<cir::IntAttr>(adaptor.getInput())) {
3560 APInt val = intAttr.getValue();
3562 return cir::IntAttr::get(
getType(), val);
3572OpFoldResult cir::FNegOp::fold(FoldAdaptor adaptor) {
3573 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3574 return adaptor.getInput();
3578 mlir::dyn_cast_if_present<cir::FPAttr>(adaptor.getInput())) {
3579 APFloat val = fpAttr.getValue();
3581 return cir::FPAttr::get(
getType(), val);
3591OpFoldResult cir::NotOp::fold(FoldAdaptor adaptor) {
3592 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()))
3593 return adaptor.getInput();
3598 if (mlir::Attribute attr = adaptor.getInput()) {
3599 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr)) {
3600 APInt val = intAttr.getValue();
3602 return cir::IntAttr::get(
getType(), val);
3604 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr))
3605 return cir::BoolAttr::get(getContext(), !boolAttr.getValue());
3615LogicalResult cir::BaseClassAddrOp::verify() {
3616 if (getSrcAddr().
getType().getAddrSpace() !=
getType().getAddrSpace())
3617 return emitOpError() <<
"address space mismatch";
3618 return mlir::success();
3621LogicalResult cir::DerivedClassAddrOp::verify() {
3622 if (getSrcAddr().
getType().getAddrSpace() !=
getType().getAddrSpace())
3623 return emitOpError() <<
"address space mismatch";
3624 return mlir::success();
3632 mlir::Type resultTy) {
3635 mlir::Type inputMemberTy;
3636 mlir::Type resultMemberTy;
3637 if (mlir::isa<cir::DataMemberType>(src.getType())) {
3639 mlir::cast<cir::DataMemberType>(src.getType()).getMemberTy();
3640 resultMemberTy = mlir::cast<cir::DataMemberType>(resultTy).getMemberTy();
3643 if (inputMemberTy != resultMemberTy)
3644 return op->emitOpError()
3645 <<
"member types of the operand and the result do not match";
3647 return mlir::success();
3650LogicalResult cir::BaseDataMemberOp::verify() {
3654LogicalResult cir::DerivedDataMemberOp::verify() {
3662LogicalResult cir::BaseMethodOp::verify() {
3666LogicalResult cir::DerivedMethodOp::verify() {
3674void cir::AwaitOp::build(OpBuilder &builder, OperationState &result,
3678 result.addAttribute(getKindAttrName(result.name),
3679 cir::AwaitKindAttr::get(builder.getContext(),
kind));
3681 OpBuilder::InsertionGuard guard(builder);
3682 Region *readyRegion = result.addRegion();
3683 builder.createBlock(readyRegion);
3684 readyBuilder(builder, result.location);
3688 OpBuilder::InsertionGuard guard(builder);
3689 Region *suspendRegion = result.addRegion();
3690 builder.createBlock(suspendRegion);
3691 suspendBuilder(builder, result.location);
3695 OpBuilder::InsertionGuard guard(builder);
3696 Region *resumeRegion = result.addRegion();
3697 builder.createBlock(resumeRegion);
3698 resumeBuilder(builder, result.location);
3702void cir::AwaitOp::getSuccessorRegions(
3703 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
3704 assert(point.isParent() || point.getTerminatorPredecessorOrNull());
3707 if (point.isParent()) {
3708 regions.emplace_back(&getReady());
3712 mlir::Region *parentRegion =
3713 point.getTerminatorPredecessorOrNull()->getParentRegion();
3722 if (&getReady() == parentRegion) {
3723 regions.emplace_back(&getResume());
3724 regions.emplace_back(&getSuspend());
3731 if (&getSuspend() == parentRegion) {
3732 regions.emplace_back(&getResume());
3733 regions.emplace_back(getOperation());
3738 regions.emplace_back(getOperation());
3741LogicalResult cir::AwaitOp::verify() {
3742 if (!isa<ConditionOp>(this->getReady().back().getTerminator()))
3743 return emitOpError(
"ready region must end with cir.condition");
3744 if (this->getSuspend().empty())
3745 return emitOpError(
"suspend region must not be empty");
3746 if (!isa<CoroSuspendPoint>(this->getSuspend().back().getTerminator()))
3747 return emitOpError(
"suspend region must end with cir.coro.suspend_point");
3755LogicalResult cir::CoReturnOp::verify() {
3756 mlir::Operation *coRet = getOperation();
3757 auto coroutine = coRet->getParentOfType<CoroutineOp>();
3758 if (!coroutine.getBody().isAncestor(getOperation()->getParentRegion()))
3759 return emitOpError(
"must be inside the cir.coroutine body region");
3767void cir::CoroutineOp::build(OpBuilder &builder, OperationState &result,
3774 OpBuilder::InsertionGuard guard(builder);
3775 Region *initialRegion = result.addRegion();
3776 builder.createBlock(initialRegion);
3777 initialSuspendBuilder(builder, result.location);
3781 OpBuilder::InsertionGuard guard(builder);
3782 Region *bodyRegion = result.addRegion();
3783 builder.createBlock(bodyRegion);
3784 bodyBuilder(builder, result.location);
3788 OpBuilder::InsertionGuard guard(builder);
3789 Region *finalRegion = result.addRegion();
3790 builder.createBlock(finalRegion);
3791 finalSuspendBuilder(builder, result.location);
3795 OpBuilder::InsertionGuard guard(builder);
3796 Region *destroyRegion = result.addRegion();
3797 builder.createBlock(destroyRegion);
3798 destroyBuilder(builder, result.location);
3802 OpBuilder::InsertionGuard guard(builder);
3803 Region *exitRegion = result.addRegion();
3804 builder.createBlock(exitRegion);
3805 exitBuilder(builder, result.location);
3809void cir::CoroutineOp::getSuccessorRegions(
3810 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
3813 if (point.isParent()) {
3814 regions.emplace_back(&getInitialSuspend());
3818 mlir::Region *parent =
3819 point.getTerminatorPredecessorOrNull()->getParentRegion();
3825 if (parent == &getInitialSuspend()) {
3826 regions.emplace_back(&getBody());
3827 regions.emplace_back(&getExit());
3828 regions.emplace_back(&getDestroy());
3836 if (parent == &getBody()) {
3837 regions.emplace_back(&getFinalSuspend());
3838 regions.emplace_back(&getExit());
3839 regions.emplace_back(&getDestroy());
3847 if (parent == &getFinalSuspend()) {
3848 regions.emplace_back(
3850 regions.emplace_back(&getExit());
3858 if (parent == &getDestroy()) {
3859 regions.emplace_back(&getExit());
3860 regions.push_back(RegionSuccessor(getOperation()));
3864 if (parent == &getExit()) {
3865 regions.emplace_back(getOperation());
3871cir::CoroutineOp::getSuccessorInputs(RegionSuccessor successor) {
3872 return ValueRange();
3875LogicalResult cir::CoroutineOp::verify() {
3876 mlir::Region &initialSuspend = getInitialSuspend();
3877 mlir::Region &body = getBody();
3878 mlir::Region &finalSuspend = getFinalSuspend();
3879 mlir::Region &destroy = getDestroy();
3880 mlir::Region &exit = getExit();
3885 int initAwaitCount = 0;
3886 bool hasInvalidAwait =
false;
3888 initialSuspend.walk([&](Operation *op) {
3889 auto awaitOp = mlir::dyn_cast<AwaitOp>(op);
3891 return mlir::WalkResult::advance();
3893 if (awaitOp.getKind() == cir::AwaitKind::Init)
3896 hasInvalidAwait =
true;
3898 if (initAwaitCount > 1 || hasInvalidAwait)
3899 return mlir::WalkResult::interrupt();
3901 return mlir::WalkResult::advance();
3904 if (hasInvalidAwait)
3905 return emitOpError(
"'initial_suspend' must not contain any cir.await other "
3906 "than the 'init' one");
3907 if (initAwaitCount != 1)
3909 "must have exactly one 'init' cir.await in 'initial_suspend'");
3912 int finalAwaitCount = 0;
3913 hasInvalidAwait =
false;
3915 finalSuspend.walk([&](Operation *op) {
3916 auto awaitOp = mlir::dyn_cast<AwaitOp>(op);
3918 return mlir::WalkResult::advance();
3920 if (awaitOp.getKind() == cir::AwaitKind::Final)
3923 hasInvalidAwait =
true;
3925 if (finalAwaitCount > 1 || hasInvalidAwait)
3926 return mlir::WalkResult::interrupt();
3928 return mlir::WalkResult::advance();
3931 if (hasInvalidAwait)
3932 return emitOpError(
"'final_suspend' must not contain any cir.await other "
3933 "than the 'final' one");
3934 if (finalAwaitCount > 1)
3936 "must have one or zero 'final' cir.await in 'final_suspend'");
3943 if (initialSuspend.empty() || initialSuspend.back().empty())
3944 return emitOpError(
"initial_suspend region must not be empty");
3945 if (!isa<YieldOp>(initialSuspend.back().back()))
3946 return emitOpError(
"'initial_suspend' must end with cir.yield");
3948 if (body.empty() || body.back().empty())
3949 return emitOpError(
"'body' region must not be empty");
3950 if (!isa<YieldOp, CoReturnOp>(body.back().back()))
3951 return emitOpError(
"'body' must end with cir.yield or cir.co_return");
3953 if (finalSuspend.empty() || finalSuspend.back().empty())
3954 return emitOpError(
"'final_suspend' region must not be empty");
3955 if (!isa<YieldOp>(finalSuspend.back().back()))
3956 return emitOpError(
"'final_suspend' must end with cir.yield");
3958 if (destroy.empty() || destroy.back().empty())
3959 return emitOpError(
"'destroy' region must not be empty");
3960 if (!isa<YieldOp>(destroy.back().back()))
3961 return emitOpError(
"'destroy' must end with cir.yield");
3963 if (exit.empty() || exit.back().empty())
3964 return emitOpError(
"'exit' region must not be empty");
3965 if (!isa<ReturnOp>(exit.back().back()))
3966 return emitOpError(
"'exit' must end with cir.return");
3968 return mlir::success();
3979 mlir::Type srcType, mlir::Type dstType) {
3980 printer.printType(srcType);
3981 if (srcType != dstType) {
3983 printer.printType(dstType);
3988 mlir::Type &srcType,
3989 mlir::Type &dstType) {
3990 if (parser.parseType(srcType))
3991 return mlir::failure();
3992 if (parser.parseOptionalComma().succeeded()) {
3993 if (parser.parseType(dstType))
3994 return mlir::failure();
3998 return mlir::success();
4001LogicalResult cir::CopyOp::verify() {
4006 if (!
getType().getPointee().hasTrait<DataLayoutTypeInterface::Trait>())
4007 return emitError() <<
"missing data layout for pointee type";
4009 if (getSkipTailPadding() &&
4010 !mlir::isa<cir::RecordType>(
getType().getPointee()))
4012 <<
"skip_tail_padding is only valid for record pointee types";
4014 return mlir::success();
4021LogicalResult cir::PtrMaskOp::verify() {
4022 mlir::DataLayout layout = mlir::DataLayout::closest(*
this);
4023 std::optional<uint64_t> indexWidth =
4024 layout.getTypeIndexBitwidth(getPtr().
getType());
4026 return emitOpError() <<
"pointer has no index width";
4028 uint64_t maskWidth = getMask().getType().getWidth();
4029 if (maskWidth != *indexWidth)
4030 return emitOpError() <<
"mask width " << maskWidth
4031 <<
" must equal the pointer index width "
4034 return mlir::success();
4041LogicalResult cir::GetRuntimeMemberOp::verify() {
4042 cir::DataMemberType memberPtrTy = getMember().getType();
4044 if (getAddr().
getType().getPointee() != memberPtrTy.getClassTy())
4045 return emitError() <<
"record type does not match the member pointer type";
4046 if (
getType().getPointee() != memberPtrTy.getMemberTy())
4047 return emitError() <<
"result type does not match the member pointer type";
4048 return mlir::success();
4055LogicalResult cir::GetMethodOp::verify() {
4056 cir::MethodType methodTy = getMethod().getType();
4059 cir::PointerType objectPtrTy = getObject().getType();
4060 mlir::Type objectTy = objectPtrTy.getPointee();
4062 if (methodTy.getClassTy() != objectTy)
4063 return emitError() <<
"method class type and object type do not match";
4066 auto calleeTy = mlir::cast<cir::FuncType>(getCallee().
getType().getPointee());
4067 cir::FuncType methodFuncTy = methodTy.getMemberFuncTy();
4074 if (methodFuncTy.getReturnType() != calleeTy.getReturnType())
4076 <<
"method return type and callee return type do not match";
4081 if (calleeArgsTy.empty())
4082 return emitError() <<
"callee parameter list lacks receiver object ptr";
4084 auto calleeThisArgPtrTy = mlir::dyn_cast<cir::PointerType>(calleeArgsTy[0]);
4085 if (!calleeThisArgPtrTy ||
4086 !mlir::isa<cir::VoidType>(calleeThisArgPtrTy.getPointee())) {
4088 <<
"the first parameter of callee must be a void pointer";
4091 if (calleeArgsTy.size() != methodFuncArgsTy.size())
4092 return emitError() <<
"callee and method parameter counts do not match";
4094 if (calleeArgsTy.size() > 1 &&
4095 calleeArgsTy.slice(1) != methodFuncArgsTy.slice(1))
4097 <<
"callee parameters and method parameters do not match";
4099 return mlir::success();
4110LogicalResult cir::GetMemberOp::verify() {
4111 const auto recordTy = dyn_cast<RecordType>(getAddrTy().getPointee());
4113 return emitError() <<
"expected pointer to a record type";
4115 if (recordTy.getMembers().size() <=
getIndex())
4116 return emitError() <<
"member index out of bounds";
4120 return emitError() <<
"member owns no storage to point at";
4122 if (pointeeTy !=
getType().getPointee())
4123 return emitError() <<
"member type mismatch";
4125 if (getAddrTy().getAddrSpace() !=
getType().getAddrSpace())
4126 return emitError() <<
"address space mismatch";
4128 return mlir::success();
4135LogicalResult cir::ExtractMemberOp::verify() {
4136 if (mlir::isa<cir::UnionType>(getRecord().
getType()))
4138 <<
"cir.extract_member currently does not support unions";
4139 auto structTy = mlir::cast<cir::StructType>(getRecord().
getType());
4140 if (structTy.getMembers().size() <=
getIndex())
4141 return emitError() <<
"member index out of bounds";
4142 mlir::Type memberTy = structTy.getMembers()[
getIndex()];
4143 if (mlir::isa<cir::BitFieldType>(memberTy))
4144 return emitError() <<
"cir.extract_member does not support bit-fields";
4146 return emitError() <<
"member type mismatch";
4147 return mlir::success();
4154LogicalResult cir::InsertMemberOp::verify() {
4155 if (mlir::isa<cir::UnionType>(getRecord().
getType()))
4156 return emitError() <<
"cir.insert_member currently does not support unions";
4157 auto structTy = mlir::cast<cir::StructType>(getRecord().
getType());
4158 if (structTy.getMembers().size() <=
getIndex())
4159 return emitError() <<
"member index out of bounds";
4160 mlir::Type memberTy = structTy.getMembers()[
getIndex()];
4161 if (mlir::isa<cir::BitFieldType>(memberTy))
4162 return emitError() <<
"cir.insert_member does not support bit-fields";
4163 if (memberTy != getValue().
getType())
4164 return emitError() <<
"member type mismatch";
4166 return mlir::success();
4173OpFoldResult cir::VecCreateOp::fold(FoldAdaptor adaptor) {
4174 if (llvm::any_of(getElements(), [](mlir::Value value) {
4175 return !value.getDefiningOp<cir::ConstantOp>();
4179 return cir::ConstVectorAttr::get(
4180 getType(), mlir::ArrayAttr::get(getContext(), adaptor.getElements()));
4183LogicalResult cir::VecCreateOp::verify() {
4187 const cir::VectorType vecTy =
getType();
4188 if (getElements().size() != vecTy.getSize()) {
4189 return emitOpError() <<
"operand count of " << getElements().size()
4190 <<
" doesn't match vector type " << vecTy
4191 <<
" element count of " << vecTy.getSize();
4194 const mlir::Type elementType = vecTy.getElementType();
4195 for (
const mlir::Value element : getElements()) {
4196 if (element.getType() != elementType) {
4197 return emitOpError() <<
"operand type " << element.getType()
4198 <<
" doesn't match vector element type "
4210OpFoldResult cir::VecExtractOp::fold(FoldAdaptor adaptor) {
4211 const auto vectorAttr =
4212 llvm::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec());
4216 const auto indexAttr =
4217 llvm::dyn_cast_if_present<cir::IntAttr>(adaptor.getIndex());
4221 const mlir::ArrayAttr elements = vectorAttr.getElts();
4222 const uint64_t index = indexAttr.getUInt();
4223 if (index >= elements.size())
4226 return elements[index];
4233LogicalResult cir::CmpOp::verify() {
4234 if (getFenvAttr() && !cir::isAnyFloatingPointType(getLhs().
getType()))
4235 return emitOpError()
4236 <<
"'fenv' is only valid for floating-point comparisons";
4244LogicalResult cir::VecCmpOp::verify() {
4245 if (getFenvAttr() && !cir::isFPOrVectorOfFPType(getLhs().
getType()))
4246 return emitOpError()
4247 <<
"'fenv' is only valid for floating-point comparisons";
4251OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
4261 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getLhs());
4263 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getRhs());
4264 if (!lhsVecAttr || !rhsVecAttr)
4267 mlir::Type inputElemTy =
4268 mlir::cast<cir::VectorType>(lhsVecAttr.getType()).getElementType();
4269 if (!isAnyIntegerOrFloatingPointType(inputElemTy))
4272 cir::CmpOpKind opKind = adaptor.getKind();
4273 mlir::ArrayAttr lhsVecElhs = lhsVecAttr.getElts();
4274 mlir::ArrayAttr rhsVecElhs = rhsVecAttr.getElts();
4275 uint64_t vecSize = lhsVecElhs.size();
4278 bool isIntAttr = vecSize && mlir::isa<cir::IntAttr>(lhsVecElhs[0]);
4279 bool isUnsignedInt =
4280 isIntAttr && mlir::cast<cir::IntType>(inputElemTy).isUnsigned();
4281 for (uint64_t i = 0; i < vecSize; i++) {
4282 mlir::Attribute lhsAttr = lhsVecElhs[i];
4283 mlir::Attribute rhsAttr = rhsVecElhs[i];
4284 bool cmpResult =
false;
4286 case cir::CmpOpKind::lt: {
4289 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() <
4290 mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
4292 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <
4293 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
4295 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <
4296 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
4300 case cir::CmpOpKind::le: {
4303 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() <=
4304 mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
4306 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <=
4307 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
4309 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <=
4310 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
4314 case cir::CmpOpKind::gt: {
4317 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() >
4318 mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
4320 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >
4321 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
4323 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >
4324 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
4328 case cir::CmpOpKind::ge: {
4331 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() >=
4332 mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
4334 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >=
4335 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
4337 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >=
4338 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
4342 case cir::CmpOpKind::eq: {
4344 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() ==
4345 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
4347 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() ==
4348 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
4352 case cir::CmpOpKind::ne: {
4354 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() !=
4355 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
4357 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() !=
4358 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
4362 case cir::CmpOpKind::one: {
4363 llvm::APFloat::cmpResult cr =
4364 mlir::cast<cir::FPAttr>(lhsAttr).getValue().compare(
4365 mlir::cast<cir::FPAttr>(rhsAttr).getValue());
4367 cr != llvm::APFloat::cmpUnordered && cr != llvm::APFloat::cmpEqual;
4370 case cir::CmpOpKind::uno: {
4371 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue().compare(
4372 mlir::cast<cir::FPAttr>(rhsAttr).getValue()) ==
4373 llvm::APFloat::cmpUnordered;
4382 cir::IntAttr::get(
getType().getElementType(), cmpResult ? -1LL : 0LL);
4385 return cir::ConstVectorAttr::get(
4386 getType(), mlir::ArrayAttr::get(getContext(), elements));
4393OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor adaptor) {
4395 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec1());
4397 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec2());
4398 if (!vec1Attr || !vec2Attr)
4401 mlir::Type vec1ElemTy =
4402 mlir::cast<cir::VectorType>(vec1Attr.getType()).getElementType();
4404 mlir::ArrayAttr vec1Elts = vec1Attr.getElts();
4405 mlir::ArrayAttr vec2Elts = vec2Attr.getElts();
4406 mlir::ArrayAttr indicesElts = adaptor.getIndices();
4409 elements.reserve(indicesElts.size());
4411 uint64_t vec1Size = vec1Elts.size();
4412 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
4413 if (idxAttr.getSInt() == -1) {
4414 elements.push_back(cir::UndefAttr::get(vec1ElemTy));
4418 uint64_t idxValue = idxAttr.getUInt();
4419 elements.push_back(idxValue < vec1Size ? vec1Elts[idxValue]
4420 : vec2Elts[idxValue - vec1Size]);
4423 return cir::ConstVectorAttr::get(
4424 getType(), mlir::ArrayAttr::get(getContext(), elements));
4427LogicalResult cir::VecShuffleOp::verify() {
4430 if (getIndices().size() != getResult().
getType().getSize()) {
4431 return emitOpError() <<
": the number of elements in " << getIndices()
4432 <<
" and " << getResult().getType() <<
" don't match";
4437 if (getVec1().
getType().getElementType() !=
4438 getResult().
getType().getElementType()) {
4439 return emitOpError() <<
": element types of " << getVec1().getType()
4440 <<
" and " << getResult().getType() <<
" don't match";
4443 const uint64_t maxValidIndex =
4444 getVec1().getType().getSize() + getVec2().getType().getSize() - 1;
4446 getIndices().getAsRange<cir::IntAttr>(), [&](cir::IntAttr idxAttr) {
4447 return idxAttr.getSInt() != -1 && idxAttr.getUInt() > maxValidIndex;
4449 return emitOpError() <<
": index for __builtin_shufflevector must be "
4450 "less than the total number of vector elements";
4459OpFoldResult cir::VecShuffleDynamicOp::fold(FoldAdaptor adaptor) {
4460 mlir::Attribute vec = adaptor.getVec();
4461 mlir::Attribute indices = adaptor.getIndices();
4462 if (mlir::isa_and_nonnull<cir::ConstVectorAttr>(vec) &&
4463 mlir::isa_and_nonnull<cir::ConstVectorAttr>(indices)) {
4464 auto vecAttr = mlir::cast<cir::ConstVectorAttr>(vec);
4465 auto indicesAttr = mlir::cast<cir::ConstVectorAttr>(indices);
4467 mlir::ArrayAttr vecElts = vecAttr.getElts();
4468 mlir::ArrayAttr indicesElts = indicesAttr.getElts();
4470 const uint64_t numElements = vecElts.size();
4473 elements.reserve(numElements);
4475 const uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
4476 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
4477 uint64_t idxValue = idxAttr.getUInt();
4478 uint64_t newIdx = idxValue & maskBits;
4479 elements.push_back(vecElts[newIdx]);
4482 return cir::ConstVectorAttr::get(
4483 getType(), mlir::ArrayAttr::get(getContext(), elements));
4489LogicalResult cir::VecShuffleDynamicOp::verify() {
4491 if (getVec().
getType().getSize() !=
4492 mlir::cast<cir::VectorType>(getIndices().
getType()).getSize()) {
4493 return emitOpError() <<
": the number of elements in " << getVec().getType()
4494 <<
" and " << getIndices().getType() <<
" don't match";
4503LogicalResult cir::VecTernaryOp::verify() {
4508 if (getCond().
getType().getSize() != getLhs().
getType().getSize()) {
4509 return emitOpError() <<
": the number of elements in "
4510 << getCond().getType() <<
" and " << getLhs().getType()
4516OpFoldResult cir::VecTernaryOp::fold(FoldAdaptor adaptor) {
4517 mlir::Attribute cond = adaptor.getCond();
4518 mlir::Attribute lhs = adaptor.getLhs();
4519 mlir::Attribute rhs = adaptor.getRhs();
4521 if (!mlir::isa_and_nonnull<cir::ConstVectorAttr>(cond) ||
4522 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(lhs) ||
4523 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(rhs))
4525 auto condVec = mlir::cast<cir::ConstVectorAttr>(cond);
4526 auto lhsVec = mlir::cast<cir::ConstVectorAttr>(lhs);
4527 auto rhsVec = mlir::cast<cir::ConstVectorAttr>(rhs);
4529 mlir::ArrayAttr condElts = condVec.getElts();
4532 elements.reserve(condElts.size());
4534 for (
const auto &[idx, condAttr] :
4535 llvm::enumerate(condElts.getAsRange<cir::IntAttr>())) {
4536 if (condAttr.getSInt()) {
4537 elements.push_back(lhsVec.getElts()[idx]);
4539 elements.push_back(rhsVec.getElts()[idx]);
4543 cir::VectorType vecTy = getLhs().getType();
4544 return cir::ConstVectorAttr::get(
4545 vecTy, mlir::ArrayAttr::get(getContext(), elements));
4552LogicalResult cir::MatrixTransposeOp::verify() {
4553 cir::MatrixType valueTy = getValue().getType();
4554 cir::MatrixType resultTy = getResult().getType();
4556 if ((valueTy.getElementType() != resultTy.getElementType()) ||
4557 (valueTy.getNumRows() != resultTy.getNumColumns()) ||
4558 (valueTy.getNumColumns() != resultTy.getNumRows())) {
4560 cir::MatrixType::get(valueTy.getElementType(), valueTy.getNumColumns(),
4561 valueTy.getNumRows());
4562 emitOpError() <<
"operand type " << valueTy <<
" expects result type of "
4563 << expectedTy <<
" but got " << resultTy;
4574LogicalResult cir::ComplexCreateOp::verify() {
4577 <<
"operand type of cir.complex.create does not match its result type";
4584OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) {
4585 mlir::Attribute real = adaptor.getReal();
4586 mlir::Attribute imag = adaptor.getImag();
4592 auto realAttr = mlir::cast<mlir::TypedAttr>(real);
4593 auto imagAttr = mlir::cast<mlir::TypedAttr>(imag);
4594 return cir::ConstComplexAttr::get(realAttr, imagAttr);
4601LogicalResult cir::ComplexRealOp::verify() {
4602 mlir::Type operandTy = getOperand().getType();
4603 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
4604 operandTy = complexOperandTy.getElementType();
4607 emitOpError() <<
": result type does not match operand type";
4614OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) {
4615 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
4618 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
4619 return complexCreateOp.getOperand(0);
4622 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
4623 return complex ? complex.getReal() :
nullptr;
4630LogicalResult cir::ComplexImagOp::verify() {
4631 mlir::Type operandTy = getOperand().getType();
4632 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
4633 operandTy = complexOperandTy.getElementType();
4636 emitOpError() <<
": result type does not match operand type";
4643OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) {
4644 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
4647 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
4648 return complexCreateOp.getOperand(1);
4651 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
4652 return complex ? complex.getImag() :
nullptr;
4659LogicalResult cir::ComplexRealPtrOp::verify() {
4660 mlir::Type resultPointeeTy =
getType().getPointee();
4661 cir::PointerType operandPtrTy = getOperand().getType();
4662 auto operandPointeeTy =
4663 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
4665 if (resultPointeeTy != operandPointeeTy.getElementType()) {
4666 return emitOpError() <<
": result type does not match operand type";
4676LogicalResult cir::ComplexImagPtrOp::verify() {
4677 mlir::Type resultPointeeTy =
getType().getPointee();
4678 cir::PointerType operandPtrTy = getOperand().getType();
4679 auto operandPointeeTy =
4680 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
4682 if (resultPointeeTy != operandPointeeTy.getElementType()) {
4683 return emitOpError()
4684 <<
"cir.complex.imag_ptr result type does not match operand type";
4695 llvm::function_ref<llvm::APInt(
const llvm::APInt &)> func,
4696 bool poisonZero =
false) {
4697 if (mlir::isa_and_present<cir::PoisonAttr>(inputAttr)) {
4702 auto input = mlir::dyn_cast_if_present<IntAttr>(inputAttr);
4706 llvm::APInt inputValue = input.getValue();
4707 if (poisonZero && inputValue.isZero())
4708 return cir::PoisonAttr::get(input.getType());
4710 llvm::APInt resultValue = func(inputValue);
4711 return IntAttr::get(input.getType(), resultValue);
4714OpFoldResult BitClrsbOp::fold(FoldAdaptor adaptor) {
4715 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4716 unsigned resultValue =
4717 inputValue.getBitWidth() - inputValue.getSignificantBits();
4718 return llvm::APInt(inputValue.getBitWidth(), resultValue);
4722OpFoldResult BitClzOp::fold(FoldAdaptor adaptor) {
4725 [](
const llvm::APInt &inputValue) {
4726 unsigned resultValue = inputValue.countLeadingZeros();
4727 return llvm::APInt(inputValue.getBitWidth(), resultValue);
4732OpFoldResult BitCtzOp::fold(FoldAdaptor adaptor) {
4735 [](
const llvm::APInt &inputValue) {
4736 return llvm::APInt(inputValue.getBitWidth(),
4737 inputValue.countTrailingZeros());
4742OpFoldResult BitFfsOp::fold(FoldAdaptor adaptor) {
4743 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4744 unsigned trailingZeros = inputValue.countTrailingZeros();
4746 trailingZeros == inputValue.getBitWidth() ? 0 : trailingZeros + 1;
4747 return llvm::APInt(inputValue.getBitWidth(), result);
4751OpFoldResult BitParityOp::fold(FoldAdaptor adaptor) {
4752 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4753 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount() % 2);
4757OpFoldResult BitPopcountOp::fold(FoldAdaptor adaptor) {
4758 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4759 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount());
4763OpFoldResult BitReverseOp::fold(FoldAdaptor adaptor) {
4764 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4765 return inputValue.reverseBits();
4769OpFoldResult ByteSwapOp::fold(FoldAdaptor adaptor) {
4770 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
4771 return inputValue.byteSwap();
4775OpFoldResult RotateOp::fold(FoldAdaptor adaptor) {
4776 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()) ||
4777 mlir::isa_and_present<cir::PoisonAttr>(adaptor.getAmount())) {
4779 return cir::PoisonAttr::get(
getType());
4782 auto input = mlir::dyn_cast_if_present<IntAttr>(adaptor.getInput());
4783 auto amount = mlir::dyn_cast_if_present<IntAttr>(adaptor.getAmount());
4784 if (!input && !amount)
4793 llvm::APInt inputValue;
4795 inputValue = input.getValue();
4796 if (inputValue.isZero() || inputValue.isAllOnes()) {
4802 uint64_t amountValue;
4804 amountValue = amount.getValue().urem(getInput().
getType().getWidth());
4805 if (amountValue == 0) {
4811 if (!input || !amount)
4814 assert(inputValue.getBitWidth() == getInput().
getType().getWidth() &&
4815 "input value must have the same bit width as the input type");
4817 llvm::APInt resultValue;
4819 resultValue = inputValue.rotl(amountValue);
4821 resultValue = inputValue.rotr(amountValue);
4823 return IntAttr::get(input.getContext(), input.getType(), resultValue);
4830void cir::InlineAsmOp::print(OpAsmPrinter &p) {
4831 p <<
'(' << getAsmFlavor() <<
", ";
4836 auto *nameIt = names.begin();
4837 auto *attrIt = getOperandAttrs().begin();
4839 for (mlir::OperandRange ops : getAsmOperands()) {
4840 p << *nameIt <<
" = ";
4843 llvm::interleaveComma(llvm::make_range(ops.begin(), ops.end()), p,
4845 p.printOperand(value);
4846 p <<
" : " << value.getType();
4847 if (mlir::isa<mlir::UnitAttr>(*attrIt))
4848 p <<
" (maybe_memory)";
4857 p.printString(getAsmString());
4859 p.printString(getConstraints());
4863 if (getSideEffects())
4864 p <<
" side_effects";
4866 p.printOptionalAttrDict(
4867 getOperation()->getDiscardableAttrDictionary().getValue());
4869 if (
auto v = getRes())
4870 p <<
" -> " << v.getType();
4873void cir::InlineAsmOp::build(OpBuilder &odsBuilder, OperationState &odsState,
4875 StringRef asmString, StringRef constraints,
4876 bool sideEffects, cir::AsmFlavor asmFlavor,
4880 for (
auto operandRange : asmOperands) {
4881 segments.push_back(operandRange.size());
4882 odsState.addOperands(operandRange);
4885 odsState.addAttribute(
4886 "operands_segments",
4887 DenseI32ArrayAttr::get(odsBuilder.getContext(), segments));
4888 odsState.addAttribute(
"asm_string", odsBuilder.getStringAttr(asmString));
4889 odsState.addAttribute(
"constraints", odsBuilder.getStringAttr(constraints));
4890 odsState.addAttribute(
"asm_flavor",
4891 AsmFlavorAttr::get(odsBuilder.getContext(), asmFlavor));
4894 odsState.addAttribute(
"side_effects", odsBuilder.getUnitAttr());
4896 odsState.addAttribute(
"operand_attrs", odsBuilder.getArrayAttr(operandAttrs));
4899ParseResult cir::InlineAsmOp::parse(OpAsmParser &parser,
4900 OperationState &result) {
4903 std::string asmString, constraints;
4905 MLIRContext *ctxt = parser.getBuilder().getContext();
4907 auto error = [&](
const Twine &msg) -> LogicalResult {
4908 return parser.emitError(parser.getCurrentLocation(), msg);
4911 auto expected = [&](
const std::string &c) {
4912 return error(
"expected '" + c +
"'");
4915 if (parser.parseLParen().failed())
4916 return expected(
"(");
4918 auto flavor = FieldParser<AsmFlavor, AsmFlavor>::parse(parser);
4920 return error(
"Unknown AsmFlavor");
4922 if (parser.parseComma().failed())
4923 return expected(
",");
4925 auto parseValue = [&](
Value &v) {
4926 OpAsmParser::UnresolvedOperand op;
4928 if (parser.parseOperand(op) || parser.parseColon())
4929 return error(
"can't parse operand");
4932 if (parser.parseType(typ).failed())
4933 return error(
"can't parse operand type");
4935 if (parser.resolveOperand(op, typ, tmp))
4936 return error(
"can't resolve operand");
4938 return mlir::success();
4941 auto parseOperands = [&](llvm::StringRef
name) {
4942 if (parser.parseKeyword(name).failed())
4943 return error(
"expected " + name +
" operands here");
4944 if (parser.parseEqual().failed())
4945 return expected(
"=");
4946 if (parser.parseLSquare().failed())
4947 return expected(
"[");
4950 if (parser.parseOptionalRSquare().succeeded()) {
4951 operandsGroupSizes.push_back(size);
4952 if (parser.parseComma())
4953 return expected(
",");
4954 return mlir::success();
4957 auto parseOperand = [&]() {
4959 if (parseValue(val).succeeded()) {
4960 result.operands.push_back(val);
4963 if (parser.parseOptionalLParen().failed()) {
4964 operandAttrs.push_back(mlir::DictionaryAttr::get(ctxt));
4965 return mlir::success();
4968 if (parser.parseKeyword(
"maybe_memory").succeeded()) {
4969 operandAttrs.push_back(mlir::UnitAttr::get(ctxt));
4970 if (parser.parseRParen())
4971 return expected(
")");
4972 return mlir::success();
4974 return expected(
"maybe_memory");
4977 return mlir::failure();
4980 if (parser.parseCommaSeparatedList(parseOperand).failed())
4981 return mlir::failure();
4983 if (parser.parseRSquare().failed() || parser.parseComma().failed())
4984 return expected(
"]");
4985 operandsGroupSizes.push_back(size);
4986 return mlir::success();
4989 if (parseOperands(
"out").failed() || parseOperands(
"in").failed() ||
4990 parseOperands(
"in_out").failed())
4991 return error(
"failed to parse operands");
4993 if (parser.parseLBrace())
4994 return expected(
"{");
4995 if (parser.parseString(&asmString))
4996 return error(
"asm string parsing failed");
4997 if (parser.parseString(&constraints))
4998 return error(
"constraints string parsing failed");
4999 if (parser.parseRBrace())
5000 return expected(
"}");
5001 if (parser.parseRParen())
5002 return expected(
")");
5004 if (parser.parseOptionalKeyword(
"side_effects").succeeded())
5005 result.attributes.set(
"side_effects", UnitAttr::get(ctxt));
5007 if (parser.parseOptionalAttrDict(result.attributes).failed())
5008 return mlir::failure();
5010 if (parser.parseOptionalArrow().succeeded() &&
5011 parser.parseType(resType).failed())
5012 return mlir::failure();
5014 result.attributes.set(
"asm_flavor", AsmFlavorAttr::get(ctxt, *flavor));
5015 result.attributes.set(
"asm_string", StringAttr::get(ctxt, asmString));
5016 result.attributes.set(
"constraints", StringAttr::get(ctxt, constraints));
5017 result.attributes.set(
"operand_attrs", ArrayAttr::get(ctxt, operandAttrs));
5018 result.getOrAddProperties<InlineAsmOp::Properties>().operands_segments =
5019 parser.getBuilder().getDenseI32ArrayAttr(operandsGroupSizes);
5021 result.addTypes(TypeRange{resType});
5023 return mlir::success();
5026void InlineAsmOp::getEffects(
5030 if (getSideEffects()) {
5031 effects.emplace_back(mlir::MemoryEffects::Read::get());
5032 effects.emplace_back(mlir::MemoryEffects::Write::get());
5040template <
typename ThrowOpTy>
5043 return mlir::success();
5045 if (op.getNumOperands() != 0) {
5046 if (op.getTypeInfo())
5047 return mlir::success();
5048 return op.emitOpError() <<
"'type_info' symbol attribute missing";
5051 return mlir::failure();
5056mlir::LogicalResult cir::TryThrowOp::verify() {
5064LogicalResult cir::AtomicFetchOp::verify() {
5065 if (getBinop() != cir::AtomicFetchKind::Add &&
5066 getBinop() != cir::AtomicFetchKind::Sub &&
5067 getBinop() != cir::AtomicFetchKind::Max &&
5068 getBinop() != cir::AtomicFetchKind::Min &&
5069 getBinop() != cir::AtomicFetchKind::Maximum &&
5070 getBinop() != cir::AtomicFetchKind::Minimum &&
5071 getBinop() != cir::AtomicFetchKind::MaximumNum &&
5072 getBinop() != cir::AtomicFetchKind::MinimumNum &&
5073 !mlir::isa<cir::IntType>(getVal().
getType()))
5074 return emitError(
"only atomic add, sub, max, min, maximum, minimum, "
5075 "maximum_num, and minimum_num operation could operate on "
5076 "floating-point values");
5078 if ((getBinop() == cir::AtomicFetchKind::Maximum ||
5079 getBinop() == cir::AtomicFetchKind::Minimum ||
5080 getBinop() == cir::AtomicFetchKind::MaximumNum ||
5081 getBinop() == cir::AtomicFetchKind::MinimumNum) &&
5082 !mlir::isa<cir::FPTypeInterface>(getVal().
getType()))
5083 return emitError(
"atomic maximum, minimum, maximum_num, and minimum_num "
5084 "operation could only operate on floating-point values");
5093LogicalResult cir::TypeInfoAttr::verify(
5094 ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
5095 ::mlir::Type type, ::mlir::ArrayAttr typeInfoData) {
5097 if (cir::ConstRecordAttr::verify(emitError, type, typeInfoData).failed())
5107void cir::TryOp::getSuccessorRegions(
5108 mlir::RegionBranchPoint point,
5111 if (!point.isParent()) {
5112 regions.emplace_back(getOperation());
5116 regions.push_back(mlir::RegionSuccessor(&getTryRegion()));
5120 for (mlir::Region &handlerRegion : this->getHandlerRegions())
5121 regions.push_back(mlir::RegionSuccessor(&handlerRegion));
5132 cir::ConstructCatchParamOp constructOp) {
5133 mlir::WalkResult result =
5134 handlerRegion.walk<mlir::WalkOrder::PreOrder>([&](mlir::Operation *op) {
5135 if (mlir::isa<cir::TryOp>(op))
5136 return mlir::WalkResult::skip();
5137 auto initOp = mlir::dyn_cast<cir::InitCatchParamOp>(op);
5139 return mlir::WalkResult::advance();
5141 cir::InitCatchKind
kind = initOp.getKind();
5143 constructOp && constructOp.getParamAddr() == initOp.getParamAddr();
5144 if (sameParam && constructOp.getKind() !=
kind) {
5145 initOp.emitOpError(
"kind '")
5146 << cir::stringifyInitCatchKind(
kind)
5147 <<
"' does not match the kind '"
5148 << cir::stringifyInitCatchKind(constructOp.getKind())
5149 <<
"' of the preceding 'cir.construct_catch_param'";
5150 return mlir::WalkResult::interrupt();
5152 if ((
kind == cir::InitCatchKind::ReferenceToPointer ||
5153 kind == cir::InitCatchKind::NonTrivialCopy) &&
5155 initOp.emitOpError(
"'")
5156 << cir::stringifyInitCatchKind(
kind)
5157 <<
"' requires a preceding 'cir.construct_catch_param' of the "
5158 "same kind on the same parameter";
5159 return mlir::WalkResult::interrupt();
5161 return mlir::WalkResult::advance();
5163 return failure(result.wasInterrupted());
5166LogicalResult cir::TryOp::verifyRegions() {
5167 mlir::ArrayAttr handlerTypes = getHandlerTypes();
5168 if (!handlerTypes) {
5169 if (!getHandlerRegions().empty())
5171 "handler regions must be empty when no handler types are present");
5175 mlir::MutableArrayRef<mlir::Region> handlerRegions = getHandlerRegions();
5179 if (handlerRegions.size() != handlerTypes.size())
5181 "number of handler regions and handler types must match");
5189 if (llvm::any_of(handlerTypes, [](mlir::Attribute typeAttr) {
5190 return mlir::isa<cir::EhFilterAttr, cir::EhUnexpectedAttr>(typeAttr);
5192 if (handlerTypes.size() != 2 ||
5193 !mlir::isa<cir::EhFilterAttr>(handlerTypes[0]) ||
5194 !mlir::isa<cir::EhUnexpectedAttr>(handlerTypes[1]))
5195 return emitOpError(
"a filter handler must be followed by an unexpected "
5196 "handler, and the two must be the only handlers");
5199 for (
const auto &[typeAttr, handlerRegion] :
5200 llvm::zip(handlerTypes, handlerRegions)) {
5202 mlir::Block &entryBlock = handlerRegion.front();
5203 if (entryBlock.getNumArguments() != 1 ||
5204 !mlir::isa<cir::EhTokenType>(entryBlock.getArgument(0).getType()))
5206 "handler region must have a single '!cir.eh_token' argument");
5210 if (mlir::isa<cir::UnwindAttr, cir::EhFilterAttr, cir::EhUnexpectedAttr>(
5214 if (entryBlock.empty())
5215 return emitOpError(
"catch handler region must not be empty");
5221 if (mlir::isa<cir::EhTerminateOp>(entryBlock.front())) {
5222 if (!mlir::isa<cir::CatchAllAttr>(typeAttr))
5223 return emitOpError(
"'cir.eh.terminate' is only allowed in a catch-all "
5242 mlir::Operation *firstOp = &entryBlock.front();
5243 if (mlir::isa<cir::LifetimeStartOp>(firstOp)) {
5244 mlir::Operation *next = firstOp->getNextNode();
5245 auto lifetimeScope = mlir::dyn_cast_if_present<cir::CleanupScopeOp>(next);
5247 return emitOpError(
"'cir.lifetime.start' in a catch handler region "
5248 "must be followed by the 'cir.cleanup.scope' of "
5249 "its lifetime-end cleanup");
5250 if (lifetimeScope.getBodyRegion().empty())
5252 "'cir.lifetime.start' in a catch handler region must be "
5253 "followed by the 'cir.cleanup.scope' of its lifetime-end "
5255 mlir::Block &scopeBody = lifetimeScope.getBodyRegion().front();
5256 firstOp = scopeBody.empty() ?
nullptr : &scopeBody.front();
5260 mlir::dyn_cast_if_present<cir::ConstructCatchParamOp>(firstOp);
5262 firstOp = firstOp->getNextNode();
5263 if (!mlir::isa_and_present<cir::BeginCatchOp>(firstOp))
5265 "catch handler region must start with 'cir.begin_catch'");
5276 mlir::MutableArrayRef<mlir::Region> handlerRegions,
5277 mlir::ArrayAttr handlerTypes) {
5281 for (
const auto [typeIdx, typeAttr] : llvm::enumerate(handlerTypes)) {
5285 if (mlir::isa<cir::CatchAllAttr>(typeAttr)) {
5286 printer <<
"catch all ";
5287 }
else if (mlir::isa<cir::UnwindAttr>(typeAttr)) {
5288 printer <<
"unwind ";
5289 }
else if (
auto filterAttr = mlir::dyn_cast<cir::EhFilterAttr>(typeAttr)) {
5290 printer <<
"filter [";
5291 llvm::interleaveComma(
5292 filterAttr.getPermittedTypes(), printer,
5293 [&](mlir::Attribute sym) { printer.printAttribute(sym); });
5295 }
else if (mlir::isa<cir::EhUnexpectedAttr>(typeAttr)) {
5296 printer <<
"unexpected ";
5298 printer <<
"catch [type ";
5299 printer.printAttribute(typeAttr);
5304 mlir::Region ®ion = handlerRegions[typeIdx];
5305 if (!region.empty() && region.front().getNumArguments() > 0) {
5307 printer.printRegionArgument(region.front().getArgument(0));
5311 printer.printRegion(region,
5318 mlir::OpAsmParser &parser,
5320 mlir::ArrayAttr &handlerTypes) {
5322 auto parseCheckedCatcherRegion = [&]() -> mlir::ParseResult {
5323 handlerRegions.emplace_back(
new mlir::Region);
5325 mlir::Region &currRegion = *handlerRegions.back();
5329 if (parser.parseLParen())
5331 mlir::OpAsmParser::Argument arg;
5332 if (parser.parseArgument(arg,
true))
5334 regionArgs.push_back(arg);
5335 if (parser.parseRParen())
5338 mlir::SMLoc regionLoc = parser.getCurrentLocation();
5339 if (parser.parseRegion(currRegion, regionArgs)) {
5340 handlerRegions.clear();
5344 if (currRegion.empty())
5345 return parser.emitError(regionLoc,
"handler region shall not be empty");
5347 if (!(currRegion.back().mightHaveTerminator() &&
5348 currRegion.back().getTerminator()))
5349 return parser.emitError(
5350 regionLoc,
"blocks are expected to be explicitly terminated");
5355 bool hasCatchAll =
false;
5357 while (parser.parseOptionalKeyword(
"catch").succeeded()) {
5358 bool hasLSquare = parser.parseOptionalLSquare().succeeded();
5360 llvm::StringRef attrStr;
5361 if (parser.parseOptionalKeyword(&attrStr, {
"all",
"type"}).failed())
5362 return parser.emitError(parser.getCurrentLocation(),
5363 "expected 'all' or 'type' keyword");
5365 bool isCatchAll = attrStr ==
"all";
5368 return parser.emitError(parser.getCurrentLocation(),
5369 "can't have more than one catch all");
5373 mlir::Attribute exceptionRTTIAttr;
5374 if (!isCatchAll && parser.parseAttribute(exceptionRTTIAttr).failed())
5375 return parser.emitError(parser.getCurrentLocation(),
5376 "expected valid RTTI info attribute");
5378 catcherAttrs.push_back(isCatchAll
5379 ? cir::CatchAllAttr::get(parser.getContext())
5380 : exceptionRTTIAttr);
5382 if (hasLSquare && isCatchAll)
5383 return parser.emitError(parser.getCurrentLocation(),
5384 "catch all dosen't need RTTI info attribute");
5386 if (hasLSquare && parser.parseRSquare().failed())
5387 return parser.emitError(parser.getCurrentLocation(),
5388 "expected `]` after RTTI info attribute");
5390 if (parseCheckedCatcherRegion().failed())
5391 return mlir::failure();
5397 if (parser.parseOptionalKeyword(
"filter").succeeded()) {
5398 mlir::SMLoc filterLoc = parser.getCurrentLocation();
5400 auto parsePermittedType = [&]() -> mlir::ParseResult {
5401 mlir::SMLoc typeLoc = parser.getCurrentLocation();
5402 mlir::Attribute rtti;
5403 if (parser.parseAttribute(rtti).failed())
5404 return mlir::failure();
5405 if (!mlir::isa<cir::GlobalViewAttr>(rtti))
5406 return parser.emitError(typeLoc,
"expected a type info symbol naming a "
5407 "permitted exception type");
5408 permittedTypes.push_back(rtti);
5409 return mlir::success();
5412 .parseCommaSeparatedList(mlir::OpAsmParser::Delimiter::Square,
5415 return mlir::failure();
5417 auto filterAttr = cir::EhFilterAttr::getChecked(
5418 [&]() {
return parser.emitError(filterLoc); }, parser.getContext(),
5419 parser.getBuilder().getArrayAttr(permittedTypes));
5421 return mlir::failure();
5422 catcherAttrs.push_back(filterAttr);
5423 if (parseCheckedCatcherRegion().failed())
5424 return mlir::failure();
5427 if (parser.parseOptionalKeyword(
"unexpected").succeeded()) {
5428 catcherAttrs.push_back(cir::EhUnexpectedAttr::get(parser.getContext()));
5429 if (parseCheckedCatcherRegion().failed())
5430 return mlir::failure();
5433 if (parser.parseOptionalKeyword(
"unwind").succeeded()) {
5435 return parser.emitError(parser.getCurrentLocation(),
5436 "unwind can't be used with catch all");
5438 catcherAttrs.push_back(cir::UnwindAttr::get(parser.getContext()));
5439 if (parseCheckedCatcherRegion().failed())
5440 return mlir::failure();
5443 handlerTypes = parser.getBuilder().getArrayAttr(catcherAttrs);
5444 return mlir::success();
5452cir::EhTypeIdOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
5453 Operation *op = symbolTable.lookupNearestSymbolFrom(*
this, getTypeSymAttr());
5454 if (!isa_and_nonnull<GlobalOp>(op))
5455 return emitOpError(
"'")
5456 << getTypeSym() <<
"' does not reference a valid cir.global";
5464LogicalResult cir::LifetimeStartOp::verify() {
5468LogicalResult cir::LifetimeEndOp::verify() {
5478 auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(attr);
5479 if (!intAttr || !intAttr.getType().isSignlessInteger(32))
5480 return std::nullopt;
5481 int64_t width = intAttr.getInt();
5484 return std::nullopt;
5485 return static_cast<unsigned>(width);
5488LogicalResult cir::MemChrOp::verify() {
5489 auto moduleOp = (*this)->getParentOfType<mlir::ModuleOp>();
5491 return emitOpError(
"expects an enclosing module");
5494 if (mlir::cast<cir::PointerType>(getSrc().
getType()).getAddrSpace())
5495 return emitOpError(
"src must be in the default address space");
5497 auto checkWidth = [&](cir::IntType type, llvm::StringRef operandName,
5498 llvm::StringRef attrName) -> LogicalResult {
5499 mlir::Attribute
attr = moduleOp->getAttr(attrName);
5501 return emitOpError(
"expects the module to record ") << attrName;
5504 return emitOpError(
"requires ")
5506 <<
" to be a signless i32 holding a fundamental integer width";
5507 if (type.getWidth() != *width)
5508 return emitOpError() << operandName <<
" must have the width recorded in "
5513 if (failed(checkWidth(getPattern().
getType(),
"pattern",
5514 cir::CIRDialect::getIntTypeWidthAttrName())))
5516 return checkWidth(getLen().
getType(),
"len",
5517 cir::CIRDialect::getSizeTypeWidthAttrName());
5528 cir::InitCatchKind
kind,
5529 cir::PointerType paramAddrType) {
5530 if (
kind != cir::InitCatchKind::ReferenceToPointer &&
5531 kind != cir::InitCatchKind::ReferenceToRecordPointer)
5534 auto refType = mlir::dyn_cast<cir::PointerType>(paramAddrType.getPointee());
5535 if (!refType || !mlir::isa<cir::PointerType>(refType.getPointee()))
5536 return op->emitOpError(
"'")
5537 << cir::stringifyInitCatchKind(
kind)
5538 <<
"' requires 'param_addr' to be the address of a reference to a "
5543LogicalResult cir::InitCatchParamOp::verify() {
5551LogicalResult cir::ConstructCatchParamOp::verify() {
5555LogicalResult cir::ConstructCatchParamOp::verifySymbolUses(
5556 SymbolTableCollection &symbolTable) {
5557 auto copyFnAttr = getCopyFnAttr();
5561 symbolTable.lookupNearestSymbolFrom<cir::FuncOp>(*
this, getCopyFnAttr());
5563 return emitOpError(
"'")
5564 << *getCopyFn() <<
"' does not reference a valid cir.func";
5566 if (!fn->hasAttr(cir::CIRDialect::getCatchCopyThunkAttrName()))
5567 return emitOpError(
"catch-init copy_fn must be tagged with the ")
5568 << cir::CIRDialect::getCatchCopyThunkAttrName() <<
" attribute";
5570 cir::FuncType fnType = fn.getFunctionType();
5571 if (fnType.getNumInputs() != 2 || !fnType.hasVoidReturn())
5572 return emitOpError(
"catch-init copy_fn must take two pointer arguments and "
5575 if (fnType.getInput(0) != getParamAddr().
getType())
5576 return emitOpError(
"first argument of catch-init copy_fn must match the "
5577 "type of 'param_addr'");
5579 if (fnType.getInput(1) != getParamAddr().
getType())
5581 "second argument of catch-init copy_fn must be a pointer "
5582 "to the catch type");
5591LogicalResult cir::EhDispatchOp::verify() {
5592 mlir::ArrayAttr handlerTypes = getCatchTypesAttr();
5596 bool hasFilter =
false;
5597 for (mlir::Attribute typeAttr : handlerTypes) {
5598 if (!mlir::isa<cir::EhFilterAttr>(typeAttr))
5601 return emitOpError(
"can't have more than one 'filter' handler");
5609 if (hasFilter && getDefaultIsCatchAll())
5611 "'filter' handler requires an 'unwind' default destination");
5618 SmallVectorImpl<Block *> &catchDestinations,
5619 Block *&defaultDestination,
5620 mlir::UnitAttr &defaultIsCatchAll) {
5622 if (parser.parseLSquare())
5626 bool hasCatchAll =
false;
5627 bool hasUnwind =
false;
5630 auto parseHandler = [&]() -> ParseResult {
5632 if (succeeded(parser.parseOptionalKeyword(
"catch_all"))) {
5634 return parser.emitError(parser.getCurrentLocation(),
5635 "duplicate 'catch_all' handler");
5637 return parser.emitError(parser.getCurrentLocation(),
5638 "cannot have both 'catch_all' and 'unwind'");
5641 if (parser.parseColon().failed())
5644 if (parser.parseSuccessor(defaultDestination).failed())
5650 if (succeeded(parser.parseOptionalKeyword(
"unwind"))) {
5652 return parser.emitError(parser.getCurrentLocation(),
5653 "duplicate 'unwind' handler");
5655 return parser.emitError(parser.getCurrentLocation(),
5656 "cannot have both 'catch_all' and 'unwind'");
5659 if (parser.parseColon().failed())
5662 if (parser.parseSuccessor(defaultDestination).failed())
5670 if (succeeded(parser.parseOptionalKeyword(
"filter"))) {
5671 SMLoc filterLoc = parser.getCurrentLocation();
5673 auto parsePermittedType = [&]() -> ParseResult {
5674 mlir::SMLoc typeLoc = parser.getCurrentLocation();
5675 mlir::Attribute rtti;
5676 if (parser.parseAttribute(rtti).failed())
5678 if (!mlir::isa<cir::GlobalViewAttr>(rtti))
5679 return parser.emitError(typeLoc,
5680 "expected a type info symbol naming a "
5681 "permitted exception type");
5682 permittedTypes.push_back(rtti);
5686 .parseCommaSeparatedList(OpAsmParser::Delimiter::Paren,
5691 auto filterAttr = cir::EhFilterAttr::getChecked(
5692 [&]() {
return parser.emitError(filterLoc); }, parser.getContext(),
5693 parser.getBuilder().getArrayAttr(permittedTypes));
5696 handlerTypes.push_back(filterAttr);
5698 if (parser.parseColon().failed())
5702 if (parser.parseSuccessor(dest).failed())
5704 catchDestinations.push_back(dest);
5711 if (parser.parseKeyword(
"catch").failed())
5714 if (parser.parseLParen().failed())
5717 mlir::Attribute catchTypeAttr;
5718 if (parser.parseAttribute(catchTypeAttr).failed())
5720 handlerTypes.push_back(catchTypeAttr);
5722 if (parser.parseRParen().failed())
5725 if (parser.parseColon().failed())
5729 if (parser.parseSuccessor(dest).failed())
5731 catchDestinations.push_back(dest);
5735 if (parser.parseCommaSeparatedList(parseHandler).failed())
5738 if (parser.parseRSquare().failed())
5742 if (!hasCatchAll && !hasUnwind)
5743 return parser.emitError(parser.getCurrentLocation(),
5744 "must have either 'catch_all' or 'unwind' handler");
5747 if (!handlerTypes.empty())
5748 catchTypes = parser.getBuilder().getArrayAttr(handlerTypes);
5751 defaultIsCatchAll = parser.getBuilder().getUnitAttr();
5757 mlir::ArrayAttr catchTypes,
5758 SuccessorRange catchDestinations,
5759 Block *defaultDestination,
5760 mlir::UnitAttr defaultIsCatchAll) {
5768 llvm::zip(catchTypes, catchDestinations),
5770 mlir::Attribute typeAttr = std::get<0>(i);
5771 if (
auto filterAttr = mlir::dyn_cast<cir::EhFilterAttr>(typeAttr)) {
5773 llvm::interleaveComma(
5774 filterAttr.getPermittedTypes(), p,
5775 [&](mlir::Attribute sym) { p.printAttribute(sym); });
5778 p.printAttribute(typeAttr);
5781 p.printSuccessor(std::get<1>(i));
5793 if (defaultIsCatchAll)
5794 p <<
" catch_all : ";
5797 p.printSuccessor(defaultDestination);
5807bool cir::StdFindOp::signatureMatches(mlir::TypeRange operands,
5808 mlir::TypeRange results) {
5809 if (operands.size() != getNumArgs() || results.size() != 1)
5811 mlir::Type iterTy = operands[0];
5812 return iterTy == operands[1] && iterTy == operands[2] && iterTy == results[0];
5819#define GET_OP_CLASSES
5820#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
static StringRef bytes(const std::vector< T, Allocator > &v)
static LogicalResult verifyLoopCleanup(LoopOpTy op)
static LogicalResult verifyOpenCLCXXVersion(ModuleOp module, cir::OpenCLVersionAttr cxxVersion)
static LogicalResult verifyCatchParamPairing(mlir::Region &handlerRegion, cir::ConstructCatchParamOp constructOp)
Verify that each cir.init_catch_param in handlerRegion, outside any nested cir.try,...
static void printEhDispatchDestinations(OpAsmPrinter &p, cir::EhDispatchOp op, mlir::ArrayAttr catchTypes, SuccessorRange catchDestinations, Block *defaultDestination, mlir::UnitAttr defaultIsCatchAll)
static mlir::LogicalResult checkReturnAndFunction(cir::ReturnOp op, cir::FuncOp function)
static void printCopyTypes(mlir::OpAsmPrinter &printer, mlir::Operation *, mlir::Type srcType, mlir::Type dstType)
static LogicalResult verifyOffloadContainer(mlir::Operation *op)
mlir::OptionalParseResult parseGlobalMemorySpace(mlir::AsmParser &p, mlir::ptr::MemorySpaceAttrInterface &attr)
static std::optional< unsigned > getRecordedIntegerWidth(mlir::Attribute attr)
Reads a fundamental integer width from a signless i32 attribute.
static bool isCirFunctionPointerType(mlir::Type ty)
static LogicalResult verifyMemberPtrCast(Operation *op, mlir::Value src, mlir::Type resultTy)
static bool isFloatingPointCastKind(cir::CastKind kind)
static LogicalResult verifyOffloadKind(mlir::ModuleOp module, cir::OffloadKind expected)
static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, mlir::OperationState &result, bool hasDestinationBlocks=false)
static mlir::Type memberPointeeType(cir::RecordType recordTy, unsigned idx)
static bool isIntOrBoolCast(cir::CastOp op)
static ParseResult parseAssumeBundle(OpAsmParser &p, cir::AssumeBundleKindAttr &bundleKindAttr, llvm::SmallVector< mlir::OpAsmParser::UnresolvedOperand, 4 > &bundleArgs, llvm::SmallVector< mlir::Type, 1 > &bundleArgTypes)
static ParseResult parseEhDispatchDestinations(OpAsmParser &parser, mlir::ArrayAttr &catchTypes, SmallVectorImpl< Block * > &catchDestinations, Block *&defaultDestination, mlir::UnitAttr &defaultIsCatchAll)
static LogicalResult verifyCatchParamAddr(mlir::Operation *op, cir::InitCatchKind kind, cir::PointerType paramAddrType)
For the reference_to_pointer and reference_to_record_pointer kinds, emit an error on op unless paramA...
static void printConstant(OpAsmPrinter &p, Attribute value)
static mlir::ParseResult parseOmittedTerminatorRegion(mlir::OpAsmParser &parser, mlir::Region ®ion)
static ParseResult checkEffectAttrKinds(mlir::OpAsmParser &parser, llvm::SMLoc loc, const mlir::NamedAttrList &attrs)
Reject an attribute in an explicit attribute dictionary whose value is not the attribute class expect...
static void printCallCommon(mlir::Operation *op, mlir::FlatSymbolRefAttr calleeSym, mlir::Value indirectCallee, mlir::OpAsmPrinter &printer, bool isNothrow, ArrayAttr argAttrs, ArrayAttr resAttrs, mlir::Block *normalDest=nullptr, mlir::Block *unwindDest=nullptr)
static void printAssumeBundle(OpAsmPrinter &p, cir::AssumeOp op, cir::AssumeBundleKindAttr kindAttr, OperandRange bundleArgs, TypeRange bundleArgTypes)
static bool areOpenCLVersionsCompatible(cir::OpenCLVersionAttr openCLVersion, cir::OpenCLVersionAttr cxxVersion)
static LogicalResult verifyOpenCLVersionAttrPlacement(Operation *op, NamedAttribute attr)
static bool isInVarCtorRegion(mlir::Operation *op)
Returns true if op is nested in the ctor region of a cir.global or cir.local_init without crossing a ...
ParseResult parseInlineKindAttr(OpAsmParser &parser, cir::InlineKindAttr &inlineKindAttr)
void printInlineKindAttr(OpAsmPrinter &p, cir::InlineKindAttr inlineKindAttr)
static 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 LogicalResult verifyOpenCLVersionAttr(Operation *op, NamedAttribute attr)
static LogicalResult verifyCallCommInSymbolUses(mlir::Operation *op, SymbolTableCollection &symbolTable)
void printGlobalMemorySpace(mlir::AsmPrinter &printer, cir::GlobalOp op, mlir::ptr::MemorySpaceAttrInterface attr)
static bool isOpenCLVersionAttrName(StringRef attrName)
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 LogicalResult verifyProducedBy(Operation *op, Value operand, StringRef operandName)
static mlir::ParseResult parseTryCallDestinations(mlir::OpAsmParser &parser, mlir::OperationState &result)
static void printGlobalOpTypeAndInitialValue(OpAsmPrinter &p, cir::GlobalOp op, TypeAttr type, Attribute initAttr, mlir::Region &ctorRegion, mlir::Region &dtorRegion)
static void printComdatName(OpAsmPrinter &p, StringAttr comdat)
static ParseResult parseCIRKeyword(AsmParser &parser, RetTy &result)
Parse an enum from the keyword, return failure if the keyword is not found.
static Value tryFoldCastChain(cir::CastOp op)
static ParseResult parseComdatName(OpAsmParser &parser, StringAttr &comdatAttr)
static void printTryHandlerRegions(mlir::OpAsmPrinter &printer, cir::TryOp op, mlir::MutableArrayRef< mlir::Region > handlerRegions, mlir::ArrayAttr handlerTypes)
ParseResult parseIndirectBrOpSucessors(OpAsmParser &parser, Type &flagType, SmallVectorImpl< Block * > &succOperandBlocks, SmallVectorImpl< SmallVector< OpAsmParser::UnresolvedOperand > > &succOperands, SmallVectorImpl< SmallVector< Type > > &succOperandsTypes)
static bool omitRegionTerm(mlir::Region &r)
static mlir::ParseResult parseCopyTypes(mlir::OpAsmParser &parser, mlir::Type &srcType, mlir::Type &dstType)
static void printOmittedTerminatorRegion(mlir::OpAsmPrinter &printer, cir::ScopeOp &op, mlir::Region ®ion)
static ParseResult parseConstantValue(OpAsmParser &parser, mlir::Attribute &valueAttr)
static LogicalResult verifyArrayCtorDtor(Op op)
static bool isFuncAttrInDict(llvm::StringRef name)
Declared cir.func attributes with no dedicated syntax, which print in and parse from the attribute di...
static bool isRedundantBeforeReturn(mlir::Region &cleanupRegion)
static mlir::LogicalResult verifyThrowOpImpl(ThrowOpTy op)
static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType, mlir::Attribute attrType)
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
C++ view class that accepts both !cir.struct and !cir.union types.
llvm::ArrayRef< mlir::Type > getMembers() const
void addBytecodeInterface(CIRDialect *dialect)
Add the interfaces necessary for encoding the CIR dialect components in bytecode.
mlir::Type memberStorageType(mlir::Type memberTy)
The storage a member is stored as: the access unit for a bit-field member, and the member type itself...
bool isValidFundamentalIntWidth(unsigned width)
void buildTerminatedBody(mlir::OpBuilder &builder, mlir::Location loc)
AllocaOp getUnderlyingAlloca(mlir::Value addr)
The alloca that defines addr, looking through casts that preserve the underlying storage.
mlir::ptr::MemorySpaceAttrInterface normalizeDefaultAddressSpace(mlir::ptr::MemorySpaceAttrInterface addrSpace)
Normalize LangAddressSpace::Default to null (empty attribute).
const AstTypeMatcher< BuiltinType > builtinType
const internal::VariadicAllOfMatcher< Attr > attr
const AstTypeMatcher< RecordType > recordType
StringRef getName(const HeaderType T)
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
static bool memberFuncPtrCast()
static bool opCallCallConv()
static bool opScopeCleanupRegion()
static bool supportIFuncAttr()