mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[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:
parent
770c9d77c5
commit
54dbb42244
|
@ -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(),
|
||||
|
|
Loading…
Reference in a new issue