18#include "mlir/Interfaces/ControlFlowInterfaces.h"
19#include "mlir/Interfaces/FunctionImplementation.h"
20#include "mlir/Support/LLVM.h"
22#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
23#include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc"
25#include "llvm/ADT/SetOperations.h"
26#include "llvm/ADT/SmallSet.h"
27#include "llvm/Support/LogicalResult.h"
36struct CIROpAsmDialectInterface :
public OpAsmDialectInterface {
37 using OpAsmDialectInterface::OpAsmDialectInterface;
39 AliasResult getAlias(Type type, raw_ostream &os)
const final {
40 if (
auto recordType = dyn_cast<cir::RecordType>(type)) {
43 os <<
"rec_anon_" <<
recordType.getKindAsStr();
45 os <<
"rec_" << nameAttr.getValue();
46 return AliasResult::OverridableAlias;
48 if (
auto intType = dyn_cast<cir::IntType>(type)) {
51 unsigned width = intType.getWidth();
52 if (width < 8 || !llvm::isPowerOf2_32(width))
53 return AliasResult::NoAlias;
54 os << intType.getAlias();
55 return AliasResult::OverridableAlias;
57 if (
auto voidType = dyn_cast<cir::VoidType>(type)) {
58 os << voidType.getAlias();
59 return AliasResult::OverridableAlias;
62 return AliasResult::NoAlias;
65 AliasResult getAlias(Attribute attr, raw_ostream &os)
const final {
66 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr)) {
67 os << (boolAttr.getValue() ?
"true" :
"false");
68 return AliasResult::FinalAlias;
70 if (
auto bitfield = mlir::dyn_cast<cir::BitfieldInfoAttr>(attr)) {
71 os <<
"bfi_" << bitfield.getName().str();
72 return AliasResult::FinalAlias;
74 return AliasResult::NoAlias;
79void cir::CIRDialect::initialize() {
84#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
86 addInterfaces<CIROpAsmDialectInterface>();
89Operation *cir::CIRDialect::materializeConstant(mlir::OpBuilder &builder,
90 mlir::Attribute value,
93 return builder.create<cir::ConstantOp>(loc, type,
94 mlir::cast<mlir::TypedAttr>(value));
106 for (
auto en : llvm::enumerate(keywords)) {
107 if (succeeded(parser.parseOptionalKeyword(en.value())))
114template <
typename Ty>
struct EnumTraits {};
116#define REGISTER_ENUM_TYPE(Ty) \
117 template <> struct EnumTraits<cir::Ty> { \
118 static llvm::StringRef stringify(cir::Ty value) { \
119 return stringify##Ty(value); \
121 static unsigned getMaxEnumVal() { return cir::getMaxEnumValFor##Ty(); } \
132template <
typename EnumTy,
typename RetTy = EnumTy>
135 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
136 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
140 return static_cast<RetTy
>(defaultValue);
141 return static_cast<RetTy
>(index);
145template <
typename EnumTy,
typename RetTy = EnumTy>
148 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
149 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
154 result =
static_cast<RetTy
>(index);
162 Location eLoc = parser.getEncodedSourceLoc(parser.getCurrentLocation());
163 OpBuilder builder(parser.getBuilder().getContext());
168 builder.createBlock(®ion);
170 Block &block = region.back();
172 if (!block.empty() && block.back().hasTrait<OpTrait::IsTerminator>())
176 if (!region.hasOneBlock())
177 return parser.emitError(errLoc,
178 "multi-block region must not omit terminator");
181 builder.setInsertionPointToEnd(&block);
182 builder.create<cir::YieldOp>(eLoc);
188 const auto singleNonEmptyBlock = r.hasOneBlock() && !r.back().empty();
189 const auto yieldsNothing = [&r]() {
190 auto y = dyn_cast<cir::YieldOp>(r.back().getTerminator());
191 return y && y.getArgs().empty();
193 return singleNonEmptyBlock && yieldsNothing();
197 cir::VisibilityAttr &visibility) {
198 switch (visibility.getValue()) {
199 case cir::VisibilityKind::Hidden:
202 case cir::VisibilityKind::Protected:
203 printer <<
"protected";
205 case cir::VisibilityKind::Default:
211 cir::VisibilityKind visibilityKind =
213 visibility = cir::VisibilityAttr::get(parser.getContext(), visibilityKind);
221 mlir::Region ®ion) {
222 auto regionLoc = parser.getCurrentLocation();
223 if (parser.parseRegion(region))
232 mlir::Region ®ion) {
233 printer.printRegion(region,
242void cir::AllocaOp::build(mlir::OpBuilder &odsBuilder,
243 mlir::OperationState &odsState, mlir::Type addr,
244 mlir::Type allocaType, llvm::StringRef name,
245 mlir::IntegerAttr alignment) {
246 odsState.addAttribute(getAllocaTypeAttrName(odsState.name),
247 mlir::TypeAttr::get(allocaType));
248 odsState.addAttribute(getNameAttrName(odsState.name),
249 odsBuilder.getStringAttr(name));
251 odsState.addAttribute(getAlignmentAttrName(odsState.name), alignment);
253 odsState.addTypes(addr);
260LogicalResult cir::BreakOp::verify() {
262 if (!getOperation()->getParentOfType<LoopOpInterface>() &&
263 !getOperation()->getParentOfType<SwitchOp>())
264 return emitOpError(
"must be within a loop");
276void cir::ConditionOp::getSuccessorRegions(
282 if (
auto loopOp = dyn_cast<LoopOpInterface>(getOperation()->getParentOp())) {
283 regions.emplace_back(&loopOp.getBody(), loopOp.getBody().getArguments());
284 regions.emplace_back(loopOp->getResults());
291cir::ConditionOp::getMutableSuccessorOperands(RegionBranchPoint point) {
293 return MutableOperandRange(getOperation(), 0, 0);
296LogicalResult cir::ConditionOp::verify() {
298 if (!isa<LoopOpInterface>(getOperation()->getParentOp()))
299 return emitOpError(
"condition must be within a conditional region");
308 mlir::Attribute attrType) {
309 if (isa<cir::ConstPtrAttr>(attrType)) {
310 if (!mlir::isa<cir::PointerType>(opType))
311 return op->emitOpError(
312 "pointer constant initializing a non-pointer type");
316 if (isa<cir::ZeroAttr>(attrType)) {
317 if (isa<cir::RecordType, cir::ArrayType, cir::VectorType, cir::ComplexType>(
320 return op->emitOpError(
321 "zero expects struct, array, vector, or complex type");
324 if (mlir::isa<cir::BoolAttr>(attrType)) {
325 if (!mlir::isa<cir::BoolType>(opType))
326 return op->emitOpError(
"result type (")
327 << opType <<
") must be '!cir.bool' for '" << attrType <<
"'";
331 if (mlir::isa<cir::IntAttr, cir::FPAttr>(attrType)) {
332 auto at = cast<TypedAttr>(attrType);
333 if (at.getType() != opType) {
334 return op->emitOpError(
"result type (")
335 << opType <<
") does not match value type (" << at.getType()
341 if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
342 cir::ConstComplexAttr, cir::ConstRecordAttr,
343 cir::GlobalViewAttr, cir::PoisonAttr, cir::TypeInfoAttr,
344 cir::VTableAttr>(attrType))
347 assert(isa<TypedAttr>(attrType) &&
"What else could we be looking at here?");
348 return op->emitOpError(
"global with type ")
349 << cast<TypedAttr>(attrType).getType() <<
" not yet supported";
352LogicalResult cir::ConstantOp::verify() {
359OpFoldResult cir::ConstantOp::fold(FoldAdaptor ) {
367LogicalResult cir::ContinueOp::verify() {
368 if (!getOperation()->getParentOfType<LoopOpInterface>())
369 return emitOpError(
"must be within a loop");
377LogicalResult cir::CastOp::verify() {
378 mlir::Type resType =
getType();
379 mlir::Type srcType = getSrc().getType();
381 if (mlir::isa<cir::VectorType>(srcType) &&
382 mlir::isa<cir::VectorType>(resType)) {
385 srcType = mlir::dyn_cast<cir::VectorType>(srcType).getElementType();
386 resType = mlir::dyn_cast<cir::VectorType>(resType).getElementType();
390 case cir::CastKind::int_to_bool: {
391 if (!mlir::isa<cir::BoolType>(resType))
392 return emitOpError() <<
"requires !cir.bool type for result";
393 if (!mlir::isa<cir::IntType>(srcType))
394 return emitOpError() <<
"requires !cir.int type for source";
397 case cir::CastKind::ptr_to_bool: {
398 if (!mlir::isa<cir::BoolType>(resType))
399 return emitOpError() <<
"requires !cir.bool type for result";
400 if (!mlir::isa<cir::PointerType>(srcType))
401 return emitOpError() <<
"requires !cir.ptr type for source";
404 case cir::CastKind::integral: {
405 if (!mlir::isa<cir::IntType>(resType))
406 return emitOpError() <<
"requires !cir.int type for result";
407 if (!mlir::isa<cir::IntType>(srcType))
408 return emitOpError() <<
"requires !cir.int type for source";
411 case cir::CastKind::array_to_ptrdecay: {
412 const auto arrayPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
413 const auto flatPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
414 if (!arrayPtrTy || !flatPtrTy)
415 return emitOpError() <<
"requires !cir.ptr type for source and result";
420 case cir::CastKind::bitcast: {
422 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
423 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
425 if (srcPtrTy && resPtrTy) {
431 case cir::CastKind::floating: {
432 if (!mlir::isa<cir::FPTypeInterface>(srcType) ||
433 !mlir::isa<cir::FPTypeInterface>(resType))
434 return emitOpError() <<
"requires !cir.float type for source and result";
437 case cir::CastKind::float_to_int: {
438 if (!mlir::isa<cir::FPTypeInterface>(srcType))
439 return emitOpError() <<
"requires !cir.float type for source";
440 if (!mlir::dyn_cast<cir::IntType>(resType))
441 return emitOpError() <<
"requires !cir.int type for result";
444 case cir::CastKind::int_to_ptr: {
445 if (!mlir::dyn_cast<cir::IntType>(srcType))
446 return emitOpError() <<
"requires !cir.int type for source";
447 if (!mlir::dyn_cast<cir::PointerType>(resType))
448 return emitOpError() <<
"requires !cir.ptr type for result";
451 case cir::CastKind::ptr_to_int: {
452 if (!mlir::dyn_cast<cir::PointerType>(srcType))
453 return emitOpError() <<
"requires !cir.ptr type for source";
454 if (!mlir::dyn_cast<cir::IntType>(resType))
455 return emitOpError() <<
"requires !cir.int type for result";
458 case cir::CastKind::float_to_bool: {
459 if (!mlir::isa<cir::FPTypeInterface>(srcType))
460 return emitOpError() <<
"requires !cir.float type for source";
461 if (!mlir::isa<cir::BoolType>(resType))
462 return emitOpError() <<
"requires !cir.bool type for result";
465 case cir::CastKind::bool_to_int: {
466 if (!mlir::isa<cir::BoolType>(srcType))
467 return emitOpError() <<
"requires !cir.bool type for source";
468 if (!mlir::isa<cir::IntType>(resType))
469 return emitOpError() <<
"requires !cir.int type for result";
472 case cir::CastKind::int_to_float: {
473 if (!mlir::isa<cir::IntType>(srcType))
474 return emitOpError() <<
"requires !cir.int type for source";
475 if (!mlir::isa<cir::FPTypeInterface>(resType))
476 return emitOpError() <<
"requires !cir.float type for result";
479 case cir::CastKind::bool_to_float: {
480 if (!mlir::isa<cir::BoolType>(srcType))
481 return emitOpError() <<
"requires !cir.bool type for source";
482 if (!mlir::isa<cir::FPTypeInterface>(resType))
483 return emitOpError() <<
"requires !cir.float type for result";
486 case cir::CastKind::address_space: {
487 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
488 auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
489 if (!srcPtrTy || !resPtrTy)
490 return emitOpError() <<
"requires !cir.ptr type for source and result";
491 if (srcPtrTy.getPointee() != resPtrTy.getPointee())
492 return emitOpError() <<
"requires two types differ in addrspace only";
495 case cir::CastKind::float_to_complex: {
496 if (!mlir::isa<cir::FPTypeInterface>(srcType))
497 return emitOpError() <<
"requires !cir.float type for source";
498 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
500 return emitOpError() <<
"requires !cir.complex type for result";
501 if (srcType != resComplexTy.getElementType())
502 return emitOpError() <<
"requires source type match result element type";
505 case cir::CastKind::int_to_complex: {
506 if (!mlir::isa<cir::IntType>(srcType))
507 return emitOpError() <<
"requires !cir.int type for source";
508 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
510 return emitOpError() <<
"requires !cir.complex type for result";
511 if (srcType != resComplexTy.getElementType())
512 return emitOpError() <<
"requires source type match result element type";
515 case cir::CastKind::float_complex_to_real: {
516 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
518 return emitOpError() <<
"requires !cir.complex type for source";
519 if (!mlir::isa<cir::FPTypeInterface>(resType))
520 return emitOpError() <<
"requires !cir.float type for result";
521 if (srcComplexTy.getElementType() != resType)
522 return emitOpError() <<
"requires source element type match result type";
525 case cir::CastKind::int_complex_to_real: {
526 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
528 return emitOpError() <<
"requires !cir.complex type for source";
529 if (!mlir::isa<cir::IntType>(resType))
530 return emitOpError() <<
"requires !cir.int type for result";
531 if (srcComplexTy.getElementType() != resType)
532 return emitOpError() <<
"requires source element type match result type";
535 case cir::CastKind::float_complex_to_bool: {
536 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
537 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
539 <<
"requires floating point !cir.complex type for source";
540 if (!mlir::isa<cir::BoolType>(resType))
541 return emitOpError() <<
"requires !cir.bool type for result";
544 case cir::CastKind::int_complex_to_bool: {
545 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
546 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
548 <<
"requires floating point !cir.complex type for source";
549 if (!mlir::isa<cir::BoolType>(resType))
550 return emitOpError() <<
"requires !cir.bool type for result";
553 case cir::CastKind::float_complex: {
554 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
555 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
557 <<
"requires floating point !cir.complex type for source";
558 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
559 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
561 <<
"requires floating point !cir.complex type for result";
564 case cir::CastKind::float_complex_to_int_complex: {
565 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
566 if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
568 <<
"requires floating point !cir.complex type for source";
569 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
570 if (!resComplexTy || !resComplexTy.isIntegerComplex())
571 return emitOpError() <<
"requires integer !cir.complex type for result";
574 case cir::CastKind::int_complex: {
575 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
576 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
577 return emitOpError() <<
"requires integer !cir.complex type for source";
578 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
579 if (!resComplexTy || !resComplexTy.isIntegerComplex())
580 return emitOpError() <<
"requires integer !cir.complex type for result";
583 case cir::CastKind::int_complex_to_float_complex: {
584 auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
585 if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
586 return emitOpError() <<
"requires integer !cir.complex type for source";
587 auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
588 if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
590 <<
"requires floating point !cir.complex type for result";
594 llvm_unreachable(
"Unknown CastOp kind?");
599 auto kind = op.getKind();
600 return kind == cir::CastKind::bool_to_int ||
601 kind == cir::CastKind::int_to_bool || kind == cir::CastKind::integral;
605 cir::CastOp head = op, tail = op;
611 op = head.getSrc().getDefiningOp<cir::CastOp>();
619 if (head.getKind() == cir::CastKind::bool_to_int &&
620 tail.getKind() == cir::CastKind::int_to_bool)
621 return head.getSrc();
626 if (head.getKind() == cir::CastKind::int_to_bool &&
627 tail.getKind() == cir::CastKind::int_to_bool)
628 return head.getResult();
633OpFoldResult cir::CastOp::fold(FoldAdaptor adaptor) {
634 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getSrc())) {
636 return cir::PoisonAttr::get(getContext(),
getType());
641 case cir::CastKind::integral: {
645 auto foldOrder = getSrc().getDefiningOp()->fold(foldResults);
646 if (foldOrder.succeeded() && mlir::isa<mlir::Attribute>(foldResults[0]))
647 return mlir::cast<mlir::Attribute>(foldResults[0]);
650 case cir::CastKind::bitcast:
651 case cir::CastKind::address_space:
652 case cir::CastKind::float_complex:
653 case cir::CastKind::int_complex: {
667mlir::OperandRange cir::CallOp::getArgOperands() {
669 return getArgs().drop_front(1);
673mlir::MutableOperandRange cir::CallOp::getArgOperandsMutable() {
674 mlir::MutableOperandRange args = getArgsMutable();
676 return args.slice(1, args.size() - 1);
680mlir::Value cir::CallOp::getIndirectCall() {
681 assert(isIndirect());
682 return getOperand(0);
686Value cir::CallOp::getArgOperand(
unsigned i) {
689 return getOperand(i);
693unsigned cir::CallOp::getNumArgOperands() {
695 return this->getOperation()->getNumOperands() - 1;
696 return this->getOperation()->getNumOperands();
700 mlir::OperationState &result) {
703 mlir::FlatSymbolRefAttr calleeAttr;
708 .parseOptionalAttribute(calleeAttr, CIRDialect::getCalleeAttrName(),
711 OpAsmParser::UnresolvedOperand indirectVal;
713 if (parser.parseOperand(indirectVal).failed())
715 ops.push_back(indirectVal);
718 if (parser.parseLParen())
719 return mlir::failure();
721 opsLoc = parser.getCurrentLocation();
722 if (parser.parseOperandList(ops))
723 return mlir::failure();
724 if (parser.parseRParen())
725 return mlir::failure();
727 if (parser.parseOptionalKeyword(
"nothrow").succeeded())
728 result.addAttribute(CIRDialect::getNoThrowAttrName(),
729 mlir::UnitAttr::get(parser.getContext()));
731 if (parser.parseOptionalKeyword(
"side_effect").succeeded()) {
732 if (parser.parseLParen().failed())
734 cir::SideEffect sideEffect;
737 if (parser.parseRParen().failed())
739 auto attr = cir::SideEffectAttr::get(parser.getContext(), sideEffect);
740 result.addAttribute(CIRDialect::getSideEffectAttrName(), attr);
743 if (parser.parseOptionalAttrDict(result.attributes))
744 return ::mlir::failure();
746 if (parser.parseColon())
747 return ::mlir::failure();
749 mlir::FunctionType opsFnTy;
750 if (parser.parseType(opsFnTy))
751 return mlir::failure();
753 allResultTypes = opsFnTy.getResults();
754 result.addTypes(allResultTypes);
756 if (parser.resolveOperands(ops, opsFnTy.getInputs(), opsLoc, result.operands))
757 return mlir::failure();
759 return mlir::success();
763 mlir::FlatSymbolRefAttr calleeSym,
764 mlir::Value indirectCallee,
765 mlir::OpAsmPrinter &printer,
bool isNothrow,
766 cir::SideEffect sideEffect) {
769 auto callLikeOp = mlir::cast<cir::CIRCallOpInterface>(op);
770 auto ops = callLikeOp.getArgOperands();
774 printer.printAttributeWithoutType(calleeSym);
777 assert(indirectCallee);
778 printer << indirectCallee;
780 printer <<
"(" << ops <<
")";
783 printer <<
" nothrow";
785 if (sideEffect != cir::SideEffect::All) {
786 printer <<
" side_effect(";
787 printer << stringifySideEffect(sideEffect);
791 printer.printOptionalAttrDict(op->getAttrs(),
792 {CIRDialect::getCalleeAttrName(),
793 CIRDialect::getNoThrowAttrName(),
794 CIRDialect::getSideEffectAttrName()});
797 printer.printFunctionalType(op->getOperands().getTypes(),
798 op->getResultTypes());
801mlir::ParseResult cir::CallOp::parse(mlir::OpAsmParser &parser,
802 mlir::OperationState &result) {
806void cir::CallOp::print(mlir::OpAsmPrinter &p) {
807 mlir::Value indirectCallee = isIndirect() ? getIndirectCall() :
nullptr;
808 cir::SideEffect sideEffect = getSideEffect();
809 printCallCommon(*
this, getCalleeAttr(), indirectCallee, p, getNothrow(),
815 SymbolTableCollection &symbolTable) {
817 op->getAttrOfType<FlatSymbolRefAttr>(CIRDialect::getCalleeAttrName());
820 return mlir::success();
823 auto fn = symbolTable.lookupNearestSymbolFrom<cir::FuncOp>(op, fnAttr);
825 return op->emitOpError() <<
"'" << fnAttr.getValue()
826 <<
"' does not reference a valid function";
828 auto callIf = dyn_cast<cir::CIRCallOpInterface>(op);
829 assert(callIf &&
"expected CIR call interface to be always available");
833 auto fnType = fn.getFunctionType();
834 if (!fn.getNoProto()) {
835 unsigned numCallOperands = callIf.getNumArgOperands();
836 unsigned numFnOpOperands = fnType.getNumInputs();
838 if (!fnType.isVarArg() && numCallOperands != numFnOpOperands)
839 return op->emitOpError(
"incorrect number of operands for callee");
840 if (fnType.isVarArg() && numCallOperands < numFnOpOperands)
841 return op->emitOpError(
"too few operands for callee");
843 for (
unsigned i = 0, e = numFnOpOperands; i != e; ++i)
844 if (callIf.getArgOperand(i).getType() != fnType.getInput(i))
845 return op->emitOpError(
"operand type mismatch: expected operand type ")
846 << fnType.getInput(i) <<
", but provided "
847 << op->getOperand(i).getType() <<
" for operand number " << i;
853 if (fnType.hasVoidReturn() && op->getNumResults() != 0)
854 return op->emitOpError(
"callee returns void but call has results");
857 if (!fnType.hasVoidReturn() && op->getNumResults() != 1)
858 return op->emitOpError(
"incorrect number of results for callee");
861 if (!fnType.hasVoidReturn() &&
862 op->getResultTypes().front() != fnType.getReturnType()) {
863 return op->emitOpError(
"result type mismatch: expected ")
864 << fnType.getReturnType() <<
", but provided "
865 << op->getResult(0).getType();
868 return mlir::success();
872cir::CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
881 cir::FuncOp function) {
883 if (op.getNumOperands() > 1)
884 return op.emitOpError() <<
"expects at most 1 return operand";
887 auto expectedTy = function.getFunctionType().getReturnType();
889 (op.getNumOperands() == 0 ? cir::VoidType::get(op.getContext())
890 : op.getOperand(0).getType());
891 if (actualTy != expectedTy)
892 return op.emitOpError() <<
"returns " << actualTy
893 <<
" but enclosing function returns " << expectedTy;
895 return mlir::success();
898mlir::LogicalResult cir::ReturnOp::verify() {
901 auto *fnOp = getOperation()->getParentOp();
902 while (!isa<cir::FuncOp>(fnOp))
903 fnOp = fnOp->getParentOp();
916ParseResult cir::IfOp::parse(OpAsmParser &parser, OperationState &result) {
918 result.regions.reserve(2);
919 Region *thenRegion = result.addRegion();
920 Region *elseRegion = result.addRegion();
922 mlir::Builder &builder = parser.getBuilder();
923 OpAsmParser::UnresolvedOperand cond;
924 Type boolType = cir::BoolType::get(builder.getContext());
926 if (parser.parseOperand(cond) ||
927 parser.resolveOperand(cond, boolType, result.operands))
931 mlir::SMLoc parseThenLoc = parser.getCurrentLocation();
932 if (parser.parseRegion(*thenRegion, {}, {}))
939 if (!parser.parseOptionalKeyword(
"else")) {
940 mlir::SMLoc parseElseLoc = parser.getCurrentLocation();
941 if (parser.parseRegion(*elseRegion, {}, {}))
948 if (parser.parseOptionalAttrDict(result.attributes))
953void cir::IfOp::print(OpAsmPrinter &p) {
954 p <<
" " << getCondition() <<
" ";
955 mlir::Region &thenRegion = this->getThenRegion();
956 p.printRegion(thenRegion,
961 mlir::Region &elseRegion = this->getElseRegion();
962 if (!elseRegion.empty()) {
964 p.printRegion(elseRegion,
969 p.printOptionalAttrDict(getOperation()->getAttrs());
975 builder.create<cir::YieldOp>(loc);
983void cir::IfOp::getSuccessorRegions(mlir::RegionBranchPoint point,
984 SmallVectorImpl<RegionSuccessor> ®ions) {
986 if (!point.isParent()) {
987 regions.push_back(RegionSuccessor());
992 Region *elseRegion = &this->getElseRegion();
993 if (elseRegion->empty())
994 elseRegion =
nullptr;
997 regions.push_back(RegionSuccessor(&getThenRegion()));
1000 regions.push_back(RegionSuccessor(elseRegion));
1005void cir::IfOp::build(OpBuilder &builder, OperationState &result,
Value cond,
1008 assert(thenBuilder &&
"the builder callback for 'then' must be present");
1009 result.addOperands(cond);
1011 OpBuilder::InsertionGuard guard(builder);
1012 Region *thenRegion = result.addRegion();
1013 builder.createBlock(thenRegion);
1014 thenBuilder(builder, result.location);
1016 Region *elseRegion = result.addRegion();
1017 if (!withElseRegion)
1020 builder.createBlock(elseRegion);
1021 elseBuilder(builder, result.location);
1033void cir::ScopeOp::getSuccessorRegions(
1034 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1036 if (!point.isParent()) {
1037 regions.push_back(RegionSuccessor(getODSResults(0)));
1042 regions.push_back(RegionSuccessor(&getScopeRegion()));
1045void cir::ScopeOp::build(
1046 OpBuilder &builder, OperationState &result,
1047 function_ref<
void(OpBuilder &, Type &, Location)> scopeBuilder) {
1048 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1050 OpBuilder::InsertionGuard guard(builder);
1051 Region *scopeRegion = result.addRegion();
1052 builder.createBlock(scopeRegion);
1056 scopeBuilder(builder, yieldTy, result.location);
1059 result.addTypes(TypeRange{yieldTy});
1062void cir::ScopeOp::build(
1063 OpBuilder &builder, OperationState &result,
1064 function_ref<
void(OpBuilder &, Location)> scopeBuilder) {
1065 assert(scopeBuilder &&
"the builder callback for 'then' must be present");
1066 OpBuilder::InsertionGuard guard(builder);
1067 Region *scopeRegion = result.addRegion();
1068 builder.createBlock(scopeRegion);
1070 scopeBuilder(builder, result.location);
1073LogicalResult cir::ScopeOp::verify() {
1075 return emitOpError() <<
"cir.scope must not be empty since it should "
1076 "include at least an implicit cir.yield ";
1079 mlir::Block &lastBlock =
getRegion().back();
1080 if (lastBlock.empty() || !lastBlock.mightHaveTerminator() ||
1081 !lastBlock.getTerminator()->hasTrait<OpTrait::IsTerminator>())
1082 return emitOpError() <<
"last block of cir.scope must be terminated";
1090mlir::SuccessorOperands cir::BrOp::getSuccessorOperands(
unsigned index) {
1091 assert(index == 0 &&
"invalid successor index");
1092 return mlir::SuccessorOperands(getDestOperandsMutable());
1103mlir::SuccessorOperands cir::BrCondOp::getSuccessorOperands(
unsigned index) {
1104 assert(index < getNumSuccessors() &&
"invalid successor index");
1105 return SuccessorOperands(index == 0 ? getDestOperandsTrueMutable()
1106 : getDestOperandsFalseMutable());
1110 if (IntegerAttr condAttr = dyn_cast_if_present<IntegerAttr>(operands.front()))
1111 return condAttr.getValue().isOne() ? getDestTrue() : getDestFalse();
1119void cir::CaseOp::getSuccessorRegions(
1120 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1121 if (!point.isParent()) {
1122 regions.push_back(RegionSuccessor());
1125 regions.push_back(RegionSuccessor(&getCaseRegion()));
1128void cir::CaseOp::build(OpBuilder &builder, OperationState &result,
1129 ArrayAttr value, CaseOpKind kind,
1130 OpBuilder::InsertPoint &insertPoint) {
1131 OpBuilder::InsertionGuard guardSwitch(builder);
1132 result.addAttribute(
"value", value);
1133 result.getOrAddProperties<Properties>().kind =
1134 cir::CaseOpKindAttr::get(builder.getContext(), kind);
1135 Region *caseRegion = result.addRegion();
1136 builder.createBlock(caseRegion);
1138 insertPoint = builder.saveInsertionPoint();
1146 mlir::OpAsmParser::UnresolvedOperand &cond,
1147 mlir::Type &condType) {
1148 cir::IntType intCondType;
1150 if (parser.parseLParen())
1151 return mlir::failure();
1153 if (parser.parseOperand(cond))
1154 return mlir::failure();
1155 if (parser.parseColon())
1156 return mlir::failure();
1157 if (parser.parseCustomTypeWithFallback(intCondType))
1158 return mlir::failure();
1159 condType = intCondType;
1161 if (parser.parseRParen())
1162 return mlir::failure();
1163 if (parser.parseRegion(regions, {}, {}))
1166 return mlir::success();
1170 mlir::Region &bodyRegion, mlir::Value condition,
1171 mlir::Type condType) {
1175 p.printStrippedAttrOrType(condType);
1179 p.printRegion(bodyRegion,
false,
1183void cir::SwitchOp::getSuccessorRegions(
1184 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ion) {
1185 if (!point.isParent()) {
1186 region.push_back(RegionSuccessor());
1190 region.push_back(RegionSuccessor(&getBody()));
1193void cir::SwitchOp::build(OpBuilder &builder, OperationState &result,
1195 assert(switchBuilder &&
"the builder callback for regions must be present");
1196 OpBuilder::InsertionGuard guardSwitch(builder);
1197 Region *switchRegion = result.addRegion();
1198 builder.createBlock(switchRegion);
1199 result.addOperands({cond});
1200 switchBuilder(builder, result.location, result);
1204 walk<mlir::WalkOrder::PreOrder>([&](mlir::Operation *op) {
1206 if (isa<cir::SwitchOp>(op) && op != *
this)
1207 return WalkResult::skip();
1209 if (
auto caseOp = dyn_cast<cir::CaseOp>(op))
1210 cases.push_back(caseOp);
1212 return WalkResult::advance();
1217 collectCases(cases);
1219 if (getBody().empty())
1222 if (!isa<YieldOp>(getBody().front().back()))
1225 if (!llvm::all_of(getBody().front(),
1226 [](Operation &op) {
return isa<CaseOp, YieldOp>(op); }))
1229 return llvm::all_of(cases, [
this](CaseOp op) {
1230 return op->getParentOfType<SwitchOp>() == *
this;
1238void cir::SwitchFlatOp::build(OpBuilder &builder, OperationState &result,
1239 Value value, Block *defaultDestination,
1240 ValueRange defaultOperands,
1242 BlockRange caseDestinations,
1245 std::vector<mlir::Attribute> caseValuesAttrs;
1246 for (
const APInt &val : caseValues)
1247 caseValuesAttrs.push_back(cir::IntAttr::get(value.getType(), val));
1248 mlir::ArrayAttr attrs = ArrayAttr::get(builder.getContext(), caseValuesAttrs);
1250 build(builder, result, value, defaultOperands, caseOperands, attrs,
1251 defaultDestination, caseDestinations);
1257 OpAsmParser &parser, Type flagType, mlir::ArrayAttr &caseValues,
1258 SmallVectorImpl<Block *> &caseDestinations,
1262 if (failed(parser.parseLSquare()))
1264 if (succeeded(parser.parseOptionalRSquare()))
1268 auto parseCase = [&]() {
1270 if (failed(parser.parseInteger(value)))
1273 values.push_back(cir::IntAttr::get(flagType, value));
1278 if (parser.parseColon() || parser.parseSuccessor(destination))
1280 if (!parser.parseOptionalLParen()) {
1281 if (parser.parseOperandList(operands, OpAsmParser::Delimiter::None,
1283 parser.parseColonTypeList(operandTypes) || parser.parseRParen())
1286 caseDestinations.push_back(destination);
1287 caseOperands.emplace_back(operands);
1288 caseOperandTypes.emplace_back(operandTypes);
1291 if (failed(parser.parseCommaSeparatedList(parseCase)))
1294 caseValues = ArrayAttr::get(flagType.getContext(), values);
1296 return parser.parseRSquare();
1300 Type flagType, mlir::ArrayAttr caseValues,
1301 SuccessorRange caseDestinations,
1302 OperandRangeRange caseOperands,
1303 const TypeRangeRange &caseOperandTypes) {
1313 llvm::zip(caseValues, caseDestinations),
1316 mlir::Attribute a = std::get<0>(i);
1317 p << mlir::cast<cir::IntAttr>(a).getValue();
1319 p.printSuccessorAndUseList(std::get<1>(i), caseOperands[index++]);
1334 mlir::Attribute &valueAttr) {
1336 return parser.parseAttribute(valueAttr,
"value", attr);
1340 p.printAttribute(value);
1343mlir::LogicalResult cir::GlobalOp::verify() {
1346 if (getInitialValue().has_value()) {
1358void cir::GlobalOp::build(OpBuilder &odsBuilder, OperationState &odsState,
1359 llvm::StringRef sym_name, mlir::Type sym_type,
1360 bool isConstant, cir::GlobalLinkageKind linkage) {
1361 odsState.addAttribute(getSymNameAttrName(odsState.name),
1362 odsBuilder.getStringAttr(sym_name));
1363 odsState.addAttribute(getSymTypeAttrName(odsState.name),
1364 mlir::TypeAttr::get(sym_type));
1366 odsState.addAttribute(getConstantAttrName(odsState.name),
1367 odsBuilder.getUnitAttr());
1369 cir::GlobalLinkageKindAttr linkageAttr =
1370 cir::GlobalLinkageKindAttr::get(odsBuilder.getContext(), linkage);
1371 odsState.addAttribute(getLinkageAttrName(odsState.name), linkageAttr);
1373 odsState.addAttribute(getGlobalVisibilityAttrName(odsState.name),
1374 cir::VisibilityAttr::get(odsBuilder.getContext()));
1379 Attribute initAttr) {
1380 if (!op.isDeclaration()) {
1392 Attribute &initialValueAttr) {
1394 if (parser.parseOptionalEqual().failed()) {
1397 if (parser.parseColonType(opTy))
1406 assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
1407 "Non-typed attrs shouldn't appear here.");
1408 auto typedAttr = mlir::cast<mlir::TypedAttr>(initialValueAttr);
1409 opTy = typedAttr.getType();
1412 typeAttr = TypeAttr::get(opTy);
1421cir::GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1424 mlir::Operation *op =
1425 symbolTable.lookupNearestSymbolFrom(*
this, getNameAttr());
1426 if (op ==
nullptr || !(isa<GlobalOp>(op) || isa<FuncOp>(op)))
1427 return emitOpError(
"'")
1429 <<
"' does not reference a valid cir.global or cir.func";
1432 if (
auto g = dyn_cast<GlobalOp>(op)) {
1433 symTy = g.getSymType();
1436 }
else if (
auto f = dyn_cast<FuncOp>(op)) {
1437 symTy = f.getFunctionType();
1439 llvm_unreachable(
"Unexpected operation for GetGlobalOp");
1442 auto resultType = dyn_cast<PointerType>(getAddr().
getType());
1443 if (!resultType || symTy != resultType.getPointee())
1444 return emitOpError(
"result type pointee type '")
1445 << resultType.getPointee() <<
"' does not match type " << symTy
1446 <<
" of the global @" <<
getName();
1456cir::VTableAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1462 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
1464 return emitOpError(
"'")
1465 <<
name <<
"' does not reference a valid cir.global";
1466 std::optional<mlir::Attribute> init = op.getInitialValue();
1469 if (!isa<cir::VTableAttr>(*init))
1470 return emitOpError(
"Expected #cir.vtable in initializer for global '")
1480cir::VTTAddrPointOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
1489 symbolTable.lookupNearestSymbolFrom<cir::GlobalOp>(*
this, getNameAttr());
1491 return emitOpError(
"'")
1492 <<
name <<
"' does not reference a valid cir.global";
1493 std::optional<mlir::Attribute> init = op.getInitialValue();
1496 if (!isa<cir::ConstArrayAttr>(*init))
1498 "Expected constant array in initializer for global VTT '")
1503LogicalResult cir::VTTAddrPointOp::verify() {
1505 if (
getName() && getSymAddr())
1506 return emitOpError(
"should use either a symbol or value, but not both");
1512 mlir::Type resultType = getAddr().getType();
1513 mlir::Type resTy = cir::PointerType::get(
1514 cir::PointerType::get(cir::VoidType::get(getContext())));
1516 if (resultType != resTy)
1517 return emitOpError(
"result type must be ")
1518 << resTy <<
", but provided result type is " << resultType;
1530void cir::FuncOp::build(OpBuilder &builder, OperationState &result,
1531 StringRef name, FuncType type,
1532 GlobalLinkageKind linkage) {
1534 result.addAttribute(SymbolTable::getSymbolAttrName(),
1535 builder.getStringAttr(name));
1536 result.addAttribute(getFunctionTypeAttrName(result.name),
1537 TypeAttr::get(type));
1538 result.addAttribute(
1540 GlobalLinkageKindAttr::get(builder.getContext(), linkage));
1541 result.addAttribute(getGlobalVisibilityAttrName(result.name),
1542 cir::VisibilityAttr::get(builder.getContext()));
1545ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
1546 llvm::SMLoc loc = parser.getCurrentLocation();
1547 mlir::Builder &builder = parser.getBuilder();
1549 mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
1550 mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
1551 mlir::StringAttr visNameAttr = getSymVisibilityAttrName(state.name);
1552 mlir::StringAttr visibilityNameAttr = getGlobalVisibilityAttrName(state.name);
1553 mlir::StringAttr dsoLocalNameAttr = getDsoLocalAttrName(state.name);
1555 if (::mlir::succeeded(parser.parseOptionalKeyword(lambdaNameAttr.strref())))
1556 state.addAttribute(lambdaNameAttr, parser.getBuilder().getUnitAttr());
1557 if (parser.parseOptionalKeyword(noProtoNameAttr).succeeded())
1558 state.addAttribute(noProtoNameAttr, parser.getBuilder().getUnitAttr());
1562 GlobalLinkageKindAttr::get(
1563 parser.getContext(),
1565 parser, GlobalLinkageKind::ExternalLinkage)));
1567 ::llvm::StringRef visAttrStr;
1568 if (parser.parseOptionalKeyword(&visAttrStr, {
"private",
"public",
"nested"})
1570 state.addAttribute(visNameAttr,
1571 parser.getBuilder().getStringAttr(visAttrStr));
1574 cir::VisibilityAttr cirVisibilityAttr;
1576 state.addAttribute(visibilityNameAttr, cirVisibilityAttr);
1578 if (parser.parseOptionalKeyword(dsoLocalNameAttr).succeeded())
1579 state.addAttribute(dsoLocalNameAttr, parser.getBuilder().getUnitAttr());
1581 StringAttr nameAttr;
1582 if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
1588 bool isVariadic =
false;
1589 if (function_interface_impl::parseFunctionSignatureWithArguments(
1590 parser,
true, arguments, isVariadic, resultTypes,
1594 for (OpAsmParser::Argument &arg : arguments)
1595 argTypes.push_back(
arg.type);
1597 if (resultTypes.size() > 1) {
1598 return parser.emitError(
1599 loc,
"functions with multiple return types are not supported");
1602 mlir::Type returnType =
1603 (resultTypes.empty() ? cir::VoidType::get(builder.getContext())
1604 : resultTypes.front());
1606 cir::FuncType fnType = cir::FuncType::get(argTypes, returnType, isVariadic);
1609 state.addAttribute(getFunctionTypeAttrName(state.name),
1610 TypeAttr::get(fnType));
1612 bool hasAlias =
false;
1613 mlir::StringAttr aliaseeNameAttr = getAliaseeAttrName(state.name);
1614 if (parser.parseOptionalKeyword(
"alias").succeeded()) {
1615 if (parser.parseLParen().failed())
1617 mlir::StringAttr aliaseeAttr;
1618 if (parser.parseOptionalSymbolName(aliaseeAttr).failed())
1620 state.addAttribute(aliaseeNameAttr, FlatSymbolRefAttr::get(aliaseeAttr));
1621 if (parser.parseRParen().failed())
1627 auto *body = state.addRegion();
1628 OptionalParseResult parseResult = parser.parseOptionalRegion(
1629 *body, arguments,
false);
1630 if (parseResult.has_value()) {
1632 return parser.emitError(loc,
"function alias shall not have a body");
1633 if (failed(*parseResult))
1637 return parser.emitError(loc,
"expected non-empty function body");
1646bool cir::FuncOp::isDeclaration() {
1649 std::optional<StringRef> aliasee = getAliasee();
1651 return getFunctionBody().empty();
1657mlir::Region *cir::FuncOp::getCallableRegion() {
1663void cir::FuncOp::print(OpAsmPrinter &p) {
1673 if (getLinkage() != GlobalLinkageKind::ExternalLinkage)
1674 p <<
' ' << stringifyGlobalLinkageKind(getLinkage());
1676 mlir::SymbolTable::Visibility vis = getVisibility();
1677 if (vis != mlir::SymbolTable::Visibility::Public)
1680 cir::VisibilityAttr cirVisibilityAttr = getGlobalVisibilityAttr();
1681 if (!cirVisibilityAttr.isDefault()) {
1690 p.printSymbolName(getSymName());
1691 cir::FuncType fnType = getFunctionType();
1692 function_interface_impl::printFunctionSignature(
1693 p, *
this, fnType.getInputs(), fnType.isVarArg(), fnType.getReturnTypes());
1695 if (std::optional<StringRef> aliaseeName = getAliasee()) {
1697 p.printSymbolName(*aliaseeName);
1702 Region &body = getOperation()->getRegion(0);
1703 if (!body.empty()) {
1705 p.printRegion(body,
false,
1710mlir::LogicalResult cir::FuncOp::verify() {
1712 llvm::SmallSet<llvm::StringRef, 16> labels;
1713 llvm::SmallSet<llvm::StringRef, 16> gotos;
1715 getOperation()->walk([&](mlir::Operation *op) {
1716 if (
auto lab = dyn_cast<cir::LabelOp>(op)) {
1717 labels.insert(lab.getLabel());
1718 }
else if (
auto goTo = dyn_cast<cir::GotoOp>(op)) {
1719 gotos.insert(goTo.getLabel());
1723 if (!labels.empty() || !gotos.empty()) {
1724 llvm::SmallSet<llvm::StringRef, 16> mismatched =
1725 llvm::set_difference(gotos, labels);
1727 if (!mismatched.empty())
1728 return emitOpError() <<
"goto/label mismatch";
1736LogicalResult cir::BinOp::verify() {
1737 bool noWrap = getNoUnsignedWrap() || getNoSignedWrap();
1738 bool saturated = getSaturated();
1740 if (!isa<cir::IntType>(
getType()) && noWrap)
1742 <<
"only operations on integer values may have nsw/nuw flags";
1744 bool noWrapOps =
getKind() == cir::BinOpKind::Add ||
1745 getKind() == cir::BinOpKind::Sub ||
1746 getKind() == cir::BinOpKind::Mul;
1749 getKind() == cir::BinOpKind::Add ||
getKind() == cir::BinOpKind::Sub;
1751 if (noWrap && !noWrapOps)
1752 return emitError() <<
"The nsw/nuw flags are applicable to opcodes: 'add', "
1754 if (saturated && !saturatedOps)
1755 return emitError() <<
"The saturated flag is applicable to opcodes: 'add' "
1757 if (noWrap && saturated)
1758 return emitError() <<
"The nsw/nuw flags and the saturated flag are "
1759 "mutually exclusive";
1761 return mlir::success();
1773void cir::TernaryOp::getSuccessorRegions(
1774 mlir::RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> ®ions) {
1776 if (!point.isParent()) {
1777 regions.push_back(RegionSuccessor(this->getODSResults(0)));
1783 regions.push_back(RegionSuccessor(&getTrueRegion()));
1784 regions.push_back(RegionSuccessor(&getFalseRegion()));
1787void cir::TernaryOp::build(
1788 OpBuilder &builder, OperationState &result,
Value cond,
1789 function_ref<
void(OpBuilder &, Location)> trueBuilder,
1790 function_ref<
void(OpBuilder &, Location)> falseBuilder) {
1791 result.addOperands(cond);
1792 OpBuilder::InsertionGuard guard(builder);
1793 Region *trueRegion = result.addRegion();
1794 Block *block = builder.createBlock(trueRegion);
1795 trueBuilder(builder, result.location);
1796 Region *falseRegion = result.addRegion();
1797 builder.createBlock(falseRegion);
1798 falseBuilder(builder, result.location);
1800 auto yield = dyn_cast<YieldOp>(block->getTerminator());
1801 assert((yield && yield.getNumOperands() <= 1) &&
1802 "expected zero or one result type");
1803 if (yield.getNumOperands() == 1)
1804 result.addTypes(TypeRange{yield.getOperandTypes().front()});
1811OpFoldResult cir::SelectOp::fold(FoldAdaptor adaptor) {
1812 mlir::Attribute condition = adaptor.getCondition();
1814 bool conditionValue = mlir::cast<cir::BoolAttr>(condition).getValue();
1815 return conditionValue ? getTrueValue() : getFalseValue();
1819 mlir::Attribute trueValue = adaptor.getTrueValue();
1820 mlir::Attribute falseValue = adaptor.getFalseValue();
1821 if (trueValue == falseValue)
1823 if (getTrueValue() == getFalseValue())
1824 return getTrueValue();
1832LogicalResult cir::ShiftOp::verify() {
1833 mlir::Operation *op = getOperation();
1834 auto op0VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(0).getType());
1835 auto op1VecTy = mlir::dyn_cast<cir::VectorType>(op->getOperand(1).getType());
1836 if (!op0VecTy ^ !op1VecTy)
1837 return emitOpError() <<
"input types cannot be one vector and one scalar";
1840 if (op0VecTy.getSize() != op1VecTy.getSize())
1841 return emitOpError() <<
"input vector types must have the same size";
1843 auto opResultTy = mlir::dyn_cast<cir::VectorType>(
getType());
1845 return emitOpError() <<
"the type of the result must be a vector "
1846 <<
"if it is vector shift";
1848 auto op0VecEleTy = mlir::cast<cir::IntType>(op0VecTy.getElementType());
1849 auto op1VecEleTy = mlir::cast<cir::IntType>(op1VecTy.getElementType());
1850 if (op0VecEleTy.getWidth() != op1VecEleTy.getWidth())
1851 return emitOpError()
1852 <<
"vector operands do not have the same elements sizes";
1854 auto resVecEleTy = mlir::cast<cir::IntType>(opResultTy.getElementType());
1855 if (op0VecEleTy.getWidth() != resVecEleTy.getWidth())
1856 return emitOpError() <<
"vector operands and result type do not have the "
1857 "same elements sizes";
1860 return mlir::success();
1867LogicalResult cir::LabelOp::verify() {
1868 mlir::Operation *op = getOperation();
1869 mlir::Block *blk = op->getBlock();
1870 if (&blk->front() != op)
1871 return emitError() <<
"must be the first operation in a block";
1873 return mlir::success();
1880LogicalResult cir::UnaryOp::verify() {
1882 case cir::UnaryOpKind::Inc:
1883 case cir::UnaryOpKind::Dec:
1884 case cir::UnaryOpKind::Plus:
1885 case cir::UnaryOpKind::Minus:
1886 case cir::UnaryOpKind::Not:
1891 llvm_unreachable(
"Unknown UnaryOp kind?");
1895 return isa<cir::BoolType>(op.getInput().getType()) &&
1896 op.getKind() == cir::UnaryOpKind::Not;
1908OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) {
1910 mlir::dyn_cast_if_present<cir::PoisonAttr>(adaptor.getInput())) {
1916 if (
auto previous = getInput().getDefiningOp<cir::UnaryOp>())
1918 return previous.getInput();
1927LogicalResult cir::CopyOp::verify() {
1929 if (!
getType().getPointee().hasTrait<DataLayoutTypeInterface::Trait>())
1930 return emitError() <<
"missing data layout for pointee type";
1932 if (getSrc() == getDst())
1933 return emitError() <<
"source and destination are the same";
1935 return mlir::success();
1942LogicalResult cir::GetMemberOp::verify() {
1943 const auto recordTy = dyn_cast<RecordType>(getAddrTy().getPointee());
1945 return emitError() <<
"expected pointer to a record type";
1947 if (recordTy.getMembers().size() <=
getIndex())
1948 return emitError() <<
"member index out of bounds";
1951 return emitError() <<
"member type mismatch";
1953 return mlir::success();
1960OpFoldResult cir::VecCreateOp::fold(FoldAdaptor adaptor) {
1961 if (llvm::any_of(getElements(), [](mlir::Value value) {
1962 return !value.getDefiningOp<cir::ConstantOp>();
1966 return cir::ConstVectorAttr::get(
1967 getType(), mlir::ArrayAttr::get(getContext(), adaptor.getElements()));
1970LogicalResult cir::VecCreateOp::verify() {
1974 const cir::VectorType vecTy =
getType();
1975 if (getElements().size() != vecTy.getSize()) {
1976 return emitOpError() <<
"operand count of " << getElements().size()
1977 <<
" doesn't match vector type " << vecTy
1978 <<
" element count of " << vecTy.getSize();
1981 const mlir::Type elementType = vecTy.getElementType();
1982 for (
const mlir::Value element : getElements()) {
1983 if (element.getType() != elementType) {
1984 return emitOpError() <<
"operand type " << element.getType()
1985 <<
" doesn't match vector element type "
1997OpFoldResult cir::VecExtractOp::fold(FoldAdaptor adaptor) {
1998 const auto vectorAttr =
1999 llvm::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec());
2003 const auto indexAttr =
2004 llvm::dyn_cast_if_present<cir::IntAttr>(adaptor.getIndex());
2008 const mlir::ArrayAttr elements = vectorAttr.getElts();
2009 const uint64_t index = indexAttr.getUInt();
2010 if (index >= elements.size())
2013 return elements[index];
2020OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
2022 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getLhs());
2024 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getRhs());
2025 if (!lhsVecAttr || !rhsVecAttr)
2028 mlir::Type inputElemTy =
2029 mlir::cast<cir::VectorType>(lhsVecAttr.getType()).getElementType();
2030 if (!isAnyIntegerOrFloatingPointType(inputElemTy))
2033 cir::CmpOpKind opKind = adaptor.getKind();
2034 mlir::ArrayAttr lhsVecElhs = lhsVecAttr.getElts();
2035 mlir::ArrayAttr rhsVecElhs = rhsVecAttr.getElts();
2036 uint64_t vecSize = lhsVecElhs.size();
2039 bool isIntAttr = vecSize && mlir::isa<cir::IntAttr>(lhsVecElhs[0]);
2040 for (uint64_t i = 0; i < vecSize; i++) {
2041 mlir::Attribute lhsAttr = lhsVecElhs[i];
2042 mlir::Attribute rhsAttr = rhsVecElhs[i];
2045 case cir::CmpOpKind::lt: {
2047 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <
2048 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
2050 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <
2051 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
2055 case cir::CmpOpKind::le: {
2057 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <=
2058 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
2060 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <=
2061 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
2065 case cir::CmpOpKind::gt: {
2067 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >
2068 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
2070 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >
2071 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
2075 case cir::CmpOpKind::ge: {
2077 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >=
2078 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
2080 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >=
2081 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
2085 case cir::CmpOpKind::eq: {
2087 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() ==
2088 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
2090 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() ==
2091 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
2095 case cir::CmpOpKind::ne: {
2097 cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() !=
2098 mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
2100 cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() !=
2101 mlir::cast<cir::FPAttr>(rhsAttr).getValue();
2107 elements[i] = cir::IntAttr::get(
getType().getElementType(), cmpResult);
2110 return cir::ConstVectorAttr::get(
2111 getType(), mlir::ArrayAttr::get(getContext(), elements));
2118OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor adaptor) {
2120 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec1());
2122 mlir::dyn_cast_if_present<cir::ConstVectorAttr>(adaptor.getVec2());
2123 if (!vec1Attr || !vec2Attr)
2126 mlir::Type vec1ElemTy =
2127 mlir::cast<cir::VectorType>(vec1Attr.getType()).getElementType();
2129 mlir::ArrayAttr vec1Elts = vec1Attr.getElts();
2130 mlir::ArrayAttr vec2Elts = vec2Attr.getElts();
2131 mlir::ArrayAttr indicesElts = adaptor.getIndices();
2134 elements.reserve(indicesElts.size());
2136 uint64_t vec1Size = vec1Elts.size();
2137 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
2138 if (idxAttr.getSInt() == -1) {
2139 elements.push_back(cir::UndefAttr::get(vec1ElemTy));
2143 uint64_t idxValue = idxAttr.getUInt();
2144 elements.push_back(idxValue < vec1Size ? vec1Elts[idxValue]
2145 : vec2Elts[idxValue - vec1Size]);
2148 return cir::ConstVectorAttr::get(
2149 getType(), mlir::ArrayAttr::get(getContext(), elements));
2152LogicalResult cir::VecShuffleOp::verify() {
2155 if (getIndices().size() != getResult().
getType().getSize()) {
2156 return emitOpError() <<
": the number of elements in " << getIndices()
2157 <<
" and " << getResult().getType() <<
" don't match";
2162 if (getVec1().
getType().getElementType() !=
2163 getResult().
getType().getElementType()) {
2164 return emitOpError() <<
": element types of " << getVec1().getType()
2165 <<
" and " << getResult().getType() <<
" don't match";
2168 const uint64_t maxValidIndex =
2169 getVec1().getType().getSize() + getVec2().getType().getSize() - 1;
2171 getIndices().getAsRange<cir::IntAttr>(), [&](cir::IntAttr idxAttr) {
2172 return idxAttr.getSInt() != -1 && idxAttr.getUInt() > maxValidIndex;
2174 return emitOpError() <<
": index for __builtin_shufflevector must be "
2175 "less than the total number of vector elements";
2184OpFoldResult cir::VecShuffleDynamicOp::fold(FoldAdaptor adaptor) {
2185 mlir::Attribute vec = adaptor.getVec();
2186 mlir::Attribute indices = adaptor.getIndices();
2187 if (mlir::isa_and_nonnull<cir::ConstVectorAttr>(vec) &&
2188 mlir::isa_and_nonnull<cir::ConstVectorAttr>(indices)) {
2189 auto vecAttr = mlir::cast<cir::ConstVectorAttr>(vec);
2190 auto indicesAttr = mlir::cast<cir::ConstVectorAttr>(indices);
2192 mlir::ArrayAttr vecElts = vecAttr.getElts();
2193 mlir::ArrayAttr indicesElts = indicesAttr.getElts();
2195 const uint64_t numElements = vecElts.size();
2198 elements.reserve(numElements);
2200 const uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
2201 for (
const auto &idxAttr : indicesElts.getAsRange<cir::IntAttr>()) {
2202 uint64_t idxValue = idxAttr.getUInt();
2203 uint64_t newIdx = idxValue & maskBits;
2204 elements.push_back(vecElts[newIdx]);
2207 return cir::ConstVectorAttr::get(
2208 getType(), mlir::ArrayAttr::get(getContext(), elements));
2214LogicalResult cir::VecShuffleDynamicOp::verify() {
2216 if (getVec().
getType().getSize() !=
2217 mlir::cast<cir::VectorType>(getIndices().
getType()).getSize()) {
2218 return emitOpError() <<
": the number of elements in " << getVec().getType()
2219 <<
" and " << getIndices().getType() <<
" don't match";
2228LogicalResult cir::VecTernaryOp::verify() {
2233 if (getCond().
getType().getSize() != getLhs().
getType().getSize()) {
2234 return emitOpError() <<
": the number of elements in "
2235 << getCond().getType() <<
" and " << getLhs().getType()
2241OpFoldResult cir::VecTernaryOp::fold(FoldAdaptor adaptor) {
2242 mlir::Attribute cond = adaptor.getCond();
2243 mlir::Attribute lhs = adaptor.getLhs();
2244 mlir::Attribute rhs = adaptor.getRhs();
2246 if (!mlir::isa_and_nonnull<cir::ConstVectorAttr>(cond) ||
2247 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(lhs) ||
2248 !mlir::isa_and_nonnull<cir::ConstVectorAttr>(rhs))
2250 auto condVec = mlir::cast<cir::ConstVectorAttr>(cond);
2251 auto lhsVec = mlir::cast<cir::ConstVectorAttr>(lhs);
2252 auto rhsVec = mlir::cast<cir::ConstVectorAttr>(rhs);
2254 mlir::ArrayAttr condElts = condVec.getElts();
2257 elements.reserve(condElts.size());
2259 for (
const auto &[idx, condAttr] :
2260 llvm::enumerate(condElts.getAsRange<cir::IntAttr>())) {
2261 if (condAttr.getSInt()) {
2262 elements.push_back(lhsVec.getElts()[idx]);
2264 elements.push_back(rhsVec.getElts()[idx]);
2268 cir::VectorType vecTy = getLhs().getType();
2269 return cir::ConstVectorAttr::get(
2270 vecTy, mlir::ArrayAttr::get(getContext(), elements));
2277LogicalResult cir::ComplexCreateOp::verify() {
2280 <<
"operand type of cir.complex.create does not match its result type";
2287OpFoldResult cir::ComplexCreateOp::fold(FoldAdaptor adaptor) {
2288 mlir::Attribute real = adaptor.getReal();
2289 mlir::Attribute imag = adaptor.getImag();
2295 auto realAttr = mlir::cast<mlir::TypedAttr>(real);
2296 auto imagAttr = mlir::cast<mlir::TypedAttr>(imag);
2297 return cir::ConstComplexAttr::get(realAttr, imagAttr);
2304LogicalResult cir::ComplexRealOp::verify() {
2306 emitOpError() <<
": result type does not match operand type";
2312OpFoldResult cir::ComplexRealOp::fold(FoldAdaptor adaptor) {
2313 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
2314 return complexCreateOp.getOperand(0);
2317 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
2318 return complex ? complex.getReal() :
nullptr;
2325LogicalResult cir::ComplexImagOp::verify() {
2327 emitOpError() <<
": result type does not match operand type";
2333OpFoldResult cir::ComplexImagOp::fold(FoldAdaptor adaptor) {
2334 if (
auto complexCreateOp = getOperand().getDefiningOp<cir::ComplexCreateOp>())
2335 return complexCreateOp.getOperand(1);
2338 mlir::cast_if_present<cir::ConstComplexAttr>(adaptor.getOperand());
2339 return complex ? complex.getImag() :
nullptr;
2346LogicalResult cir::ComplexRealPtrOp::verify() {
2347 mlir::Type resultPointeeTy =
getType().getPointee();
2348 cir::PointerType operandPtrTy = getOperand().getType();
2349 auto operandPointeeTy =
2350 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
2352 if (resultPointeeTy != operandPointeeTy.getElementType()) {
2353 return emitOpError() <<
": result type does not match operand type";
2363LogicalResult cir::ComplexImagPtrOp::verify() {
2364 mlir::Type resultPointeeTy =
getType().getPointee();
2365 cir::PointerType operandPtrTy = getOperand().getType();
2366 auto operandPointeeTy =
2367 mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
2369 if (resultPointeeTy != operandPointeeTy.getElementType()) {
2370 return emitOpError()
2371 <<
"cir.complex.imag_ptr result type does not match operand type";
2382 llvm::function_ref<llvm::APInt(
const llvm::APInt &)> func,
2383 bool poisonZero =
false) {
2384 if (mlir::isa_and_present<cir::PoisonAttr>(inputAttr)) {
2389 auto input = mlir::dyn_cast_if_present<IntAttr>(inputAttr);
2393 llvm::APInt inputValue = input.getValue();
2394 if (poisonZero && inputValue.isZero())
2395 return cir::PoisonAttr::get(input.getType());
2397 llvm::APInt resultValue = func(inputValue);
2398 return IntAttr::get(input.getType(), resultValue);
2401OpFoldResult BitClrsbOp::fold(FoldAdaptor adaptor) {
2402 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
2403 unsigned resultValue =
2404 inputValue.getBitWidth() - inputValue.getSignificantBits();
2405 return llvm::APInt(inputValue.getBitWidth(), resultValue);
2409OpFoldResult BitClzOp::fold(FoldAdaptor adaptor) {
2412 [](
const llvm::APInt &inputValue) {
2413 unsigned resultValue = inputValue.countLeadingZeros();
2414 return llvm::APInt(inputValue.getBitWidth(), resultValue);
2419OpFoldResult BitCtzOp::fold(FoldAdaptor adaptor) {
2422 [](
const llvm::APInt &inputValue) {
2423 return llvm::APInt(inputValue.getBitWidth(),
2424 inputValue.countTrailingZeros());
2429OpFoldResult BitFfsOp::fold(FoldAdaptor adaptor) {
2430 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
2431 unsigned trailingZeros = inputValue.countTrailingZeros();
2433 trailingZeros == inputValue.getBitWidth() ? 0 : trailingZeros + 1;
2434 return llvm::APInt(inputValue.getBitWidth(), result);
2438OpFoldResult BitParityOp::fold(FoldAdaptor adaptor) {
2439 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
2440 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount() % 2);
2444OpFoldResult BitPopcountOp::fold(FoldAdaptor adaptor) {
2445 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
2446 return llvm::APInt(inputValue.getBitWidth(), inputValue.popcount());
2450OpFoldResult BitReverseOp::fold(FoldAdaptor adaptor) {
2451 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
2452 return inputValue.reverseBits();
2456OpFoldResult ByteSwapOp::fold(FoldAdaptor adaptor) {
2457 return foldUnaryBitOp(adaptor.getInput(), [](
const llvm::APInt &inputValue) {
2458 return inputValue.byteSwap();
2462OpFoldResult RotateOp::fold(FoldAdaptor adaptor) {
2463 if (mlir::isa_and_present<cir::PoisonAttr>(adaptor.getInput()) ||
2464 mlir::isa_and_present<cir::PoisonAttr>(adaptor.getAmount())) {
2466 return cir::PoisonAttr::get(
getType());
2469 auto input = mlir::dyn_cast_if_present<IntAttr>(adaptor.getInput());
2470 auto amount = mlir::dyn_cast_if_present<IntAttr>(adaptor.getAmount());
2471 if (!input && !amount)
2480 llvm::APInt inputValue;
2482 inputValue = input.getValue();
2483 if (inputValue.isZero() || inputValue.isAllOnes()) {
2489 uint64_t amountValue;
2491 amountValue = amount.getValue().urem(getInput().
getType().getWidth());
2492 if (amountValue == 0) {
2498 if (!input || !amount)
2501 assert(inputValue.getBitWidth() == getInput().
getType().getWidth() &&
2502 "input value must have the same bit width as the input type");
2504 llvm::APInt resultValue;
2506 resultValue = inputValue.rotl(amountValue);
2508 resultValue = inputValue.rotr(amountValue);
2510 return IntAttr::get(input.getContext(), input.getType(), resultValue);
2517void cir::InlineAsmOp::print(OpAsmPrinter &p) {
2518 p <<
'(' << getAsmFlavor() <<
", ";
2523 auto *nameIt = names.begin();
2524 auto *attrIt = getOperandAttrs().begin();
2526 for (mlir::OperandRange ops : getAsmOperands()) {
2527 p << *nameIt <<
" = ";
2530 llvm::interleaveComma(llvm::make_range(ops.begin(), ops.end()), p,
2532 p.printOperand(value);
2533 p <<
" : " << value.getType();
2535 p <<
" (maybe_memory)";
2544 p.printString(getAsmString());
2546 p.printString(getConstraints());
2550 if (getSideEffects())
2551 p <<
" side_effects";
2553 std::array elidedAttrs{
2554 llvm::StringRef(
"asm_flavor"), llvm::StringRef(
"asm_string"),
2555 llvm::StringRef(
"constraints"), llvm::StringRef(
"operand_attrs"),
2556 llvm::StringRef(
"operands_segments"), llvm::StringRef(
"side_effects")};
2557 p.printOptionalAttrDict(getOperation()->getAttrs(), elidedAttrs);
2559 if (
auto v = getRes())
2560 p <<
" -> " << v.getType();
2563void cir::InlineAsmOp::build(OpBuilder &odsBuilder, OperationState &odsState,
2565 StringRef asmString, StringRef constraints,
2566 bool sideEffects, cir::AsmFlavor asmFlavor,
2570 for (
auto operandRange : asmOperands) {
2571 segments.push_back(operandRange.size());
2572 odsState.addOperands(operandRange);
2575 odsState.addAttribute(
2576 "operands_segments",
2577 DenseI32ArrayAttr::get(odsBuilder.getContext(), segments));
2578 odsState.addAttribute(
"asm_string", odsBuilder.getStringAttr(asmString));
2579 odsState.addAttribute(
"constraints", odsBuilder.getStringAttr(constraints));
2580 odsState.addAttribute(
"asm_flavor",
2581 AsmFlavorAttr::get(odsBuilder.getContext(), asmFlavor));
2584 odsState.addAttribute(
"side_effects", odsBuilder.getUnitAttr());
2586 odsState.addAttribute(
"operand_attrs", odsBuilder.getArrayAttr(operandAttrs));
2589ParseResult cir::InlineAsmOp::parse(OpAsmParser &parser,
2590 OperationState &result) {
2593 std::string asmString, constraints;
2595 MLIRContext *ctxt = parser.getBuilder().getContext();
2597 auto error = [&](
const Twine &msg) -> LogicalResult {
2598 return parser.emitError(parser.getCurrentLocation(), msg);
2601 auto expected = [&](
const std::string &
c) {
2602 return error(
"expected '" +
c +
"'");
2605 if (parser.parseLParen().failed())
2606 return expected(
"(");
2608 auto flavor = FieldParser<AsmFlavor, AsmFlavor>::parse(parser);
2610 return error(
"Unknown AsmFlavor");
2612 if (parser.parseComma().failed())
2613 return expected(
",");
2615 auto parseValue = [&](
Value &v) {
2616 OpAsmParser::UnresolvedOperand op;
2618 if (parser.parseOperand(op) || parser.parseColon())
2619 return error(
"can't parse operand");
2622 if (parser.parseType(typ).failed())
2623 return error(
"can't parse operand type");
2625 if (parser.resolveOperand(op, typ, tmp))
2626 return error(
"can't resolve operand");
2628 return mlir::success();
2631 auto parseOperands = [&](llvm::StringRef
name) {
2632 if (parser.parseKeyword(name).failed())
2633 return error(
"expected " + name +
" operands here");
2634 if (parser.parseEqual().failed())
2635 return expected(
"=");
2636 if (parser.parseLSquare().failed())
2637 return expected(
"[");
2640 if (parser.parseOptionalRSquare().succeeded()) {
2641 operandsGroupSizes.push_back(size);
2642 if (parser.parseComma())
2643 return expected(
",");
2644 return mlir::success();
2647 auto parseOperand = [&]() {
2649 if (parseValue(val).succeeded()) {
2650 result.operands.push_back(val);
2653 if (parser.parseOptionalLParen().failed()) {
2654 operandAttrs.push_back(mlir::Attribute());
2655 return mlir::success();
2658 if (parser.parseKeyword(
"maybe_memory").succeeded()) {
2659 operandAttrs.push_back(mlir::UnitAttr::get(ctxt));
2660 if (parser.parseRParen())
2661 return expected(
")");
2662 return mlir::success();
2664 return expected(
"maybe_memory");
2667 return mlir::failure();
2670 if (parser.parseCommaSeparatedList(parseOperand).failed())
2671 return mlir::failure();
2673 if (parser.parseRSquare().failed() || parser.parseComma().failed())
2674 return expected(
"]");
2675 operandsGroupSizes.push_back(size);
2676 return mlir::success();
2679 if (parseOperands(
"out").failed() || parseOperands(
"in").failed() ||
2680 parseOperands(
"in_out").failed())
2681 return error(
"failed to parse operands");
2683 if (parser.parseLBrace())
2684 return expected(
"{");
2685 if (parser.parseString(&asmString))
2686 return error(
"asm string parsing failed");
2687 if (parser.parseString(&constraints))
2688 return error(
"constraints string parsing failed");
2689 if (parser.parseRBrace())
2690 return expected(
"}");
2691 if (parser.parseRParen())
2692 return expected(
")");
2694 if (parser.parseOptionalKeyword(
"side_effects").succeeded())
2695 result.attributes.set(
"side_effects", UnitAttr::get(ctxt));
2697 if (parser.parseOptionalArrow().succeeded() &&
2698 parser.parseType(resType).failed())
2699 return mlir::failure();
2701 if (parser.parseOptionalAttrDict(result.attributes).failed())
2702 return mlir::failure();
2704 result.attributes.set(
"asm_flavor", AsmFlavorAttr::get(ctxt, *flavor));
2705 result.attributes.set(
"asm_string", StringAttr::get(ctxt, asmString));
2706 result.attributes.set(
"constraints", StringAttr::get(ctxt, constraints));
2707 result.attributes.set(
"operand_attrs", ArrayAttr::get(ctxt, operandAttrs));
2708 result.getOrAddProperties<InlineAsmOp::Properties>().operands_segments =
2709 parser.getBuilder().getDenseI32ArrayAttr(operandsGroupSizes);
2711 result.addTypes(TypeRange{resType});
2713 return mlir::success();
2720mlir::LogicalResult cir::ThrowOp::verify() {
2725 if (getNumOperands() != 0) {
2728 return emitOpError() <<
"'type_info' symbol attribute missing";
2738LogicalResult cir::AtomicCmpXchg::verify() {
2739 mlir::Type pointeeType = getPtr().getType().getPointee();
2741 if (pointeeType != getExpected().
getType() ||
2742 pointeeType != getDesired().
getType())
2743 return emitOpError(
"ptr, expected and desired types must match");
2752LogicalResult cir::TypeInfoAttr::verify(
2753 ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
2754 ::mlir::Type type, ::mlir::ArrayAttr typeInfoData) {
2756 if (cir::ConstRecordAttr::verify(emitError, type, typeInfoData).failed())
2766#define GET_OP_CLASSES
2767#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)
static void printGlobalOpTypeAndInitialValue(OpAsmPrinter &p, cir::GlobalOp op, TypeAttr type, Attribute initAttr)
static mlir::LogicalResult checkReturnAndFunction(cir::ReturnOp op, cir::FuncOp function)
static bool isBoolNot(cir::UnaryOp op)
static bool isIntOrBoolCast(cir::CastOp op)
static ParseResult parseGlobalOpTypeAndInitialValue(OpAsmParser &parser, TypeAttr &typeAttr, Attribute &initialValueAttr)
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 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 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()