Skip to content

Commit 2e429e0

Browse files
smarterlrytz
andcommitted
Fix #7677: Fix comparisons involving NaN
This reverts the fix in 10cc2f8 which was apparently incomplete since it doesn't handle i7677.scala correctly and replace it by the original fix done in scalac in scala/scala#5207. (It might have been possible to fix the dotty version instead, but I'd rather keep the dotty backend as close as possible to the scalac backend). Since this commit contains code from scalac it is: Co-Authored-By: Lukas Rytz <lukas.rytz@gmail.com>
1 parent bc4c565 commit 2e429e0

File tree

3 files changed

+26
-15
lines changed

3 files changed

+26
-15
lines changed

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

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,23 +1224,20 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
12241224
}
12251225

12261226
/* Emit code to compare the two top-most stack values using the 'op' operator. */
1227-
private def genCJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label): Unit = {
1228-
if (targetIfNoJump == success) genCJUMP(failure, success, op.negate(), tk, targetIfNoJump)
1227+
private def genCJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label, negated: Boolean = false): Unit = {
1228+
if (targetIfNoJump == success) genCJUMP(failure, success, op.negate(), tk, targetIfNoJump, negated = !negated)
12291229
else {
12301230
if (tk.isIntSizedType) { // BOOL, BYTE, CHAR, SHORT, or INT
12311231
bc.emitIF_ICMP(op, success)
12321232
} else if (tk.isRef) { // REFERENCE(_) | ARRAY(_)
12331233
bc.emitIF_ACMP(op, success)
12341234
} else {
12351235
import Primitives._
1236+
def useCmpG = if (negated) op == GT || op == GE else op == LT || op == LE
12361237
(tk: @unchecked) match {
12371238
case LONG => emit(asm.Opcodes.LCMP)
1238-
case FLOAT =>
1239-
if (op == LT || op == LE) emit(asm.Opcodes.FCMPL)
1240-
else emit(asm.Opcodes.FCMPG)
1241-
case DOUBLE =>
1242-
if (op == LT || op == LE) emit(asm.Opcodes.DCMPL)
1243-
else emit(asm.Opcodes.DCMPG)
1239+
case FLOAT => emit(if (useCmpG) asm.Opcodes.FCMPG else asm.Opcodes.FCMPL)
1240+
case DOUBLE => emit(if (useCmpG) asm.Opcodes.DCMPG else asm.Opcodes.DCMPL)
12441241
}
12451242
bc.emitIF(op, success)
12461243
}
@@ -1249,9 +1246,9 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
12491246
}
12501247

12511248
/* Emits code to compare (and consume) stack-top and zero using the 'op' operator */
1252-
private def genCZJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label): Unit = {
1249+
private def genCZJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label, negated: Boolean = false): Unit = {
12531250
import Primitives._
1254-
if (targetIfNoJump == success) genCZJUMP(failure, success, op.negate(), tk, targetIfNoJump)
1251+
if (targetIfNoJump == success) genCZJUMP(failure, success, op.negate(), tk, targetIfNoJump, negated = !negated)
12551252
else {
12561253
if (tk.isIntSizedType) { // BOOL, BYTE, CHAR, SHORT, or INT
12571254
bc.emitIF(op, success)
@@ -1261,18 +1258,17 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
12611258
case NE => bc emitIFNONNULL success
12621259
}
12631260
} else {
1261+
def useCmpG = if (negated) op == GT || op == GE else op == LT || op == LE
12641262
(tk: @unchecked) match {
12651263
case LONG =>
12661264
emit(asm.Opcodes.LCONST_0)
12671265
emit(asm.Opcodes.LCMP)
12681266
case FLOAT =>
12691267
emit(asm.Opcodes.FCONST_0)
1270-
if (op == LT || op == LE) emit(asm.Opcodes.FCMPL)
1271-
else emit(asm.Opcodes.FCMPG)
1268+
emit(if (useCmpG) asm.Opcodes.FCMPG else asm.Opcodes.FCMPL)
12721269
case DOUBLE =>
12731270
emit(asm.Opcodes.DCONST_0)
1274-
if (op == LT || op == LE) emit(asm.Opcodes.DCMPL)
1275-
else emit(asm.Opcodes.DCMPG)
1271+
emit(if (useCmpG) asm.Opcodes.DCMPG else asm.Opcodes.DCMPL)
12761272
}
12771273
bc.emitIF(op, success)
12781274
}
@@ -1287,8 +1283,8 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
12871283
case ScalaPrimitivesOps.NE => Primitives.NE
12881284
case ScalaPrimitivesOps.LT => Primitives.LT
12891285
case ScalaPrimitivesOps.LE => Primitives.LE
1290-
case ScalaPrimitivesOps.GE => Primitives.GE
12911286
case ScalaPrimitivesOps.GT => Primitives.GT
1287+
case ScalaPrimitivesOps.GE => Primitives.GE
12921288
}
12931289

12941290
/*
File renamed without changes.

tests/run/i7677.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
val a: Double = Double.NaN
4+
val eval = (a <= 0) || (10L <= 0)
5+
assert(!eval)
6+
val eval2 = (Double.NaN <= 0) || (10L <= 0)
7+
assert(!eval2)
8+
9+
val b: Float = Float.NaN
10+
val eval3 = (b <= 0) || (10L <= 0)
11+
assert(!eval3)
12+
val eval4 = (Float.NaN <= 0) || (10L <= 0)
13+
assert(!eval4)
14+
}
15+
}

0 commit comments

Comments
 (0)