[dart2wasm] Fix truncating int div code gen

Wasm `i64.div_s` result[1] is undefined when the division result is
2^63, and v8 traps with "divide result unrepresentable".

This change follows the checks in native runtime (in
`Integer::ArithmeticOp`) to handle overflowing in
`-9223372036854775808 ~/ -1`:

   case Token::kTRUNCDIV:
     if ((left_value == Mint::kMinValue) && (right_value == -1)) {
       return Integer::New(Mint::kMinValue, space);
     }
     return Integer::New(left_value / right_value, space);

These tests now pass:

- corelib/integer_parsed_div_rem_vm_test/01
- language/operator/left_shift_test

language/operator/arithmetic_test used to fail with the same trap, but
it now fails because of #50228.

[1]: https://webassembly.github.io/spec/core/exec/numerics.html#op-idiv-s

Change-Id: Ib43ac7a53d5cf96c01b016f73240da533ef84516
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/264460
Commit-Queue: Ömer Ağacan <omersa@google.com>
Reviewed-by: Joshua Litt <joshualitt@google.com>
This commit is contained in:
Ömer Sinan Ağacan 2022-10-18 07:06:46 +00:00 committed by Commit Queue
parent 770c9d77c5
commit 54dbb42244

View file

@ -32,7 +32,35 @@ class Intrinsifier {
'+': (b) => b.i64_add(),
'-': (b) => b.i64_sub(),
'*': (b) => b.i64_mul(),
'~/': (b) => b.i64_div_s(),
'~/': (b) {
final arg2Local = b.addLocal(intType, isParameter: false);
b.local_set(arg2Local);
final arg1Local = b.addLocal(intType, isParameter: false);
b.local_set(arg1Local);
// Division special case: overflow in I64.
// MIN_VALUE / -1 = (MAX_VALUE + 1), which wraps around to MIN_VALUE
b.local_get(arg2Local);
b.i64_const(-1);
b.i64_eq();
b.if_([], [intType]);
b.local_get(arg1Local);
b.i64_const(-9223372036854775808); // MIN_VALUE
b.i64_eq();
b.if_([], [intType]);
b.i64_const(-9223372036854775808); // MIN_VALUE
b.else_();
b.local_get(arg1Local);
b.local_get(arg2Local);
b.i64_div_s();
b.end();
b.else_();
b.local_get(arg1Local);
b.local_get(arg2Local);
b.i64_div_s();
b.end();
},
'&': (b) => b.i64_and(),
'|': (b) => b.i64_or(),
'^': (b) => b.i64_xor(),