Skip to content

Commit 2b95f1d

Browse files
authored
Merge pull request #6366 from sjrd/fix-int-shift-long-semantics
Fix the semantics of int-shift-long operations.
2 parents db7e411 + 722da71 commit 2b95f1d

File tree

3 files changed

+60
-7
lines changed

3 files changed

+60
-7
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala

+5-4
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,16 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
119119

120120
// binary operation
121121
case rarg :: Nil =>
122-
resKind = tpeTK(larg).maxType(tpeTK(rarg))
123-
if (isShiftOp(code) || isBitwiseOp(code)) {
122+
val isShift = isShiftOp(code)
123+
resKind = tpeTK(larg).maxType(if (isShift) INT else tpeTK(rarg))
124+
125+
if (isShift || isBitwiseOp(code)) {
124126
assert(resKind.isIntegralType || (resKind == BOOL),
125127
s"$resKind incompatible with arithmetic modulo operation.")
126128
}
127129

128130
genLoad(larg, resKind)
129-
genLoad(rarg, // check .NET size of shift arguments!
130-
if (isShiftOp(code)) INT else resKind)
131+
genLoad(rarg, if (isShift) INT else resKind)
131132

132133
(code: @switch) match {
133134
case ADD => bc add resKind

compiler/src/dotty/tools/dotc/typer/ConstFold.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,9 @@ object ConstFold {
115115
case nme.OR => Constant(x.longValue | y.longValue)
116116
case nme.XOR => Constant(x.longValue ^ y.longValue)
117117
case nme.AND => Constant(x.longValue & y.longValue)
118-
case nme.LSL => Constant(x.longValue << y.longValue)
119-
case nme.LSR => Constant(x.longValue >>> y.longValue)
120-
case nme.ASR => Constant(x.longValue >> y.longValue)
118+
case nme.LSL => if (x.tag <= IntTag) Constant(x.intValue << y.longValue.toInt) else Constant(x.longValue << y.longValue)
119+
case nme.LSR => if (x.tag <= IntTag) Constant(x.intValue >>> y.longValue.toInt) else Constant(x.longValue >>> y.longValue)
120+
case nme.ASR => if (x.tag <= IntTag) Constant(x.intValue >> y.longValue.toInt) else Constant(x.longValue >> y.longValue)
121121
case nme.EQ => Constant(x.longValue == y.longValue)
122122
case nme.NE => Constant(x.longValue != y.longValue)
123123
case nme.LT => Constant(x.longValue < y.longValue)

tests/run/t9516.scala

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
intShiftLeftLongConstantFolded()
4+
intShiftLeftLongAtRuntime()
5+
intShiftLogicalRightLongConstantFolded()
6+
intShiftLogicalRightLongAtRuntime()
7+
intShiftArithmeticRightLongConstantFolded()
8+
intShiftArithmeticRightLongAtRuntime()
9+
}
10+
11+
def intShiftLeftLongConstantFolded(): Unit = {
12+
assert(0x01030507 << 36L == 271601776)
13+
val r = 0x01030507 << 36L
14+
assert(r == 271601776)
15+
}
16+
17+
def intShiftLeftLongAtRuntime(): Unit = {
18+
var x: Int = 0x01030507
19+
var y: Long = 36L
20+
assert(x << y == 271601776)
21+
val r = x << y
22+
assert(r == 271601776)
23+
}
24+
25+
def intShiftLogicalRightLongConstantFolded(): Unit = {
26+
assert(0x90503010 >>> 36L == 151323393)
27+
val r = 0x90503010 >>> 36L
28+
assert(r == 151323393)
29+
}
30+
31+
def intShiftLogicalRightLongAtRuntime(): Unit = {
32+
var x: Int = 0x90503010
33+
var y: Long = 36L
34+
assert(x >>> y == 151323393)
35+
val r = x >>> y
36+
assert(r == 151323393)
37+
}
38+
39+
def intShiftArithmeticRightLongConstantFolded(): Unit = {
40+
assert(0x90503010 >> 36L == -117112063)
41+
val r = 0x90503010 >> 36L
42+
assert(r == -117112063)
43+
}
44+
45+
def intShiftArithmeticRightLongAtRuntime(): Unit = {
46+
var x: Int = 0x90503010
47+
var y: Long = 36L
48+
assert(x >> y == -117112063)
49+
val r = x >> y
50+
assert(r == -117112063)
51+
}
52+
}

0 commit comments

Comments
 (0)