diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala index 1dc166c46fe5..293895c1097d 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala @@ -119,15 +119,16 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder { // binary operation case rarg :: Nil => - resKind = tpeTK(larg).maxType(tpeTK(rarg)) - if (isShiftOp(code) || isBitwiseOp(code)) { + val isShift = isShiftOp(code) + resKind = tpeTK(larg).maxType(if (isShift) INT else tpeTK(rarg)) + + if (isShift || isBitwiseOp(code)) { assert(resKind.isIntegralType || (resKind == BOOL), s"$resKind incompatible with arithmetic modulo operation.") } genLoad(larg, resKind) - genLoad(rarg, // check .NET size of shift arguments! - if (isShiftOp(code)) INT else resKind) + genLoad(rarg, if (isShift) INT else resKind) (code: @switch) match { case ADD => bc add resKind diff --git a/compiler/src/dotty/tools/dotc/typer/ConstFold.scala b/compiler/src/dotty/tools/dotc/typer/ConstFold.scala index 43567923b1c2..0dcba1f6907c 100644 --- a/compiler/src/dotty/tools/dotc/typer/ConstFold.scala +++ b/compiler/src/dotty/tools/dotc/typer/ConstFold.scala @@ -115,9 +115,9 @@ object ConstFold { case nme.OR => Constant(x.longValue | y.longValue) case nme.XOR => Constant(x.longValue ^ y.longValue) case nme.AND => Constant(x.longValue & y.longValue) - case nme.LSL => Constant(x.longValue << y.longValue) - case nme.LSR => Constant(x.longValue >>> y.longValue) - case nme.ASR => Constant(x.longValue >> y.longValue) + case nme.LSL => if (x.tag <= IntTag) Constant(x.intValue << y.longValue.toInt) else Constant(x.longValue << y.longValue) + case nme.LSR => if (x.tag <= IntTag) Constant(x.intValue >>> y.longValue.toInt) else Constant(x.longValue >>> y.longValue) + case nme.ASR => if (x.tag <= IntTag) Constant(x.intValue >> y.longValue.toInt) else Constant(x.longValue >> y.longValue) case nme.EQ => Constant(x.longValue == y.longValue) case nme.NE => Constant(x.longValue != y.longValue) case nme.LT => Constant(x.longValue < y.longValue) diff --git a/tests/run/t9516.scala b/tests/run/t9516.scala new file mode 100644 index 000000000000..b3068dd1ff18 --- /dev/null +++ b/tests/run/t9516.scala @@ -0,0 +1,52 @@ +object Test { + def main(args: Array[String]): Unit = { + intShiftLeftLongConstantFolded() + intShiftLeftLongAtRuntime() + intShiftLogicalRightLongConstantFolded() + intShiftLogicalRightLongAtRuntime() + intShiftArithmeticRightLongConstantFolded() + intShiftArithmeticRightLongAtRuntime() + } + + def intShiftLeftLongConstantFolded(): Unit = { + assert(0x01030507 << 36L == 271601776) + val r = 0x01030507 << 36L + assert(r == 271601776) + } + + def intShiftLeftLongAtRuntime(): Unit = { + var x: Int = 0x01030507 + var y: Long = 36L + assert(x << y == 271601776) + val r = x << y + assert(r == 271601776) + } + + def intShiftLogicalRightLongConstantFolded(): Unit = { + assert(0x90503010 >>> 36L == 151323393) + val r = 0x90503010 >>> 36L + assert(r == 151323393) + } + + def intShiftLogicalRightLongAtRuntime(): Unit = { + var x: Int = 0x90503010 + var y: Long = 36L + assert(x >>> y == 151323393) + val r = x >>> y + assert(r == 151323393) + } + + def intShiftArithmeticRightLongConstantFolded(): Unit = { + assert(0x90503010 >> 36L == -117112063) + val r = 0x90503010 >> 36L + assert(r == -117112063) + } + + def intShiftArithmeticRightLongAtRuntime(): Unit = { + var x: Int = 0x90503010 + var y: Long = 36L + assert(x >> y == -117112063) + val r = x >> y + assert(r == -117112063) + } +}