@@ -73,6 +73,7 @@ Type adaptIntegralTypeSignedness(Type ty, bool needsUnsigned) {
7373
7474// / Insert a cast operation to type \p ty if \p val does not have this type.
7575Value adaptValueType (Value val, ConversionPatternRewriter &rewriter, Type ty) {
76+ assert (emitc::isSupportedEmitCType (val.getType ()));
7677 return rewriter.createOrFold <emitc::CastOp>(val.getLoc (), ty, val);
7778}
7879
@@ -279,7 +280,8 @@ class CmpIOpConversion : public OpConversionPattern<arith::CmpIOp> {
279280 ConversionPatternRewriter &rewriter) const override {
280281
281282 Type type = adaptor.getLhs ().getType ();
282- if (!type || !(isa<IntegerType>(type) || emitc::isPointerWideType (type))) {
283+ if (!type || !(emitc::isIntegerOrOpaqueType (type) ||
284+ emitc::isPointerWideType (type))) {
283285 return rewriter.notifyMatchFailure (
284286 op, " expected integer or size_t/ssize_t/ptrdiff_t type" );
285287 }
@@ -334,7 +336,7 @@ class CastConversion : public OpConversionPattern<ArithOp> {
334336 ConversionPatternRewriter &rewriter) const override {
335337
336338 Type opReturnType = this ->getTypeConverter ()->convertType (op.getType ());
337- if (!opReturnType || !(isa<IntegerType> (opReturnType) ||
339+ if (!opReturnType || !(emitc::isIntegerOrOpaqueType (opReturnType) ||
338340 emitc::isPointerWideType (opReturnType)))
339341 return rewriter.notifyMatchFailure (
340342 op, " expected integer or size_t/ssize_t/ptrdiff_t result type" );
@@ -345,7 +347,7 @@ class CastConversion : public OpConversionPattern<ArithOp> {
345347 }
346348
347349 Type operandType = adaptor.getIn ().getType ();
348- if (!operandType || !(isa<IntegerType> (operandType) ||
350+ if (!operandType || !(emitc::isIntegerOrOpaqueType (operandType) ||
349351 emitc::isPointerWideType (operandType)))
350352 return rewriter.notifyMatchFailure (
351353 op, " expected integer or size_t/ssize_t/ptrdiff_t operand type" );
@@ -439,16 +441,17 @@ class BinaryUIOpConversion final : public OpConversionPattern<ArithOp> {
439441 if (!newRetTy)
440442 return rewriter.notifyMatchFailure (uiBinOp,
441443 " converting result type failed" );
442- if (!isa<IntegerType>(newRetTy)) {
444+
445+ if (!emitc::isIntegerOrOpaqueType (newRetTy)) {
443446 return rewriter.notifyMatchFailure (uiBinOp, " expected integer type" );
444447 }
445448 Type unsignedType =
446449 adaptIntegralTypeSignedness (newRetTy, /* needsUnsigned=*/ true );
447450 if (!unsignedType)
448451 return rewriter.notifyMatchFailure (uiBinOp,
449452 " converting result type failed" );
450- Value lhsAdapted = adaptValueType (uiBinOp .getLhs (), rewriter, unsignedType);
451- Value rhsAdapted = adaptValueType (uiBinOp .getRhs (), rewriter, unsignedType);
453+ Value lhsAdapted = adaptValueType (adaptor .getLhs (), rewriter, unsignedType);
454+ Value rhsAdapted = adaptValueType (adaptor .getRhs (), rewriter, unsignedType);
452455
453456 auto newDivOp =
454457 rewriter.create <EmitCOp>(uiBinOp.getLoc (), unsignedType,
@@ -469,7 +472,8 @@ class IntegerOpConversion final : public OpConversionPattern<ArithOp> {
469472 ConversionPatternRewriter &rewriter) const override {
470473
471474 Type type = this ->getTypeConverter ()->convertType (op.getType ());
472- if (!type || !(isa<IntegerType>(type) || emitc::isPointerWideType (type))) {
475+ if (!type || !(emitc::isIntegerOrOpaqueType (type) ||
476+ emitc::isPointerWideType (type))) {
473477 return rewriter.notifyMatchFailure (
474478 op, " expected integer or size_t/ssize_t/ptrdiff_t type" );
475479 }
@@ -512,7 +516,7 @@ class BitwiseOpConversion : public OpConversionPattern<ArithOp> {
512516 ConversionPatternRewriter &rewriter) const override {
513517
514518 Type type = this ->getTypeConverter ()->convertType (op.getType ());
515- if (!isa_and_nonnull<IntegerType> (type)) {
519+ if (!type || ! emitc::isIntegerOrOpaqueType (type)) {
516520 return rewriter.notifyMatchFailure (
517521 op,
518522 " expected integer type, vector/tensor support not yet implemented" );
@@ -552,7 +556,9 @@ class ShiftOpConversion : public OpConversionPattern<ArithOp> {
552556 ConversionPatternRewriter &rewriter) const override {
553557
554558 Type type = this ->getTypeConverter ()->convertType (op.getType ());
555- if (!type || !(isa<IntegerType>(type) || emitc::isPointerWideType (type))) {
559+ bool retIsOpaque = isa_and_nonnull<emitc::OpaqueType>(type);
560+ if (!type || (!retIsOpaque && !(isa<IntegerType>(type) ||
561+ emitc::isPointerWideType (type)))) {
556562 return rewriter.notifyMatchFailure (
557563 op, " expected integer or size_t/ssize_t/ptrdiff_t type" );
558564 }
@@ -578,21 +584,33 @@ class ShiftOpConversion : public OpConversionPattern<ArithOp> {
578584 op.getLoc (), rhsType, " sizeof" , ArrayRef<Value>{eight});
579585 width = rewriter.create <emitc::MulOp>(op.getLoc (), rhsType, eight,
580586 sizeOfCall.getResult (0 ));
581- } else {
587+ } else if (!retIsOpaque) {
582588 width = rewriter.create <emitc::ConstantOp>(
583589 op.getLoc (), rhsType,
584590 rewriter.getIntegerAttr (rhsType, type.getIntOrFloatBitWidth ()));
591+ } else {
592+ width = rewriter.create <emitc::ConstantOp>(
593+ op.getLoc (), rhsType,
594+ emitc::OpaqueAttr::get (rhsType.getContext (),
595+ " opaque_shift_bitwidth" ));
585596 }
586597
587598 Value excessCheck = rewriter.create <emitc::CmpOp>(
588599 op.getLoc (), rewriter.getI1Type (), emitc::CmpPredicate::lt, rhs, width);
589600
590601 // Any concrete value is a valid refinement of poison.
591- Value poison = rewriter.create <emitc::ConstantOp>(
592- op.getLoc (), arithmeticType,
593- (isa<IntegerType>(arithmeticType)
594- ? rewriter.getIntegerAttr (arithmeticType, 0 )
595- : rewriter.getIndexAttr (0 )));
602+ Value poison;
603+ if (retIsOpaque) {
604+ poison = rewriter.create <emitc::ConstantOp>(
605+ op.getLoc (), arithmeticType,
606+ emitc::OpaqueAttr::get (rhsType.getContext (), " opaque_shift_poison" ));
607+ } else {
608+ poison = rewriter.create <emitc::ConstantOp>(
609+ op.getLoc (), arithmeticType,
610+ (isa<IntegerType>(arithmeticType)
611+ ? rewriter.getIntegerAttr (arithmeticType, 0 )
612+ : rewriter.getIndexAttr (0 )));
613+ }
596614
597615 emitc::ExpressionOp ternary = rewriter.create <emitc::ExpressionOp>(
598616 op.getLoc (), arithmeticType, /* do_not_inline=*/ false );
@@ -669,19 +687,23 @@ class FtoICastOpConversion : public OpConversionPattern<CastOp> {
669687 if (!dstType)
670688 return rewriter.notifyMatchFailure (castOp, " type conversion failed" );
671689
690+ Type actualResultType = dstType;
691+
672692 // Float-to-i1 casts are not supported: any value with 0 < value < 1 must be
673693 // truncated to 0, whereas a boolean conversion would return true.
674- if (!emitc::isSupportedIntegerType (dstType) || dstType.isInteger (1 ))
675- return rewriter.notifyMatchFailure (castOp,
676- " unsupported cast destination type" );
677-
678- // Convert to unsigned if it's the "ui" variant
679- // Signless is interpreted as signed, so no need to cast for "si"
680- Type actualResultType = dstType;
681- if (isa<arith::FPToUIOp>(castOp)) {
682- actualResultType =
683- rewriter.getIntegerType (dstType.getIntOrFloatBitWidth (),
684- /* isSigned=*/ false );
694+ bool dstIsOpaque = isa<emitc::OpaqueType>(dstType);
695+ if (!dstIsOpaque) {
696+ if (!emitc::isSupportedIntegerType (dstType) || dstType.isInteger (1 ))
697+ return rewriter.notifyMatchFailure (castOp,
698+ " unsupported cast destination type" );
699+
700+ // Convert to unsigned if it's the "ui" variant
701+ // Signless is interpreted as signed, so no need to cast for "si"
702+ if (isa<arith::FPToUIOp>(castOp)) {
703+ actualResultType =
704+ rewriter.getIntegerType (dstType.getIntOrFloatBitWidth (),
705+ /* isSigned=*/ false );
706+ }
685707 }
686708
687709 Value result = rewriter.create <emitc::CastOp>(
@@ -708,7 +730,9 @@ class ItoFCastOpConversion : public OpConversionPattern<CastOp> {
708730 ConversionPatternRewriter &rewriter) const override {
709731 // Vectors in particular are not supported
710732 Type operandType = adaptor.getIn ().getType ();
711- if (!emitc::isSupportedIntegerType (operandType))
733+ bool opIsOpaque = isa<emitc::OpaqueType>(operandType);
734+
735+ if (!(opIsOpaque || emitc::isSupportedIntegerType (operandType)))
712736 return rewriter.notifyMatchFailure (castOp,
713737 " unsupported cast source type" );
714738
@@ -723,7 +747,7 @@ class ItoFCastOpConversion : public OpConversionPattern<CastOp> {
723747 // Convert to unsigned if it's the "ui" variant
724748 // Signless is interpreted as signed, so no need to cast for "si"
725749 Type actualOperandType = operandType;
726- if (isa<arith::UIToFPOp>(castOp)) {
750+ if (!opIsOpaque && isa<arith::UIToFPOp>(castOp)) {
727751 actualOperandType =
728752 rewriter.getIntegerType (operandType.getIntOrFloatBitWidth (),
729753 /* isSigned=*/ false );
@@ -751,7 +775,7 @@ class FpCastOpConversion : public OpConversionPattern<CastOp> {
751775 ConversionPatternRewriter &rewriter) const override {
752776 // Vectors in particular are not supported.
753777 Type operandType = adaptor.getIn ().getType ();
754- if (!emitc::isSupportedFloatType (operandType))
778+ if (!emitc::isFloatOrOpaqueType (operandType))
755779 return rewriter.notifyMatchFailure (castOp,
756780 " unsupported cast source type" );
757781 if (auto roundingModeOp =
@@ -765,7 +789,7 @@ class FpCastOpConversion : public OpConversionPattern<CastOp> {
765789 if (!dstType)
766790 return rewriter.notifyMatchFailure (castOp, " type conversion failed" );
767791
768- if (!emitc::isSupportedFloatType (dstType))
792+ if (!emitc::isFloatOrOpaqueType (dstType))
769793 return rewriter.notifyMatchFailure (castOp,
770794 " unsupported cast destination type" );
771795
0 commit comments