18#include "mlir/IR/DialectImplementation.h"
19#include "mlir/Interfaces/ControlFlowInterfaces.h"
20#include "mlir/Interfaces/FunctionImplementation.h"
21#include "mlir/Support/LLVM.h"
23#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
24#include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc"
26#include "llvm/ADT/SetOperations.h"
27#include "llvm/ADT/SmallSet.h"
28#include "llvm/Support/LogicalResult.h"
37struct CIROpAsmDialectInterface :
public OpAsmDialectInterface {
38 using OpAsmDialectInterface::OpAsmDialectInterface;
40 AliasResult getAlias(Type type, raw_ostream &os)
const final {
41 if (
auto recordType = dyn_cast<cir::RecordType>(type)) {
44 os <<
"rec_anon_" <<
recordType.getKindAsStr();
46 os <<
"rec_" << nameAttr.getValue();
47 return AliasResult::OverridableAlias;
49 if (
auto intType = dyn_cast<cir::IntType>(type)) {
52 unsigned width = intType.getWidth();
53 if (width < 8 || !llvm::isPowerOf2_32(width))
54 return AliasResult::NoAlias;
55 os << intType.getAlias();
56 return AliasResult::OverridableAlias;
58 if (
auto voidType = dyn_cast<cir::VoidType>(type)) {
59 os << voidType.getAlias();
60 return AliasResult::OverridableAlias;
63 return AliasResult::NoAlias;
66 AliasResult getAlias(Attribute attr, raw_ostream &os)
const final {
67 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr)) {
68 os << (boolAttr.getValue() ?
"true" :
"false");
69 return AliasResult::FinalAlias;
71 if (
auto bitfield = mlir::dyn_cast<cir::BitfieldInfoAttr>(attr)) {
72 os <<
"bfi_" << bitfield.getName().str();
73 return AliasResult::FinalAlias;
75 if (
auto dynCastInfoAttr = mlir::dyn_cast<cir::DynamicCastInfoAttr>(attr)) {
76 os << dynCastInfoAttr.getAlias();
77 return AliasResult::FinalAlias;
79 return AliasResult::NoAlias;
84void cir::CIRDialect::initialize() {
89#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
91 addInterfaces<CIROpAsmDialectInterface>();
94Operation *cir::CIRDialect::materializeConstant(mlir::OpBuilder &builder,
95 mlir::Attribute value,
98 return builder.create<cir::ConstantOp>(loc, type,
99 mlir::cast<mlir::TypedAttr>(value));
111 for (
auto en : llvm::enumerate(keywords)) {
112 if (succeeded(parser.parseOptionalKeyword(en.value())))
119template <
typename Ty>
struct EnumTraits {};
121#define REGISTER_ENUM_TYPE(Ty) \
122 template <> struct EnumTraits<cir::Ty> { \
123 static llvm::StringRef stringify(cir::Ty value) { \
124 return stringify##Ty(value); \
126 static unsigned getMaxEnumVal() { return cir::getMaxEnumValFor##Ty(); } \
137template <
typename EnumTy,
typename RetTy = EnumTy>
140 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
141 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
145 return static_cast<RetTy
>(defaultValue);
146 return static_cast<RetTy
>(index);
150template <
typename EnumTy,
typename RetTy = EnumTy>
153 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
154 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
159 result =
static_cast<RetTy
>(index);
167 Location eLoc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
168 OpBuilder builder(parser.getBuilder().getContext());
173 builder.createBlock(®ion);
175 Block &block = region.back();
177 if (!block.empty() && block.back().hasTrait<OpTrait::IsTerminator>())
181 if (!region.hasOneBlock())
182 return parser.emitError(errLoc,
183 "multi-block region must not omit terminator");
186 builder.setInsertionPointToEnd(&block);
187 builder.create<cir::YieldOp>(eLoc);
193 const auto singleNonEmptyBlock = r.hasOneBlock() && !r.back().empty();
194 const auto yieldsNothing = [&r]() {
195 auto y = dyn_cast<cir::YieldOp>(r.back().getTerminator());
196 return y && y.getArgs().empty();
198 return singleNonEmptyBlock && yieldsNothing();
202 cir::VisibilityAttr &visibility) {
203 switch (visibility.getValue()) {
204 case cir::VisibilityKind::Hidden:
207 case cir::VisibilityKind::Protected:
208 printer <<
"protected";
210 case cir::VisibilityKind::Default:
216 cir::VisibilityKind visibilityKind =
218 visibility = cir::VisibilityAttr::get(parser.getContext(), visibilityKind);
226 mlir::Region ®ion) {
227 auto regionLoc = parser.getCurrentLocation();
228 if (parser.parseRegion(region))
237 mlir::Region ®ion) {
238 printer.printRegion(region,
247void cir::AllocaOp::build(mlir::OpBuilder &odsBuilder,
248 mlir::OperationState &odsState, mlir::Type addr,
249 mlir::Type allocaType, llvm::StringRef name,
250 mlir::IntegerAttr alignment) {
251 odsState.addAttribute(getAllocaTypeAttrName(odsState.name),
252 mlir::TypeAttr::get(allocaType));
253 odsState.addAttribute(getNameAttrName(odsState.name),
254 odsBuilder.getStringAttr(name));
256 odsState.addAttribute(getAlignmentAttrName(odsState.name), alignment);
258 odsState.addTypes(addr);
265LogicalResult cir::BreakOp::verify() {
267 if (!getOperation()->getParentOfType<LoopOpInterface>() &&
268 !getOperation()->getParentOfType<SwitchOp>())
269 return emitOpError(
"must be within a loop");
281void cir::ConditionOp::getSuccessorRegions(
287 if (
auto loopOp = dyn_cast<LoopOpInterface>(getOperation()->getParentOp())) {
288 regions.emplace_back(&loopOp.getBody(), loopOp.getBody().getArguments());
289 regions.emplace_back(loopOp->getResults());
296cir::ConditionOp::getMutableSuccessorOperands(RegionBranchPoint point) {
298 return MutableOperandRange(getOperation(), 0, 0);
301LogicalResult cir::ConditionOp::verify() {
303 if (!isa<LoopOpInterface>(getOperation()->getParentOp()))
304 return emitOpError(
"condition must be within a conditional region");
313 mlir::Attribute attrType) {
314 if (isa<cir::ConstPtrAttr>(attrType)) {
315 if (!mlir::isa<cir::PointerType>(opType))
316 return op->emitOpError(
317 "pointer constant initializing a non-pointer type");
321 if (isa<cir::ZeroAttr>(attrType)) {
322 if (isa<cir::RecordType, cir::ArrayType, cir::VectorType, cir::ComplexType>(
325 return op->emitOpError(
326 "zero expects struct, array, vector, or complex type");
329 if (mlir::isa<cir::BoolAttr>(attrType)) {
330 if (!mlir::isa<cir::BoolType>(opType))
331 return op->emitOpError(
"result type (")
332 << opType <<
") must be '!cir.bool' for '" << attrType <<
"'";
336 if (mlir::isa<cir::IntAttr, cir::FPAttr>(attrType)) {
337 auto at = cast<TypedAttr>(attrType);
338 if (at.getType() != opType) {
339 return op->emitOpError(
"result type (")
340 << opType <<
") does not match value type (" << at.getType()
346 if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
347 cir::ConstComplexAttr, cir::ConstRecordAttr,
348 cir::GlobalViewAttr, cir::PoisonAttr, cir::TypeInfoAttr,
349 cir::VTableAttr>(attrType))
352 assert(isa<TypedAttr>(attrType) &&
"What else could we be looking at here?");
353 return op->emitOpError(
"global with type ")
354 << cast<TypedAttr>(attrType).getType() <<
" not yet supported";
357LogicalResult cir::ConstantOp::verify() {
364OpFoldResult cir::ConstantOp::fold(FoldAdaptor ) {
372LogicalResult cir::ContinueOp::verify() {
373 if (!getOperation()->getParentOfType<LoopOpInterface>())
374 return emitOpError(
"must be within a loop");
382LogicalResult cir::CastOp::verify() {
383 mlir::Type resType =
getType();
384 mlir::Type srcType = getSrc().getType();
386 if (mlir::isa<cir::VectorType>(srcType) &&
387 mlir::isa<cir::VectorType>(resType)) {
390 srcType = mlir::dyn_cast<cir::VectorType>(srcType).getElementType();
391 resType = mlir::dyn_cast<cir::VectorType>(resType).getElementType();
395 case cir::CastKind::int_to_bool: {
396 if (!mlir::isa<cir::BoolType>(resType))
397 return emitOpError() <<
"requires !cir.bool type for result";
398 if (!mlir::isa<cir::IntType>(srcType))
399 return emitOpError() <<
"requires !cir.int type for source";
402 case cir::CastKind::ptr_to_bool: {
403 if (!mlir::isa<cir::BoolType>(resType))
404 return emitOpError() <<
"requires !cir.bool type for result";
405 if (!mlir::isa<cir::PointerType>(srcType))
406 return emitOpError() <<
"requires !cir.ptr type for source";
409 case cir::CastKind::integral: {
410 if (!mlir::isa<cir::IntType>(resType))
411 return emitOpError() <<
"requires !cir.int type for result";
412 if (!mlir::isa<cir::IntType>(srcType))
413 return emitOpError() <<
"requires !cir.int type for source";
416 case cir::CastKind::array_to_ptrdecay: {
417 const auto arrayPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
418 const auto flatPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
419 if (!arrayPtrTy || !flatPtrTy)
420 return emitOpError() <<
"requires !cir.ptr type for source and result";
425 case cir::CastKind::bitcast: {
427 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
428 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
430 if (srcPtrTy && resPtrTy) {
436 case cir::CastKind::floating: {
437 if (!mlir::isa<cir::FPTypeInterface>(srcType) ||
438 !mlir::isa<cir::FPTypeInterface>(resType))
439 return emitOpError() <<
"requires !cir.float type for source and result";
442 case cir::CastKind::float_to_int: {
443 if (!mlir::isa<cir::FPTypeInterface>(srcType))
444 return emitOpError() <<
"requires !cir.float type for source";
445 if (!mlir::dyn_cast<cir::IntType>(resType))
446 return emitOpError() <<
"requires !cir.int type for result";
449 case cir::CastKind::int_to_ptr: {
450 if (!mlir::dyn_cast<cir::IntType>(srcType))
451 return emitOpError() <<
"requires !cir.int type for source";
452 if (!mlir::dyn_cast<cir::PointerType>(resType))
453 return emitOpError() <<
"requires !cir.ptr type for result";
456 case cir::CastKind::ptr_to_int: {
457 if (!mlir::dyn_cast<cir::PointerType>(srcType))
458 return emitOpError() <<
"requires !cir.ptr type for source";
459 if (!mlir::dyn_cast<cir::IntType>(resType))
460 return emitOpError() <<
"requires !cir.int type for result";
463 case cir::CastKind::float_to_bool: {
464 if (!mlir::isa<cir::FPTypeInterface>(srcType))
465 return emitOpError() <<
"requires !cir.float type for source";
466 if (!mlir::isa<cir::BoolType>(resType))
467 return emitOpError() <<
"requires !cir.bool type for result";
470 case cir::CastKind::bool_to_int: {
471 if (!mlir::isa<cir::BoolType>(srcType))
472 return emitOpError() <<
"requires !cir.bool type for source";
473 if (!mlir::isa<cir::IntType>(resType))
474 return emitOpError() <<
"requires !cir.int type for result";
477 case cir::CastKind::int_to_float: {
478 if (!mlir::isa<cir::IntType>(srcType))
479 return emitOpError() <<
"requires !cir.int type for source";
480 if (!mlir::isa<cir::FPTypeInterface>(resType))
481 return emitOpError() <<
"requires !cir.float type for result";
484 case cir::CastKind::bool_to_float: {
485 if (!mlir::isa<cir::BoolType>(srcType))
486 return emitOpError() <<
"requires !cir.bool type for source";
487 if (!mlir::isa<cir::FPTypeInterface>(resType))
488 return emitOpError() <<
"requires !cir.float type for result";
491 case cir::CastKind::address_space: {
492 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
493 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
494 if (!srcPtrTy || !resPtrTy)
495 return emitOpError() <<
"requires !cir.ptr type for source and result";
496 if (srcPtrTy.getPointee() != resPtrTy.getPointee())
497 return emitOpError() <<
"requires two types differ in addrspace only";
500 case cir::CastKind::float_to_complex: {
501 if (!mlir::isa<cir::FPTypeInterface>(srcType))
502 return emitOpError() <<
"requires !cir.float type for source";
503 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
505 return emitOpError() <<
"requires !cir.complex type for result";
506 if (srcType != resComplexTy.getElementType())
507 return emitOpError() <<
"requires source type match result element type";
510 case cir::CastKind::int_to_complex: {
511 if (!mlir::isa<cir::IntType>(srcType))
512 return emitOpError() <<
"requires !cir.int type for source";
513 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
515 return emitOpError() <<
"requires !cir.complex type for result";
516 if (srcType != resComplexTy.getElementType())
517 return emitOpError() <<
"requires source type match result element type";
520 case cir::CastKind::float_complex_to_real: {
521 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
523 return emitOpError() <<
"requires !cir.complex type for source";
524 if (!mlir::isa<cir::FPTypeInterface>(resType))
525 return emitOpError() <<
"requires !cir.float type for result";
526 if (srcComplexTy.getElementType() != resType)
527 return emitOpError() <<
"requires source element type match result type";
530 case cir::CastKind::int_complex_to_real: {
531 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
533 return emitOpError() <<
"requires !cir.complex type for source";
534 if (!mlir::isa<cir::IntType>(resType))
535 return emitOpError() <<
"requires !cir.int type for result";
536 if (srcComplexTy.getElementType() != resType)
537 return emitOpError() <<
"requires source element type match result type";
540 case cir::CastKind::float_complex_to_bool: {
541 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
542 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
544 <<
"requires floating point !cir.complex type for source";
545 if (!mlir::isa<cir::BoolType>(resType))
546 return emitOpError() <<
"requires !cir.bool type for result";
549 case cir::CastKind::int_complex_to_bool: {
550 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
551 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
553 <<
"requires floating point !cir.complex type for source";
554 if (!mlir::isa<cir::BoolType>(resType))
555 return emitOpError() <<
"requires !cir.bool type for result";
558 case cir::CastKind::float_complex: {
559 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
560 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
562 <<
"requires floating point !cir.complex type for source";
563 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
564 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
566 <<
"requires floating point !cir.complex type for result";
569 case cir::CastKind::float_complex_to_int_complex: {
570 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
571 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
573 <<
"requires floating point !cir.complex type for source";
574 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
575 if (!resComplexTy || !resComplexTy.isIntegerComplex())
576 return emitOpError() <<
"requires integer !cir.complex type for result";
579 case cir::CastKind::int_complex: {
580 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
581 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
582 return emitOpError() <<
"requires integer !cir.complex type for source";
583 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
584 if (!resComplexTy || !resComplexTy.isIntegerComplex())
585 return emitOpError() <<
"requires integer !cir.complex type for result";
588 case cir::CastKind::int_complex_to_float_complex: {
589 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
590 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
591 return emitOpError() <<
"requires integer !cir.complex type for source";
592 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
593 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
595 <<
"requires floating point !cir.complex type for result";
599 llvm_unreachable(
"Unknown CastOp kind?");
604 auto kind = op.getKind();
605 return kind == cir::CastKind::bool_to_int ||
606 kind == cir::CastKind::int_to_bool || kind == cir::CastKind::integral;
610 cir::CastOp head = op, tail = op;
616 op = head.getSrc().getDefiningOp<cir::CastOp>();
624 if (head.getKind() == cir::CastKind::bool_to_int &&
625 tail.getKind() == cir::CastKind::int_to_bool)
626 return head.getSrc();
631 if (head.getKind() == cir::CastKind::int_to_bool &&
632 tail.getKind() == cir::CastKind::int_to_bool)
633 return head.getResult();
638OpFoldResult cir::CastOp::fold(FoldAdaptor adaptor) {
639 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getSrc())) {
641 return cir::PoisonAttr::get(getContext(),
getType());
646 case cir::CastKind::integral: {
650 auto foldOrder = getSrc().getDefiningOp()->fold(foldResults);
651 if (foldOrder.succeeded() && mlir::isa<mlir::Attribute>(foldResults[0]))
652 return mlir::cast<mlir::Attribute>(foldResults[0]);
655 case cir::CastKind::bitcast:
656 case cir::CastKind::address_space:
657 case cir::CastKind::float_complex:
658 case cir::CastKind::int_complex: {
672mlir::OperandRange cir::CallOp::getArgOperands() {
674 return getArgs().drop_front(1);
678mlir::MutableOperandRange cir::CallOp::getArgOperandsMutable() {
679 mlir::MutableOperandRange args = getArgsMutable();
681 return args.slice(1, args.size() - 1);
685mlir::Value cir::CallOp::getIndirectCall() {
686 assert(isIndirect());
687 return getOperand(0);
691Value cir::CallOp::getArgOperand(
unsigned i) {
694 return getOperand(i);
698unsigned cir::CallOp::getNumArgOperands() {
700 return this->getOperation()->getNumOperands() - 1;
701 return this->getOperation()->getNumOperands();
705 mlir::OperationState &result) {
708 mlir::FlatSymbolRefAttr calleeAttr;
713 .parseOptionalAttribute(calleeAttr, CIRDialect::getCalleeAttrName(),
716 OpAsmParser::UnresolvedOperand indirectVal;
718 if (parser.parseOperand(indirectVal).failed())
720 ops.push_back(indirectVal);
723 if (parser.parseLParen())
724 return mlir::failure();
726 opsLoc = parser.getCurrentLocation();
727 if (parser.parseOperandList(ops))
728 return mlir::failure();
729 if (parser.parseRParen())
730 return mlir::failure();
732 if (parser.parseOptionalKeyword(
"nothrow").succeeded())
733 result.addAttribute(CIRDialect::getNoThrowAttrName(),
734 mlir::UnitAttr::get(parser.getContext()));
736 if (parser.parseOptionalKeyword(
"side_effect").succeeded()) {
737 if (parser.parseLParen().failed())
739 cir::SideEffect sideEffect;
742 if (parser.parseRParen().failed())
744 auto attr = cir::SideEffectAttr::get(parser.getContext(), sideEffect);
745 result.addAttribute(CIRDialect::getSideEffectAttrName(), attr);
748 if (parser.parseOptionalAttrDict(result.attributes))
749 return ::mlir::failure();
751 if (parser.parseColon())
752 return ::mlir::failure();
754 mlir::FunctionType opsFnTy;
755 if (parser.parseType(opsFnTy))
756 return mlir::failure();
758 allResultTypes = opsFnTy.getResults();
759 result.addTypes(allResultTypes);
761 if (parser.resolveOperands(ops, opsFnTy.getInputs(), opsLoc, result.operands))
762 return mlir::failure();
764 return mlir::success();
768 mlir::FlatSymbolRefAttr calleeSym,
769 mlir::Value indirectCallee,
770 mlir::OpAsmPrinter &printer,
bool isNothrow,
771 cir::SideEffect sideEffect) {
774 auto callLikeOp = mlir::cast<cir::CIRCallOpInterface>(op);
775 auto ops = callLikeOp.getArgOperands();
779 printer.printAttributeWithoutType(calleeSym);
782 assert(indirectCallee);
783 printer << indirectCallee;
785 printer <<
"(" << ops <<
")";
788 printer <<
" nothrow";
790 if (sideEffect != cir::SideEffect::All) {
791 printer <<
" side_effect(";
792 printer << stringifySideEffect(sideEffect);
796 printer.printOptionalAttrDict(op->getAttrs(),
797 {CIRDialect::getCalleeAttrName(),
798 CIRDialect::getNoThrowAttrName(),
799 CIRDialect::getSideEffectAttrName()});
802 printer.printFunctionalType(op->getOperands().getTypes(),
803 op->getResultTypes());
806mlir::ParseResult cir::CallOp::parse(mlir::OpAsmParser &parser,
807 mlir::OperationState &result) {
811void cir::CallOp::print(mlir::OpAsmPrinter &p) {
812 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
813 cir::SideEffect sideEffect = getSideEffect();
814 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
820 SymbolTableCollection &symbolTable) {
822 op->getAttrOfType<FlatSymbolRefAttr>(CIRDialect::getCalleeAttrName());
825 return mlir::success();
828 auto fn = symbolTable.lookupNearestSymbolFrom<cir::FuncOp>(op, fnAttr);
830 return op->emitOpError() <<
"'" << fnAttr.getValue()
831 <<
"' does not reference a valid function";
833 auto callIf = dyn_cast<cir::CIRCallOpInterface>(op);
834 assert(callIf &&
"expected CIR call interface to be always available");
838 auto fnType = fn.getFunctionType();
839 if (!fn.getNoProto()) {
840 unsigned numCallOperands = callIf.getNumArgOperands();
841 unsigned numFnOpOperands = fnType.getNumInputs();
843 if (!fnType.isVarArg() && numCallOperands != numFnOpOperands)
844 return op->emitOpError(
"incorrect number of operands for callee");
845 if (fnType.isVarArg() && numCallOperands < numFnOpOperands)
846 return op->emitOpError(
"too few operands for callee");
848 for (
unsigned i = 0, e = numFnOpOperands; i != e; ++i)
849 if (callIf.getArgOperand(i).getType() != fnType.getInput(i))
850 return op->emitOpError(
"operand type mismatch: expected operand type ")
851 << fnType.getInput(i) <<
", but provided "
852 << op->getOperand(i).getType() <<
" for operand number " << i;
858 if (fnType.hasVoidReturn() && op->getNumResults() != 0)
859 return op->emitOpError(
"callee returns void but call has results");
862 if (!fnType.hasVoidReturn() && op->getNumResults() != 1)
863 return op->emitOpError(
"incorrect number of results for callee");
866 if (!fnType.hasVoidReturn() &&
867 op->getResultTypes().front() != fnType.getReturnType()) {
868 return op->emitOpError(
"result type mismatch: expected ")
869 << fnType.getReturnType() <<
", but provided "
870 << op->getResult(0).getType();
873 return mlir::success();
877cir::CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
886 cir::FuncOp function) {
888 if (op.getNumOperands() > 1)
889 return op.emitOpError() <<
"expects at most 1 return operand";
892 auto expectedTy = function.getFunctionType().getReturnType();
894 (op.getNumOperands() == 0 ? cir::VoidType::get(op.getContext())
895 : op.getOperand(0).getType());
896 if (actualTy != expectedTy)
897 return op.emitOpError() <<
"returns " << actualTy
898 <<
" but enclosing function returns " << expectedTy;
900 return mlir::success();
903mlir::LogicalResult cir::ReturnOp::verify() {
906 auto *fnOp = getOperation()->getParentOp();
907 while (!isa<cir::FuncOp>(fnOp))
908 fnOp = fnOp->getParentOp();
921ParseResult cir::IfOp::parse(OpAsmParser &parser, OperationState &result) {
923 result.regions.reserve(2);
924 Region *thenRegion = result.addRegion();
925 Region *elseRegion = result.addRegion();
927 mlir::Builder &builder = parser.getBuilder();
928 OpAsmParser::UnresolvedOperand cond;
929 Type boolType = cir::BoolType::get(builder.getContext());
931 if (parser.parseOperand(cond) ||
932 parser.resolveOperand(cond, boolType, result.operands))
936 mlir::SMLoc parseThenLoc = parser.getCurrentLocation();
937 if (parser.parseRegion(*thenRegion, {}, {}))
944 if (!parser.parseOptionalKeyword(
"else")) {
945 mlir::SMLoc parseElseLoc = parser.getCurrentLocation();
946 if (parser.parseRegion(*elseRegion, {}, {}))
953 if (parser.parseOptionalAttrDict(result.attributes))
958void cir::IfOp::print(OpAsmPrinter &p) {
959 p <<
" " << getCondition() <<
" ";
960 mlir::Region &thenRegion = this->getThenRegion();
961 p.printRegion(thenRegion,
966 mlir::Region &elseRegion = this->getElseRegion();
967 if (!elseRegion.empty()) {
969 p.printRegion(elseRegion,
974 p.printOptionalAttrDict(getOperation()->getAttrs());
980 builder.create<cir::YieldOp>(loc);
988void cir::IfOp::getSuccessorRegions(mlir::RegionBranchPoint point,
989 SmallVectorImpl<RegionSuccessor> ®ions) {
991 if (!point.isParent()) {
992 regions.push_back(RegionSuccessor());
997 Region *elseRegion = &this->getElseRegion();
998 if (elseRegion->empty())
999 elseRegion =
nullptr;
1002 regions.push_back(RegionSuccessor(&getThenRegion()));
1005 regions.push_back(RegionSuccessor(elseRegion));
1010void cir::IfOp::build(OpBuilder &builder, OperationState &result,
Value cond,
1013 assert(thenBuilder &&
"the builder callback for 'then' must be present");
1014 result.addOperands(cond);
1016 OpBuilder::InsertionGuard guard(builder);
1017 Region *thenRegion = result.addRegion();
1018 builder.createBlock(thenRegion);
1019 thenBuilder(builder, result.location);
1021 Region *elseRegion = result.addRegion();
1022 if (!withElseRegion)
1025 builder.createBlock(elseRegion);
1026 elseBuilder(builder, result.location);
1038void cir::ScopeOp::getSuccessorRegions(
1039 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1041 if (!point.isParent()) {
1042 regions.push_back(RegionSuccessor(getODSResults(0)));
1047 regions.push_back(RegionSuccessor(&getScopeRegion()));
1050void cir::ScopeOp::build(
1051 OpBuilder &builder, OperationState &result,
1052 function_ref<
void(OpBuilder &, Type &, Location)> scopeBuilder) {
1053 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1055 OpBuilder::InsertionGuard guard(builder);
1056 Region *scopeRegion = result.addRegion();
1057 builder.createBlock(scopeRegion);
1061 scopeBuilder(builder, yieldTy, result.location);
1064 result.addTypes(TypeRange{yieldTy});
1067void cir::ScopeOp::build(
1068 OpBuilder &builder, OperationState &result,
1069 function_ref<
void(OpBuilder &, Location)> scopeBuilder) {
1070 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1071 OpBuilder::InsertionGuard guard(builder);
1072 Region *scopeRegion = result.addRegion();
1073 builder.createBlock(scopeRegion);
1075 scopeBuilder(builder, result.location);
1078LogicalResult cir::ScopeOp::verify() {
1080 return emitOpError() <<
"cir.scope must not be empty since it should "
1081 "include at least an implicit cir.yield ";
1084 mlir::Block &lastBlock =
getRegion().back();
1085 if (lastBlock.empty() || !lastBlock.mightHaveTerminator() ||
1086 !lastBlock.getTerminator()->hasTrait<OpTrait::IsTerminator>())
1087 return emitOpError() <<
"last block of cir.scope must be terminated";
1095mlir::SuccessorOperands cir::BrOp::getSuccessorOperands(
unsigned index) {
1096 assert(index == 0 &&
"invalid successor index");
1097 return mlir::SuccessorOperands(getDestOperandsMutable());
1108mlir::SuccessorOperands cir::BrCondOp::getSuccessorOperands(
unsigned index) {
1109 assert(index < getNumSuccessors() &&
"invalid successor index");
1110 return SuccessorOperands(index == 0 ? getDestOperandsTrueMutable()
1111 : getDestOperandsFalseMutable());
1115 if (IntegerAttr condAttr = dyn_cast_if_present<IntegerAttr>(operands.front()))
1116 return condAttr.getValue().isOne() ? getDestTrue() : getDestFalse();
1124void cir::CaseOp::getSuccessorRegions(
1125 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1126 if (!point.isParent()) {
1127 regions.push_back(RegionSuccessor());
1130 regions.push_back(RegionSuccessor(&getCaseRegion()));
1133void cir::CaseOp::build(OpBuilder &builder, OperationState &result,
1134 ArrayAttr value, CaseOpKind kind,
1135 OpBuilder::InsertPoint &insertPoint) {
1136 OpBuilder::InsertionGuard guardSwitch(builder);
1137 result.addAttribute(
"value", value);
1138 result.getOrAddProperties<Properties>().kind =
1139 cir::CaseOpKindAttr::get(builder.getContext(), kind);
1140 Region *caseRegion = result.addRegion();
1141 builder.createBlock(caseRegion);
1143 insertPoint = builder.saveInsertionPoint();
1151 mlir::OpAsmParser::UnresolvedOperand &cond,
1152 mlir::Type &condType) {
1153 cir::IntType intCondType;
1155 if (parser.parseLParen())
1156 return mlir::failure();
1158 if (parser.parseOperand(cond))
1159 return mlir::failure();
1160 if (parser.parseColon())
1161 return mlir::failure();
1162 if (parser.parseCustomTypeWithFallback(intCondType))
1163 return mlir::failure();
1164 condType = intCondType;
1166 if (parser.parseRParen())
1167 return mlir::failure();
1168 if (parser.parseRegion(regions, {}, {}))
1171 return mlir::success();
1175 mlir::Region &bodyRegion, mlir::Value condition,
1176 mlir::Type condType) {
1180 p.printStrippedAttrOrType(condType);
1184 p.printRegion(bodyRegion,
false,
1188void cir::SwitchOp::getSuccessorRegions(
1189 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ion) {
1190 if (!point.isParent()) {
1191 region.push_back(RegionSuccessor());
1195 region.push_back(RegionSuccessor(&getBody()));
1198void cir::SwitchOp::build(OpBuilder &builder, OperationState &result,
1200 assert(switchBuilder &&
"the builder callback for regions must be present");
1201 OpBuilder::InsertionGuard guardSwitch(builder);
1202 Region *switchRegion = result.addRegion();
1203 builder.createBlock(switchRegion);
1204 result.addOperands({cond});
1205 switchBuilder(builder, result.location, result);
1209 walk<mlir::WalkOrder::PreOrder>([&](mlir::Operation *op) {
1211 if (isa<cir::SwitchOp>(op) && op != *
this)
1212 return WalkResult::skip();
1214 if (
auto caseOp = dyn_cast<cir::CaseOp>(op))
1215 cases.push_back(caseOp);
1217 return WalkResult::advance();
1222 collectCases(cases);
1224 if (getBody().empty())
1227 if (!isa<YieldOp>(getBody().front().back()))
1230 if (!llvm::all_of(getBody().front(),
1231 [](Operation &op) {
return isa<CaseOp, YieldOp>(op); }))
1234 return llvm::all_of(cases, [
this](CaseOp op) {
1235 return op->getParentOfType<SwitchOp>() == *
this;
1243void cir::SwitchFlatOp::build(OpBuilder &builder, OperationState &result,
1244 Value value, Block *defaultDestination,
1245 ValueRange defaultOperands,
1247 BlockRange caseDestinations,
1250 std::vector<mlir::Attribute> caseValuesAttrs;
1251 for (
const APInt &val : caseValues)
1252 caseValuesAttrs.push_back(cir::IntAttr::get(value.getType(), val));
1253 mlir::ArrayAttr attrs = ArrayAttr::get(builder.getContext(), caseValuesAttrs);
1255 build(builder, result, value, defaultOperands, caseOperands, attrs,
1256 defaultDestination, caseDestinations);
1262 OpAsmParser &parser, Type flagType, mlir::ArrayAttr &caseValues,
1263 SmallVectorImpl<Block *> &caseDestinations,
1267 if (failed(parser.parseLSquare()))
1269 if (succeeded(parser.parseOptionalRSquare()))
1273 auto parseCase = [&]() {
1275 if (failed(parser.parseInteger(value)))
1278 values.push_back(cir::IntAttr::get(flagType, value));
1283 if (parser.parseColon() || parser.parseSuccessor(destination))
1285 if (!parser.parseOptionalLParen()) {
1286 if (parser.parseOperandList(operands, OpAsmParser::Delimiter::None,
1288 parser.parseColonTypeList(operandTypes) || parser.parseRParen())
1291 caseDestinations.push_back(destination);
1292 caseOperands.emplace_back(operands);
1293 caseOperandTypes.emplace_back(operandTypes);
1296 if (failed(parser.parseCommaSeparatedList(parseCase)))
1299 caseValues = ArrayAttr::get(flagType.getContext(), values);
1301 return parser.parseRSquare();
1305 Type flagType, mlir::ArrayAttr caseValues,
1306 SuccessorRange caseDestinations,
1307 OperandRangeRange caseOperands,
1308 const TypeRangeRange &caseOperandTypes) {
1318 llvm::zip(caseValues, caseDestinations),
1321 mlir::Attribute a = std::get<0>(i);
1322 p << mlir::cast<cir::IntAttr>(a).getValue();
1324 p.printSuccessorAndUseList(std::get<1>(i), caseOperands[index++]);
1339 mlir::Attribute &valueAttr) {
1341 return parser.parseAttribute(valueAttr,
"value", attr);
1345 p.printAttribute(value);
1348mlir::LogicalResult cir::GlobalOp::verify() {
1351 if (getInitialValue().has_value()) {
1363void cir::GlobalOp::build(
1364 OpBuilder &odsBuilder, OperationState &odsState, llvm::StringRef sym_name,
1365 mlir::Type sym_type,
bool isConstant, cir::GlobalLinkageKind linkage,
1366 function_ref<
void(OpBuilder &, Location)> ctorBuilder,
1367 function_ref<
void(OpBuilder &, Location)> dtorBuilder) {
1368 odsState.addAttribute(getSymNameAttrName(odsState.name),
1369 odsBuilder.getStringAttr(sym_name));
1370 odsState.addAttribute(getSymTypeAttrName(odsState.name),
1371 mlir::TypeAttr::get(sym_type));
1373 odsState.addAttribute(getConstantAttrName(odsState.name),
1374 odsBuilder.getUnitAttr());
1376 cir::GlobalLinkageKindAttr linkageAttr =
1377 cir::GlobalLinkageKindAttr::get(odsBuilder.getContext(), linkage);
1378 odsState.addAttribute(getLinkageAttrName(odsState.name), linkageAttr);
1380 Region *ctorRegion = odsState.addRegion();
1382 odsBuilder.createBlock(ctorRegion);
1383 ctorBuilder(odsBuilder, odsState.location);
1386 Region *dtorRegion = odsState.addRegion();
1388 odsBuilder.createBlock(dtorRegion);
1389 dtorBuilder(odsBuilder, odsState.location);
1392 odsState.addAttribute(getGlobalVisibilityAttrName(odsState.name),
1393 cir::VisibilityAttr::get(odsBuilder.getContext()));
1401void cir::GlobalOp::getSuccessorRegions(
1402 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1404 if (!point.isParent()) {
1405 regions.push_back(RegionSuccessor());
1410 Region *ctorRegion = &this->getCtorRegion();
1411 if (ctorRegion->empty())
1412 ctorRegion =
nullptr;
1415 Region *dtorRegion = &this->getCtorRegion();
1416 if (dtorRegion->empty())
1417 dtorRegion =
nullptr;
1421 regions.push_back(RegionSuccessor(ctorRegion));
1423 regions.push_back(RegionSuccessor(dtorRegion));
1427 TypeAttr type, Attribute initAttr,
1428 mlir::Region &ctorRegion,
1429 mlir::Region &dtorRegion) {
1430 auto printType = [&]() { p <<
": " << type; };
1431 if (!op.isDeclaration()) {
1433 if (!ctorRegion.empty()) {
1437 p.printRegion(ctorRegion,
1446 if (!dtorRegion.empty()) {
1448 p.printRegion(dtorRegion,
1459 Attribute &initialValueAttr,
1460 mlir::Region &ctorRegion,
1461 mlir::Region &dtorRegion) {
1463 if (parser.parseOptionalEqual().failed()) {
1466 if (parser.parseColonType(opTy))
1471 if (!parser.parseOptionalKeyword(
"ctor")) {
1472 if (parser.parseColonType(opTy))
1474 auto parseLoc = parser.getCurrentLocation();
1475 if (parser.parseRegion(ctorRegion, {}, {}))
1486 assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
1487 "Non-typed attrs shouldn't appear here.");
1488 auto typedAttr = mlir::cast<mlir::TypedAttr>(initialValueAttr);
1489 opTy = typedAttr.getType();
1494 if (!parser.parseOptionalKeyword(
"dtor")) {
1495 auto parseLoc = parser.getCurrentLocation();
1496 if (parser.parseRegion(dtorRegion, {}, {}))
1503 typeAttr = TypeAttr::get(opTy);
1512cir::GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1515 mlir::Operation *op =
1516 symbolTable.lookupNearestSymbolFrom(*
this, getNameAttr());
1517 if (op ==
nullptr || !(isa<GlobalOp>(op) || isa<FuncOp>(op)))
1518 return emitOpError(
"'")
1520 <<
"' does not reference a valid cir.global or cir.func";
1523 if (
auto g = dyn_cast<GlobalOp>(op)) {
1524 symTy = g.getSymType();
1527 }
else if (
auto f = dyn_cast<FuncOp>(op)) {
1528 symTy = f.getFunctionType();
1530 llvm_unreachable(
"Unexpected operation for GetGlobalOp");
1533 auto resultType = dyn_cast<PointerType>(getAddr().
getType());
1534 if (!resultType || symTy != resultType.getPointee())
1535 return emitOpError(
"result type pointee type '")
1536 << resultType.getPointee() <<
"' does not match type " << symTy
1537 <<
" of the global @" <<
getName();
1547cir::VTableAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1553 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
1555 return emitOpError(
"'")
1556 <<
name <<
"' does not reference a valid cir.global";
1557 std::optional<mlir::Attribute> init = op.getInitialValue();
1560 if (!isa<cir::VTableAttr>(*init))
1561 return emitOpError(
"Expected #cir.vtable in initializer for global '")
1571cir::VTTAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1580 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
1582 return emitOpError(
"'")
1583 <<
name <<
"' does not reference a valid cir.global";
1584 std::optional<mlir::Attribute> init = op.getInitialValue();
1587 if (!isa<cir::ConstArrayAttr>(*init))
1589 "Expected constant array in initializer for global VTT '")
1594LogicalResult cir::VTTAddrPointOp::verify() {
1596 if (
getName() && getSymAddr())
1597 return emitOpError(
"should use either a symbol or value, but not both");
1603 mlir::Type resultType = getAddr().getType();
1604 mlir::Type resTy = cir::PointerType::get(
1605 cir::PointerType::get(cir::VoidType::get(getContext())));
1607 if (resultType != resTy)
1608 return emitOpError(
"result type must be ")
1609 << resTy <<
", but provided result type is " << resultType;
1621void cir::FuncOp::build(OpBuilder &builder, OperationState &result,
1622 StringRef name, FuncType type,
1623 GlobalLinkageKind linkage) {
1625 result.addAttribute(SymbolTable::getSymbolAttrName(),
1626 builder.getStringAttr(name));
1627 result.addAttribute(getFunctionTypeAttrName(result.name),
1628 TypeAttr::get(type));
1629 result.addAttribute(
1631 GlobalLinkageKindAttr::get(builder.getContext(), linkage));
1632 result.addAttribute(getGlobalVisibilityAttrName(result.name),
1633 cir::VisibilityAttr::get(builder.getContext()));
1636ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
1637 llvm::SMLoc loc = parser.getCurrentLocation();
1638 mlir::Builder &builder = parser.getBuilder();
1640 mlir::StringAttr builtinNameAttr = getBuiltinAttrName(state.name);
1641 mlir::StringAttr coroutineNameAttr = getCoroutineAttrName(state.name);
1642 mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
1643 mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
1644 mlir::StringAttr visNameAttr = getSymVisibilityAttrName(state.name);
1645 mlir::StringAttr visibilityNameAttr = getGlobalVisibilityAttrName(state.name);
1646 mlir::StringAttr dsoLocalNameAttr = getDsoLocalAttrName(state.name);
1648 if (::mlir::succeeded(parser.parseOptionalKeyword(builtinNameAttr.strref())))
1649 state.addAttribute(builtinNameAttr, parser.getBuilder().getUnitAttr());
1650 if (::mlir::succeeded(
1651 parser.parseOptionalKeyword(coroutineNameAttr.strref())))
1652 state.addAttribute(coroutineNameAttr, parser.getBuilder().getUnitAttr());
1653 if (::mlir::succeeded(parser.parseOptionalKeyword(lambdaNameAttr.strref())))
1654 state.addAttribute(lambdaNameAttr, parser.getBuilder().getUnitAttr());
1655 if (parser.parseOptionalKeyword(noProtoNameAttr).succeeded())
1656 state.addAttribute(noProtoNameAttr, parser.getBuilder().getUnitAttr());
1660 GlobalLinkageKindAttr::get(
1661 parser.getContext(),
1663 parser, GlobalLinkageKind::ExternalLinkage)));
1665 ::llvm::StringRef visAttrStr;
1666 if (parser.parseOptionalKeyword(&visAttrStr, {
"private",
"public",
"nested"})
1668 state.addAttribute(visNameAttr,
1669 parser.getBuilder().getStringAttr(visAttrStr));
1672 cir::VisibilityAttr cirVisibilityAttr;
1674 state.addAttribute(visibilityNameAttr, cirVisibilityAttr);
1676 if (parser.parseOptionalKeyword(dsoLocalNameAttr).succeeded())
1677 state.addAttribute(dsoLocalNameAttr, parser.getBuilder().getUnitAttr());
1679 StringAttr nameAttr;
1680 if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
1686 bool isVariadic =
false;
1687 if (function_interface_impl::parseFunctionSignatureWithArguments(
1688 parser,
true, arguments, isVariadic, resultTypes,
1692 for (OpAsmParser::Argument &arg : arguments)
1693 argTypes.push_back(
arg.type);
1695 if (resultTypes.size() > 1) {
1696 return parser.emitError(
1697 loc,
"functions with multiple return types are not supported");
1700 mlir::Type returnType =
1701 (resultTypes.empty() ? cir::VoidType::get(builder.getContext())
1702 : resultTypes.front());
1704 cir::FuncType fnType = cir::FuncType::get(argTypes, returnType, isVariadic);
1707 state.addAttribute(getFunctionTypeAttrName(state.name),
1708 TypeAttr::get(fnType));
1710 bool hasAlias =
false;
1711 mlir::StringAttr aliaseeNameAttr = getAliaseeAttrName(state.name);
1712 if (parser.parseOptionalKeyword(
"alias").succeeded()) {
1713 if (parser.parseLParen().failed())
1715 mlir::StringAttr aliaseeAttr;
1716 if (parser.parseOptionalSymbolName(aliaseeAttr).failed())
1718 state.addAttribute(aliaseeNameAttr, FlatSymbolRefAttr::get(aliaseeAttr));
1719 if (parser.parseRParen().failed())
1724 auto parseGlobalDtorCtor =
1725 [&](StringRef keyword,
1726 llvm::function_ref<void(std::optional<int> prio)> createAttr)
1727 -> mlir::LogicalResult {
1728 if (mlir::succeeded(parser.parseOptionalKeyword(keyword))) {
1729 std::optional<int> priority;
1730 if (mlir::succeeded(parser.parseOptionalLParen())) {
1731 auto parsedPriority = mlir::FieldParser<int>::parse(parser);
1732 if (mlir::failed(parsedPriority))
1733 return parser.emitError(parser.getCurrentLocation(),
1734 "failed to parse 'priority', of type 'int'");
1735 priority = parsedPriority.value_or(
int());
1737 if (parser.parseRParen())
1740 createAttr(priority);
1745 if (parseGlobalDtorCtor(
"global_ctor", [&](std::optional<int> priority) {
1746 mlir::IntegerAttr globalCtorPriorityAttr =
1747 builder.getI32IntegerAttr(priority.value_or(65535));
1748 state.addAttribute(getGlobalCtorPriorityAttrName(state.name),
1749 globalCtorPriorityAttr);
1753 if (parseGlobalDtorCtor(
"global_dtor", [&](std::optional<int> priority) {
1754 mlir::IntegerAttr globalDtorPriorityAttr =
1755 builder.getI32IntegerAttr(priority.value_or(65535));
1756 state.addAttribute(getGlobalDtorPriorityAttrName(state.name),
1757 globalDtorPriorityAttr);
1762 auto *body = state.addRegion();
1763 OptionalParseResult parseResult = parser.parseOptionalRegion(
1764 *body, arguments,
false);
1765 if (parseResult.has_value()) {
1767 return parser.emitError(loc,
"function alias shall not have a body");
1768 if (failed(*parseResult))
1772 return parser.emitError(loc,
"expected non-empty function body");
1781bool cir::FuncOp::isDeclaration() {
1784 std::optional<StringRef> aliasee = getAliasee();
1786 return getFunctionBody().empty();
1792mlir::Region *cir::FuncOp::getCallableRegion() {
1798void cir::FuncOp::print(OpAsmPrinter &p) {
1814 if (getLinkage() != GlobalLinkageKind::ExternalLinkage)
1815 p <<
' ' << stringifyGlobalLinkageKind(getLinkage());
1817 mlir::SymbolTable::Visibility vis = getVisibility();
1818 if (vis != mlir::SymbolTable::Visibility::Public)
1821 cir::VisibilityAttr cirVisibilityAttr = getGlobalVisibilityAttr();
1822 if (!cirVisibilityAttr.isDefault()) {
1831 p.printSymbolName(getSymName());
1832 cir::FuncType fnType = getFunctionType();
1833 function_interface_impl::printFunctionSignature(
1834 p, *
this, fnType.getInputs(), fnType.isVarArg(), fnType.getReturnTypes());
1836 if (std::optional<StringRef> aliaseeName = getAliasee()) {
1838 p.printSymbolName(*aliaseeName);
1842 if (
auto globalCtorPriority = getGlobalCtorPriority()) {
1843 p <<
" global_ctor";
1844 if (globalCtorPriority.value() != 65535)
1845 p <<
"(" << globalCtorPriority.value() <<
")";
1848 if (
auto globalDtorPriority = getGlobalDtorPriority()) {
1849 p <<
" global_dtor";
1850 if (globalDtorPriority.value() != 65535)
1851 p <<
"(" << globalDtorPriority.value() <<
")";
1855 Region &body = getOperation()->getRegion(0);
1856 if (!body.empty()) {
1858 p.printRegion(body,
false,
1863mlir::LogicalResult cir::FuncOp::verify() {
1865 llvm::SmallSet<llvm::StringRef, 16> labels;
1866 llvm::SmallSet<llvm::StringRef, 16> gotos;
1868 getOperation()->walk([&](mlir::Operation *op) {
1869 if (
auto lab = dyn_cast<cir::LabelOp>(op)) {
1870 labels.insert(lab.getLabel());
1871 }
else if (
auto goTo = dyn_cast<cir::GotoOp>(op)) {
1872 gotos.insert(goTo.getLabel());
1876 if (!labels.empty() || !gotos.empty()) {
1877 llvm::SmallSet<llvm::StringRef, 16> mismatched =
1878 llvm::set_difference(gotos, labels);
1880 if (!mismatched.empty())
1881 return emitOpError() <<
"goto/label mismatch";
1889LogicalResult cir::BinOp::verify() {
1890 bool noWrap = getNoUnsignedWrap() || getNoSignedWrap();
1891 bool saturated = getSaturated();
1893 if (!isa<cir::IntType>(
getType()) && noWrap)
1895 <<
"only operations on integer values may have nsw/nuw flags";
1897 bool noWrapOps =
getKind() == cir::BinOpKind::Add ||
1898 getKind() == cir::BinOpKind::Sub ||
1899 getKind() == cir::BinOpKind::Mul;
1902 getKind() == cir::BinOpKind::Add ||
getKind() == cir::BinOpKind::Sub;
1904 if (noWrap && !noWrapOps)
1905 return emitError() <<
"The nsw/nuw flags are applicable to opcodes: 'add', "
1907 if (saturated && !saturatedOps)
1908 return emitError() <<
"The saturated flag is applicable to opcodes: 'add' "
1910 if (noWrap && saturated)
1911 return emitError() <<
"The nsw/nuw flags and the saturated flag are "
1912 "mutually exclusive";
1914 return mlir::success();
1926void cir::TernaryOp::getSuccessorRegions(
1927 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1929 if (!point.isParent()) {
1930 regions.push_back(RegionSuccessor(this->getODSResults(0)));
1936 regions.push_back(RegionSuccessor(&getTrueRegion()));
1937 regions.push_back(RegionSuccessor(&getFalseRegion()));
1940void cir::TernaryOp::build(
1941 OpBuilder &builder, OperationState &result,
Value cond,
1942 function_ref<
void(OpBuilder &, Location)> trueBuilder,
1943 function_ref<
void(OpBuilder &, Location)> falseBuilder) {
1944 result.addOperands(cond);
1945 OpBuilder::InsertionGuard guard(builder);
1946 Region *trueRegion = result.addRegion();
1947 Block *block = builder.createBlock(trueRegion);
1948 trueBuilder(builder, result.location);
1949 Region *falseRegion = result.addRegion();
1950 builder.createBlock(falseRegion);
1951 falseBuilder(builder, result.location);
1953 auto yield = dyn_cast<YieldOp>(block->getTerminator());
1954 assert((yield && yield.getNumOperands() <= 1) &&
1955 "expected zero or one result type");
1956 if (yield.getNumOperands() == 1)
1957 result.addTypes(TypeRange{yield.getOperandTypes().front()});
1964OpFoldResult cir::SelectOp::fold(FoldAdaptor adaptor) {
1965 mlir::Attribute condition = adaptor.getCondition();
1967 bool conditionValue = mlir::cast<cir::BoolAttr>(condition).getValue();
1968 return conditionValue ? getTrueValue() : getFalseValue();
1972 mlir::Attribute trueValue = adaptor.getTrueValue();
1973 mlir::Attribute falseValue = adaptor.getFalseValue();
1974 if (trueValue == falseValue)
1976 if (getTrueValue() == getFalseValue())
1977 return getTrueValue();
1985LogicalResult cir::ShiftOp::verify() {
1986 mlir::Operation *op = getOperation();
1987 auto op0VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(0).getType());
1988 auto op1VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(1).getType());
1989 if (!op0VecTy ^ !op1VecTy)
1990 return emitOpError() <<
"input types cannot be one vector and one scalar";
1993 if (op0VecTy.getSize() != op1VecTy.getSize())
1994 return emitOpError() <<
"input vector types must have the same size";
1996 auto opResultTy = mlir::dyn_cast<cir::VectorType>(
getType());
1998 return emitOpError() <<
"the type of the result must be a vector "
1999 <<
"if it is vector shift";
2001 auto op0VecEleTy = mlir::cast<cir::IntType>(op0VecTy.getElementType());
2002 auto op1VecEleTy = mlir::cast<cir::IntType>(op1VecTy.getElementType());
2003 if (op0VecEleTy.getWidth() != op1VecEleTy.getWidth())
2004 return emitOpError()
2005 <<
"vector operands do not have the same elements sizes";
2007 auto resVecEleTy = mlir::cast<cir::IntType>(opResultTy.getElementType());
2008 if (op0VecEleTy.getWidth() != resVecEleTy.getWidth())
2009 return emitOpError() <<
"vector operands and result type do not have the "
2010 "same elements sizes";
2013 return mlir::success();
2020LogicalResult cir::LabelOp::verify() {
2021 mlir::Operation *op = getOperation();
2022 mlir::Block *blk = op->getBlock();
2023 if (&blk->front() != op)
2024 return emitError() <<
"must be the first operation in a block";
2026 return mlir::success();
2033LogicalResult cir::UnaryOp::verify() {
2035 case cir::UnaryOpKind::Inc:
2036 case cir::UnaryOpKind::Dec:
2037 case cir::UnaryOpKind::Plus:
2038 case cir::UnaryOpKind::Minus:
2039 case cir::UnaryOpKind::Not:
2044 llvm_unreachable(
"Unknown UnaryOp kind?");
2048 return isa<cir::BoolType>(op.getInput().getType()) &&
2049 op.getKind() == cir::UnaryOpKind::Not;
2061OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) {
2063 mlir::dyn_cast_if_present<cir::PoisonAttr>(adaptor.getInput())) {
2069 if (
auto previous = getInput().getDefiningOp<cir::UnaryOp>())
2071 return previous.getInput();
2080LogicalResult cir::CopyOp::verify() {
2082 if (!
getType().getPointee().hasTrait<DataLayoutTypeInterface::Trait>())
2083 return emitError() <<
"missing data layout for pointee type";
2085 if (getSrc() == getDst())
2086 return emitError() <<
"source and destination are the same";
2088 return mlir::success();
2095LogicalResult cir::GetMemberOp::verify() {
2096 const auto recordTy = dyn_cast<RecordType>(getAddrTy().getPointee());
2098 return emitError() <<
"expected pointer to a record type";
2100 if (recordTy.getMembers().size() <=
getIndex())
2101 return emitError() <<
"member index out of bounds";
2104 return emitError() <<
"member type mismatch";
2106 return mlir::success();
2113OpFoldResult cir::VecCreateOp::fold(FoldAdaptor adaptor) {
2114 if (llvm::any_of(getElements(), [](mlir::Value value) {
2115 return !value.getDefiningOp<cir::ConstantOp>();
2119 return cir::ConstVectorAttr::get(
2120 getType(), mlir::ArrayAttr::get(getContext(), adaptor.getElements()));
2123LogicalResult cir::VecCreateOp::verify() {
2127 const cir::VectorType vecTy =
getType();
2128 if (getElements().size() != vecTy.getSize()) {
2129 return emitOpError() <<
"operand count of " << getElements().size()
2130 <<
" doesn't match vector type " << vecTy
2131 <<
" element count of " << vecTy.getSize();
2134 const mlir::Type elementType = vecTy.getElementType();
2135 for (
const mlir::Value element : getElements()) {
2136 if (element.getType() != elementType) {
2137 return emitOpError() <<
"operand type " << element.getType()
2138 <<
" doesn't match vector element type "
2150OpFoldResult cir::VecExtractOp::fold(FoldAdaptor adaptor) {
2151 const auto vectorAttr =
2152 llvm::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec());
2156 const auto indexAttr =
2157 llvm::dyn_cast_if_present<cir::IntAttr>(adaptor.getIndex());
2161 const mlir::ArrayAttr elements = vectorAttr.getElts();
2162 const uint64_t index = indexAttr.getUInt();
2163 if (index >= elements.size())
2166 return elements[index];
2173OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
2175 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getLhs());
2177 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getRhs());
2178 if (!lhsVecAttr || !rhsVecAttr)
2181 mlir::Type inputElemTy =
2182 mlir::cast<cir::VectorType>(lhsVecAttr.getType()).getElementType();
2183 if (!isAnyIntegerOrFloatingPointType(inputElemTy))
2186 cir::CmpOpKind opKind = adaptor.getKind();
2187 mlir::ArrayAttr lhsVecElhs = lhsVecAttr.getElts();
2188 mlir::ArrayAttr rhsVecElhs = rhsVecAttr.getElts();
2189 uint64_t vecSize = lhsVecElhs.size();
2192 bool isIntAttr = vecSize && mlir::isa<cir::IntAttr>(lhsVecElhs[0]);
2193 for (uint64_t i = 0; i < vecSize; i++) {
2194 mlir::Attribute lhsAttr = lhsVecElhs[i];
2195 mlir::Attribute rhsAttr = rhsVecElhs[i];
2198 case cir::CmpOpKind::lt: {
2200 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <
2201 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
2203 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <
2204 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
2208 case cir::CmpOpKind::le: {
2210 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <=
2211 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
2213 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <=
2214 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
2218 case cir::CmpOpKind::gt: {
2220 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >
2221 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
2223 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >
2224 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
2228 case cir::CmpOpKind::ge: {
2230 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >=
2231 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
2233 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >=
2234 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
2238 case cir::CmpOpKind::eq: {
2240 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() ==
2241 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
2243 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() ==
2244 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
2248 case cir::CmpOpKind::ne: {
2250 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() !=
2251 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
2253 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() !=
2254 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
2260 elements[i] = cir::IntAttr::get(
getType().getElementType(), cmpResult);
2263 return cir::ConstVectorAttr::get(
2264 getType(), mlir::ArrayAttr::get(getContext(), elements));
2271OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor adaptor) {
2273 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec1());
2275 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec2());
2276 if (!vec1Attr || !vec2Attr)
2279 mlir::Type vec1ElemTy =
2280 mlir::cast<cir::VectorType>(vec1Attr.getType()).getElementType();
2282 mlir::ArrayAttr vec1Elts = vec1Attr.getElts();
2283 mlir::ArrayAttr vec2Elts = vec2Attr.getElts();
2284 mlir::ArrayAttr indicesElts = adaptor.getIndices();
2287 elements.reserve(indicesElts.size());
2289 uint64_t vec1Size = vec1Elts.size();
2290 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
2291 if (idxAttr.getSInt() == -1) {
2292 elements.push_back(cir::UndefAttr::get(vec1ElemTy));
2296 uint64_t idxValue = idxAttr.getUInt();
2297 elements.push_back(idxValue < vec1Size ? vec1Elts[idxValue]
2298 : vec2Elts[idxValue - vec1Size]);
2301 return cir::ConstVectorAttr::get(
2302 getType(), mlir::ArrayAttr::get(getContext(), elements));
2305LogicalResult cir::VecShuffleOp::verify() {
2308 if (getIndices().size() != getResult().
getType().getSize()) {
2309 return emitOpError() <<
": the number of elements in " << getIndices()
2310 <<
" and " << getResult().getType() <<
" don't match";
2315 if (getVec1().
getType().getElementType() !=
2316 getResult().
getType().getElementType()) {
2317 return emitOpError() <<
": element types of " << getVec1().getType()
2318 <<
" and " << getResult().getType() <<
" don't match";
2321 const uint64_t maxValidIndex =
2322 getVec1().getType().getSize() + getVec2().getType().getSize() - 1;
2324 getIndices().getAsRange<cir::IntAttr>(), [&](cir::IntAttr idxAttr) {
2325 return idxAttr.getSInt() != -1 && idxAttr.getUInt() > maxValidIndex;
2327 return emitOpError() <<
": index for __builtin_shufflevector must be "
2328 "less than the total number of vector elements";
2337OpFoldResult cir::VecShuffleDynamicOp::fold(FoldAdaptor adaptor) {
2338 mlir::Attribute vec = adaptor.getVec();
2339 mlir::Attribute indices = adaptor.getIndices();
2340 if (mlir::isa_and_nonnull<cir::ConstVectorAttr>(vec) &&
2341 mlir::isa_and_nonnull<cir::ConstVectorAttr>(indices)) {
2342 auto vecAttr = mlir::cast<cir::ConstVectorAttr>(vec);
2343 auto indicesAttr = mlir::cast<cir::ConstVectorAttr>(indices);
2345 mlir::ArrayAttr vecElts = vecAttr.getElts();
2346 mlir::ArrayAttr indicesElts = indicesAttr.getElts();
2348 const uint64_t numElements = vecElts.size();
2351 elements.reserve(numElements);
2353 const uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
2354 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
2355 uint64_t idxValue = idxAttr.getUInt();
2356 uint64_t newIdx = idxValue & maskBits;
2357 elements.push_back(vecElts[newIdx]);
2360 return cir::ConstVectorAttr::get(
2361 getType(), mlir::ArrayAttr::get(getContext(), elements));
2367LogicalResult cir::VecShuffleDynamicOp::verify() {
2369 if (getVec().
getType().getSize() !=
2370 mlir::cast<cir::VectorType>(getIndices().
getType()).getSize()) {
2371 return emitOpError() <<
": the number of elements in " << getVec().getType()
2372 <<
" and " << getIndices().getType() <<
" don't match";
2381LogicalResult cir::VecTernaryOp::verify() {
2386 if (getCond().
getType().getSize() != getLhs().
getType().getSize()) {
2387 return emitOpError() <<
": the number of elements in "
2388 << getCond().getType() <<
" and " << getLhs().getType()
2394OpFoldResult cir::VecTernaryOp::fold(FoldAdaptor adaptor) {
2395 mlir::Attribute cond = adaptor.getCond();
2396 mlir::Attribute lhs = adaptor.getLhs();
2397 mlir::Attribute rhs = adaptor.getRhs();
2399 if (!mlir::isa_and_nonnull<cir::ConstVectorAttr>(cond) ||
2400 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(lhs) ||
2401 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(rhs))
2403 auto condVec = mlir::cast<cir::ConstVectorAttr>(cond);
2404 auto lhsVec = mlir::cast<cir::ConstVectorAttr>(lhs);
2405 auto rhsVec = mlir::cast<cir::ConstVectorAttr>(rhs);
2407 mlir::ArrayAttr condElts = condVec.getElts();
2410 elements.reserve(condElts.size());
2412 for (
const auto &[idx, condAttr] :
2413 llvm::enumerate(condElts.getAsRange<cir::IntAttr>())) {
2414 if (condAttr.getSInt()) {
2415 elements.push_back(lhsVec.getElts()[idx]);
2417 elements.push_back(rhsVec.getElts()[idx]);
2421 cir::VectorType vecTy = getLhs().getType();
2422 return cir::ConstVectorAttr::get(
2423 vecTy, mlir::ArrayAttr::get(getContext(), elements));
2430LogicalResult cir::ComplexCreateOp::verify() {
2433 <<
"operand type of cir.complex.create does not match its result type";
2440OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) {
2441 mlir::Attribute real = adaptor.getReal();
2442 mlir::Attribute imag = adaptor.getImag();
2448 auto realAttr = mlir::cast<mlir::TypedAttr>(real);
2449 auto imagAttr = mlir::cast<mlir::TypedAttr>(imag);
2450 return cir::ConstComplexAttr::get(realAttr, imagAttr);
2457LogicalResult cir::ComplexRealOp::verify() {
2458 mlir::Type operandTy = getOperand().getType();
2459 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
2460 operandTy = complexOperandTy.getElementType();
2463 emitOpError() <<
": result type does not match operand type";
2470OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) {
2471 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
2474 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
2475 return complexCreateOp.getOperand(0);
2478 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
2479 return complex ? complex.getReal() :
nullptr;
2486LogicalResult cir::ComplexImagOp::verify() {
2487 mlir::Type operandTy = getOperand().getType();
2488 if (
auto complexOperandTy = mlir::dyn_cast<cir::ComplexType>(operandTy))
2489 operandTy = complexOperandTy.getElementType();
2492 emitOpError() <<
": result type does not match operand type";
2499OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) {
2500 if (!mlir::isa<cir::ComplexType>(getOperand().
getType()))
2503 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
2504 return complexCreateOp.getOperand(1);
2507 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
2508 return complex ? complex.getImag() :
nullptr;
2515LogicalResult cir::ComplexRealPtrOp::verify() {
2516 mlir::Type resultPointeeTy =
getType().getPointee();
2517 cir::PointerType operandPtrTy = getOperand().getType();
2518 auto operandPointeeTy =
2519 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
2521 if (resultPointeeTy != operandPointeeTy.getElementType()) {
2522 return emitOpError() <<
": result type does not match operand type";
2532LogicalResult cir::ComplexImagPtrOp::verify() {
2533 mlir::Type resultPointeeTy =
getType().getPointee();
2534 cir::PointerType operandPtrTy = getOperand().getType();
2535 auto operandPointeeTy =
2536 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
2538 if (resultPointeeTy != operandPointeeTy.getElementType()) {
2539 return emitOpError()
2540 <<
"cir.complex.imag_ptr result type does not match operand type";
2551 llvm::function_ref<llvm::APInt(
const llvm::APInt &)> func,
2552 bool poisonZero =
false) {
2553 if (mlir::isa_and_present<cir::PoisonAttr>(inputAttr)) {
2558 auto input = mlir::dyn_cast_if_present<IntAttr>(inputAttr);
2562 llvm::APInt inputValue = input.getValue();
2563 if (poisonZero && inputValue.isZero())
2564 return cir::PoisonAttr::get(input.getType());
2566 llvm::APInt resultValue = func(inputValue);
2567 return IntAttr::get(input.getType(), resultValue);
2570OpFoldResult BitClrsbOp::fold(FoldAdaptor adaptor) {
2571 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
2572 unsigned resultValue =
2573 inputValue.getBitWidth() - inputValue.getSignificantBits();
2574 return llvm::APInt(inputValue.getBitWidth(), resultValue);
2578OpFoldResult BitClzOp::fold(FoldAdaptor adaptor) {
2581 [](
const llvm::APInt &inputValue) {
2582 unsigned resultValue = inputValue.countLeadingZeros();
2583 return llvm::APInt(inputValue.getBitWidth(), resultValue);
2588OpFoldResult BitCtzOp::fold(FoldAdaptor adaptor) {
2591 [](
const llvm::APInt &inputValue) {
2592 return llvm::APInt(inputValue.getBitWidth(),
2593 inputValue.countTrailingZeros());
2598OpFoldResult BitFfsOp::fold(FoldAdaptor adaptor) {
2599 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
2600 unsigned trailingZeros = inputValue.countTrailingZeros();
2602 trailingZeros == inputValue.getBitWidth() ? 0 : trailingZeros + 1;
2603 return llvm::APInt(inputValue.getBitWidth(), result);
2607OpFoldResult BitParityOp::fold(FoldAdaptor adaptor) {
2608 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
2609 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount() % 2);
2613OpFoldResult BitPopcountOp::fold(FoldAdaptor adaptor) {
2614 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
2615 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount());
2619OpFoldResult BitReverseOp::fold(FoldAdaptor adaptor) {
2620 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
2621 return inputValue.reverseBits();
2625OpFoldResult ByteSwapOp::fold(FoldAdaptor adaptor) {
2626 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
2627 return inputValue.byteSwap();
2631OpFoldResult RotateOp::fold(FoldAdaptor adaptor) {
2632 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()) ||
2633 mlir::isa_and_present<cir::PoisonAttr>(adaptor.getAmount())) {
2635 return cir::PoisonAttr::get(
getType());
2638 auto input = mlir::dyn_cast_if_present<IntAttr>(adaptor.getInput());
2639 auto amount = mlir::dyn_cast_if_present<IntAttr>(adaptor.getAmount());
2640 if (!input && !amount)
2649 llvm::APInt inputValue;
2651 inputValue = input.getValue();
2652 if (inputValue.isZero() || inputValue.isAllOnes()) {
2658 uint64_t amountValue;
2660 amountValue = amount.getValue().urem(getInput().
getType().getWidth());
2661 if (amountValue == 0) {
2667 if (!input || !amount)
2670 assert(inputValue.getBitWidth() == getInput().
getType().getWidth() &&
2671 "input value must have the same bit width as the input type");
2673 llvm::APInt resultValue;
2675 resultValue = inputValue.rotl(amountValue);
2677 resultValue = inputValue.rotr(amountValue);
2679 return IntAttr::get(input.getContext(), input.getType(), resultValue);
2686void cir::InlineAsmOp::print(OpAsmPrinter &p) {
2687 p <<
'(' << getAsmFlavor() <<
", ";
2692 auto *nameIt = names.begin();
2693 auto *attrIt = getOperandAttrs().begin();
2695 for (mlir::OperandRange ops : getAsmOperands()) {
2696 p << *nameIt <<
" = ";
2699 llvm::interleaveComma(llvm::make_range(ops.begin(), ops.end()), p,
2701 p.printOperand(value);
2702 p <<
" : " << value.getType();
2704 p <<
" (maybe_memory)";
2713 p.printString(getAsmString());
2715 p.printString(getConstraints());
2719 if (getSideEffects())
2720 p <<
" side_effects";
2722 std::array elidedAttrs{
2723 llvm::StringRef(
"asm_flavor"), llvm::StringRef(
"asm_string"),
2724 llvm::StringRef(
"constraints"), llvm::StringRef(
"operand_attrs"),
2725 llvm::StringRef(
"operands_segments"), llvm::StringRef(
"side_effects")};
2726 p.printOptionalAttrDict(getOperation()->getAttrs(), elidedAttrs);
2728 if (
auto v = getRes())
2729 p <<
" -> " << v.getType();
2732void cir::InlineAsmOp::build(OpBuilder &odsBuilder, OperationState &odsState,
2734 StringRef asmString, StringRef constraints,
2735 bool sideEffects, cir::AsmFlavor asmFlavor,
2739 for (
auto operandRange : asmOperands) {
2740 segments.push_back(operandRange.size());
2741 odsState.addOperands(operandRange);
2744 odsState.addAttribute(
2745 "operands_segments",
2746 DenseI32ArrayAttr::get(odsBuilder.getContext(), segments));
2747 odsState.addAttribute(
"asm_string", odsBuilder.getStringAttr(asmString));
2748 odsState.addAttribute(
"constraints", odsBuilder.getStringAttr(constraints));
2749 odsState.addAttribute(
"asm_flavor",
2750 AsmFlavorAttr::get(odsBuilder.getContext(), asmFlavor));
2753 odsState.addAttribute(
"side_effects", odsBuilder.getUnitAttr());
2755 odsState.addAttribute(
"operand_attrs", odsBuilder.getArrayAttr(operandAttrs));
2758ParseResult cir::InlineAsmOp::parse(OpAsmParser &parser,
2759 OperationState &result) {
2762 std::string asmString, constraints;
2764 MLIRContext *ctxt = parser.getBuilder().getContext();
2766 auto error = [&](
const Twine &msg) -> LogicalResult {
2767 return parser.emitError(parser.getCurrentLocation(), msg);
2770 auto expected = [&](
const std::string &
c) {
2771 return error(
"expected '" +
c +
"'");
2774 if (parser.parseLParen().failed())
2775 return expected(
"(");
2777 auto flavor = FieldParser<AsmFlavor, AsmFlavor>::parse(parser);
2779 return error(
"Unknown AsmFlavor");
2781 if (parser.parseComma().failed())
2782 return expected(
",");
2784 auto parseValue = [&](
Value &v) {
2785 OpAsmParser::UnresolvedOperand op;
2787 if (parser.parseOperand(op) || parser.parseColon())
2788 return error(
"can't parse operand");
2791 if (parser.parseType(typ).failed())
2792 return error(
"can't parse operand type");
2794 if (parser.resolveOperand(op, typ, tmp))
2795 return error(
"can't resolve operand");
2797 return mlir::success();
2800 auto parseOperands = [&](llvm::StringRef
name) {
2801 if (parser.parseKeyword(name).failed())
2802 return error(
"expected " + name +
" operands here");
2803 if (parser.parseEqual().failed())
2804 return expected(
"=");
2805 if (parser.parseLSquare().failed())
2806 return expected(
"[");
2809 if (parser.parseOptionalRSquare().succeeded()) {
2810 operandsGroupSizes.push_back(size);
2811 if (parser.parseComma())
2812 return expected(
",");
2813 return mlir::success();
2816 auto parseOperand = [&]() {
2818 if (parseValue(val).succeeded()) {
2819 result.operands.push_back(val);
2822 if (parser.parseOptionalLParen().failed()) {
2823 operandAttrs.push_back(mlir::Attribute());
2824 return mlir::success();
2827 if (parser.parseKeyword(
"maybe_memory").succeeded()) {
2828 operandAttrs.push_back(mlir::UnitAttr::get(ctxt));
2829 if (parser.parseRParen())
2830 return expected(
")");
2831 return mlir::success();
2833 return expected(
"maybe_memory");
2836 return mlir::failure();
2839 if (parser.parseCommaSeparatedList(parseOperand).failed())
2840 return mlir::failure();
2842 if (parser.parseRSquare().failed() || parser.parseComma().failed())
2843 return expected(
"]");
2844 operandsGroupSizes.push_back(size);
2845 return mlir::success();
2848 if (parseOperands(
"out").failed() || parseOperands(
"in").failed() ||
2849 parseOperands(
"in_out").failed())
2850 return error(
"failed to parse operands");
2852 if (parser.parseLBrace())
2853 return expected(
"{");
2854 if (parser.parseString(&asmString))
2855 return error(
"asm string parsing failed");
2856 if (parser.parseString(&constraints))
2857 return error(
"constraints string parsing failed");
2858 if (parser.parseRBrace())
2859 return expected(
"}");
2860 if (parser.parseRParen())
2861 return expected(
")");
2863 if (parser.parseOptionalKeyword(
"side_effects").succeeded())
2864 result.attributes.set(
"side_effects", UnitAttr::get(ctxt));
2866 if (parser.parseOptionalArrow().succeeded() &&
2867 parser.parseType(resType).failed())
2868 return mlir::failure();
2870 if (parser.parseOptionalAttrDict(result.attributes).failed())
2871 return mlir::failure();
2873 result.attributes.set(
"asm_flavor", AsmFlavorAttr::get(ctxt, *flavor));
2874 result.attributes.set(
"asm_string", StringAttr::get(ctxt, asmString));
2875 result.attributes.set(
"constraints", StringAttr::get(ctxt, constraints));
2876 result.attributes.set(
"operand_attrs", ArrayAttr::get(ctxt, operandAttrs));
2877 result.getOrAddProperties<InlineAsmOp::Properties>().operands_segments =
2878 parser.getBuilder().getDenseI32ArrayAttr(operandsGroupSizes);
2880 result.addTypes(TypeRange{resType});
2882 return mlir::success();
2889mlir::LogicalResult cir::ThrowOp::verify() {
2894 if (getNumOperands() != 0) {
2897 return emitOpError() <<
"'type_info' symbol attribute missing";
2907LogicalResult cir::TypeInfoAttr::verify(
2908 ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
2909 ::mlir::Type type, ::mlir::ArrayAttr typeInfoData) {
2911 if (cir::ConstRecordAttr::verify(emitError, type, typeInfoData).failed())
2921#define GET_OP_CLASSES
2922#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)
static mlir::LogicalResult checkReturnAndFunction(cir::ReturnOp op, cir::FuncOp function)
static bool isBoolNot(cir::UnaryOp op)
static bool isIntOrBoolCast(cir::CastOp op)
static void printConstant(OpAsmPrinter &p, Attribute value)
static mlir::ParseResult parseOmittedTerminatorRegion(mlir::OpAsmParser &parser, mlir::Region ®ion)
void printVisibilityAttr(OpAsmPrinter &printer, cir::VisibilityAttr &visibility)
static ParseResult parseSwitchFlatOpCases(OpAsmParser &parser, Type flagType, mlir::ArrayAttr &caseValues, SmallVectorImpl< Block * > &caseDestinations, SmallVectorImpl< llvm::SmallVector< OpAsmParser::UnresolvedOperand > > &caseOperands, SmallVectorImpl< llvm::SmallVector< Type > > &caseOperandTypes)
<cases> ::= [ (case (, case )* )?
static LogicalResult verifyCallCommInSymbolUses(mlir::Operation *op, SymbolTableCollection &symbolTable)
static LogicalResult ensureRegionTerm(OpAsmParser &parser, Region ®ion, SMLoc errLoc)
static ParseResult parseGlobalOpTypeAndInitialValue(OpAsmParser &parser, TypeAttr &typeAttr, Attribute &initialValueAttr, mlir::Region &ctorRegion, mlir::Region &dtorRegion)
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 void printSwitchOp(OpAsmPrinter &p, cir::SwitchOp op, mlir::Region &bodyRegion, mlir::Value condition, mlir::Type condType)
static void printGlobalOpTypeAndInitialValue(OpAsmPrinter &p, cir::GlobalOp op, TypeAttr type, Attribute initAttr, mlir::Region &ctorRegion, mlir::Region &dtorRegion)
static ParseResult parseCIRKeyword(AsmParser &parser, RetTy &result)
Parse an enum from the keyword, return failure if the keyword is not found.
static Value tryFoldCastChain(cir::CastOp op)
void parseVisibilityAttr(OpAsmParser &parser, cir::VisibilityAttr &visibility)
static bool omitRegionTerm(mlir::Region &r)
static void printOmittedTerminatorRegion(mlir::OpAsmPrinter &printer, cir::ScopeOp &op, mlir::Region ®ion)
static ParseResult parseConstantValue(OpAsmParser &parser, mlir::Attribute &valueAttr)
static void printCallCommon(mlir::Operation *op, mlir::FlatSymbolRefAttr calleeSym, mlir::Value indirectCallee, mlir::OpAsmPrinter &printer, bool isNothrow, cir::SideEffect sideEffect)
static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType, mlir::Attribute attrType)
static ParseResult parseSwitchOp(OpAsmParser &parser, mlir::Region ®ions, mlir::OpAsmParser::UnresolvedOperand &cond, mlir::Type &condType)
static mlir::ParseResult parseCallCommon(mlir::OpAsmParser &parser, mlir::OperationState &result)
#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)
__device__ __2f16 float c
void buildTerminatedBody(mlir::OpBuilder &builder, mlir::Location loc)
const AstTypeMatcher< RecordType > recordType
StringRef getName(const HeaderType T)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
static bool addressSpace()
static bool opGlobalThreadLocal()
static bool opCallCallConv()
static bool opScopeCleanupRegion()
static bool supportIFuncAttr()