[dart2wasm] Fix int left and right shifts
New passing tests:
- co19/Language/Expressions/Numbers/syntax_t06
- co19/Language/Expressions/Shift/integer_t01
- co19/Language/Expressions/Shift/integer_t02
- co19/Language/Expressions/Shift/integer_t03
- co19/Language/Expressions/Shift/integer_t04
- co19/Language/Expressions/Shift/integer_t06
- co19/Language/Expressions/Shift/integer_t07
- co19/Language/Types/Type_Aliases/built-in_types_t09
- co19/Language/Types/Type_Aliases/built-in_types_t10
- co19/Language/Types/Type_Aliases/built-in_types_t11
- co19/LanguageFeatures/Triple-Shift/Constants_A01_t09
- co19/LibTest/core/int/operator_left_shift_A01_t03
- co19/LibTest/core/int/operator_right_shift_A01_t03
- corelib/integer_parsed_arith_vm_test
- corelib/unsigned_shift_test/07
- corelib/unsigned_shift_test/08
- corelib/unsigned_shift_test/none
- language/operator/bit_operations_test/03
- language/operator/bit_operations_test/04
- language/operator/bit_operations_test/none
- language/operator/bit_shift_test
- language/regress/regress24283_test
Change-Id: I61c1224f8490d413002ea53270773370bc2cd334
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/267921
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
diff --git a/pkg/dart2wasm/lib/intrinsics.dart b/pkg/dart2wasm/lib/intrinsics.dart
index a6889ab..92bb76c 100644
--- a/pkg/dart2wasm/lib/intrinsics.dart
+++ b/pkg/dart2wasm/lib/intrinsics.dart
@@ -37,9 +37,6 @@
'&': (b) => b.i64_and(),
'|': (b) => b.i64_or(),
'^': (b) => b.i64_xor(),
- '<<': (b) => b.i64_shl(),
- '>>': (b) => b.i64_shr_s(),
- '>>>': (b) => b.i64_shr_u(),
'<': (b) => b.i64_lt_s(),
'<=': (b) => b.i64_le_s(),
'>': (b) => b.i64_gt_s(),
@@ -734,6 +731,42 @@
codeGen.wrap(second, w.NumType.i64);
b.i64_div_s();
return w.NumType.i64;
+ case "_shl":
+ assert(cls == translator.boxedIntClass);
+ assert(node.arguments.positional.length == 2);
+ Expression first = node.arguments.positional[0];
+ Expression second = node.arguments.positional[1];
+ codeGen.wrap(first, w.NumType.i64);
+ codeGen.wrap(second, w.NumType.i64);
+ b.i64_shl();
+ return w.NumType.i64;
+ case "_shr_s":
+ assert(cls == translator.boxedIntClass);
+ assert(node.arguments.positional.length == 2);
+ Expression first = node.arguments.positional[0];
+ Expression second = node.arguments.positional[1];
+ codeGen.wrap(first, w.NumType.i64);
+ codeGen.wrap(second, w.NumType.i64);
+ b.i64_shr_s();
+ return w.NumType.i64;
+ case "_shr_u":
+ assert(cls == translator.boxedIntClass);
+ assert(node.arguments.positional.length == 2);
+ Expression first = node.arguments.positional[0];
+ Expression second = node.arguments.positional[1];
+ codeGen.wrap(first, w.NumType.i64);
+ codeGen.wrap(second, w.NumType.i64);
+ b.i64_shr_u();
+ return w.NumType.i64;
+ case "_lt_u":
+ assert(cls == translator.boxedIntClass);
+ assert(node.arguments.positional.length == 2);
+ Expression first = node.arguments.positional[0];
+ Expression second = node.arguments.positional[1];
+ codeGen.wrap(first, w.NumType.i64);
+ codeGen.wrap(second, w.NumType.i64);
+ b.i64_lt_u();
+ return w.NumType.i32; // bool
case "_toInt":
assert(cls == translator.boxedDoubleClass);
assert(node.arguments.positional.length == 1);
diff --git a/sdk/lib/_internal/wasm/lib/int.dart b/sdk/lib/_internal/wasm/lib/int.dart
index f7dcc06..72457ff 100644
--- a/sdk/lib/_internal/wasm/lib/int.dart
+++ b/sdk/lib/_internal/wasm/lib/int.dart
@@ -66,9 +66,59 @@
external int operator |(int other);
external int operator ^(int other);
- external int operator >>(int other);
- external int operator >>>(int other);
- external int operator <<(int other);
+ int operator >>(int shift) {
+ // Unsigned comparison to check for large and negative shifts
+ if (_lt_u(shift, 64)) {
+ return _shr_s(this, shift);
+ }
+
+ if (shift < 0) {
+ throw ArgumentError(shift);
+ }
+
+ // shift >= 64, 0 or -1 depending on sign: `this >= 0 ? 0 : -1`
+ return _shr_s(this, 63);
+ }
+
+ int operator >>>(int shift) {
+ // Unsigned comparison to check for large and negative shifts
+ if (_lt_u(shift, 64)) {
+ return _shr_u(this, shift);
+ }
+
+ if (shift < 0) {
+ throw ArgumentError(shift);
+ }
+
+ // shift >= 64
+ return 0;
+ }
+
+ int operator <<(int shift) {
+ // Unsigned comparison to check for large and negative shifts
+ if (_lt_u(shift, 64)) {
+ return _shl(this, shift);
+ }
+
+ if (shift < 0) {
+ throw ArgumentError(shift);
+ }
+
+ // shift >= 64
+ return 0;
+ }
+
+ /// Wasm i64.lt_u instruction
+ external static bool _lt_u(int a, int b);
+
+ /// Wasm i64.shr_s instruction
+ external static int _shr_s(int a, int b);
+
+ /// Wasm i64.shr_u instruction
+ external static int _shr_u(int a, int b);
+
+ /// Wasm i64.shl instruction
+ external static int _shl(int a, int b);
external bool operator <(num other);
external bool operator >(num other);