Skip to content

Commit 95ab28e

Browse files
authored
Fix splitI64 so it can be used to send values from JS libraries into wasm (#19575)
When a JS library calls into wasm and the function has an i64 argument, we must legalize into two 32-bit integers if we lack BigInt support. Note that we may be able to do more efficient things than splitI64 (assuming the input uses only 53 bits, and is signed, can help simplify things a lot), but we leave that for optimization later. This removes the old/unused sendI64Argument.
1 parent 8d809aa commit 95ab28e

File tree

4 files changed

+50
-8
lines changed

4 files changed

+50
-8
lines changed

src/parseTools.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,12 @@ function makeInlineCalculation(expression, value, tempVar) {
213213
// value, represented by a low and high i32 pair.
214214
// Will suffer from rounding and truncation.
215215
function splitI64(value) {
216+
if (WASM_BIGINT) {
217+
// Nothing to do: just make sure it is a BigInt (as it must be of that
218+
// type, to be sent into wasm).
219+
return `BigInt(${value})`;
220+
}
221+
216222
// general idea:
217223
//
218224
// $1$0 = ~~$d >>> 0;
@@ -229,7 +235,6 @@ function splitI64(value) {
229235
// For negatives, we need to ensure a -1 if the value is overall negative,
230236
// even if not significant negative component
231237

232-
assert(!WASM_BIGINT, 'splitI64 should not be used when WASM_BIGINT is enabled');
233238
const low = value + '>>>0';
234239
const high = makeInlineCalculation(
235240
asmCoercion('Math.abs(VALUE)', 'double') + ' >= ' + asmEnsureFloat('1', 'double') + ' ? ' +
@@ -886,15 +891,10 @@ function receiveI64ParamAsI53(name, onError) {
886891
}
887892

888893
function receiveI64ParamAsI53Unchecked(name) {
889-
if (WASM_BIGINT) return `${name} = Number(${name});`;
890-
return `var ${name} = convertI32PairToI53(${name}_low, ${name}_high);`;
891-
}
892-
893-
function sendI64Argument(low, high) {
894894
if (WASM_BIGINT) {
895-
return 'BigInt(low) | (BigInt(high) << 32n)';
895+
return `${name} = Number(${name});`;
896896
}
897-
return low + ', ' + high;
897+
return `var ${name} = convertI32PairToI53(${name}_low, ${name}_high);`;
898898
}
899899

900900
// Any function called from wasm64 may have bigint args, this function takes

test/core/js_library_i64_params.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <assert.h>
2+
#include <emscripten.h>
23
#include <stdio.h>
34

45
#define MAX_SAFE_INTEGER (1ll<<53)
@@ -8,6 +9,11 @@
89

910
int64_t jscall(int64_t arg);
1011

12+
EMSCRIPTEN_KEEPALIVE
13+
void called_from_js(uint64_t arg) {
14+
printf("called_from_js with: %lld\n", arg);
15+
}
16+
1117
void check_ok(int64_t val) {
1218
printf("checking: %lld\n", val);
1319
int64_t rtn = jscall(val);
@@ -25,7 +31,11 @@ void check_invalid(int64_t val) {
2531
}
2632

2733
int main() {
34+
check_ok(0);
35+
check_ok(1);
36+
check_ok(-1);
2837
check_ok(42);
38+
check_ok(-42);
2939
check_ok(MAX_SAFE_INTEGER/2);
3040
check_ok(MIN_SAFE_INTEGER/2);
3141
check_ok(MAX_SAFE_INTEGER);

test/core/js_library_i64_params.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ TestLibrary = {
44
jscall: function({{{ defineI64Param('foo') }}}) {
55
{{{ receiveI64ParamAsI53('foo', `(err('overflow'), ${makeReturn64('42')})`) }}}
66
err('js:got: ' + foo);
7+
8+
_called_from_js({{{ splitI64("foo") }}});
9+
710
if (foo < 0)
811
var rtn = Math.ceil(foo / 2);
912
else

test/core/js_library_i64_params.out

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,54 @@
1+
checking: 0
2+
js:got: 0
3+
called_from_js with: 0
4+
js:returning: 0
5+
got: 0
6+
expected: 0
7+
checking: 1
8+
js:got: 1
9+
called_from_js with: 1
10+
js:returning: 0
11+
got: 0
12+
expected: 0
13+
checking: -1
14+
js:got: -1
15+
called_from_js with: -1
16+
js:returning: 0
17+
got: 0
18+
expected: 0
119
checking: 42
220
js:got: 42
21+
called_from_js with: 42
322
js:returning: 21
423
got: 21
524
expected: 21
25+
checking: -42
26+
js:got: -42
27+
called_from_js with: -42
28+
js:returning: -21
29+
got: -21
30+
expected: -21
631
checking: 4503599627370496
732
js:got: 4503599627370496
33+
called_from_js with: 4503599627370496
834
js:returning: 2251799813685248
935
got: 2251799813685248
1036
expected: 2251799813685248
1137
checking: -4503599627370496
1238
js:got: -4503599627370496
39+
called_from_js with: -4503599627370496
1340
js:returning: -2251799813685248
1441
got: -2251799813685248
1542
expected: -2251799813685248
1643
checking: 9007199254740992
1744
js:got: 9007199254740992
45+
called_from_js with: 9007199254740992
1846
js:returning: 4503599627370496
1947
got: 4503599627370496
2048
expected: 4503599627370496
2149
checking: -9007199254740992
2250
js:got: -9007199254740992
51+
called_from_js with: -9007199254740992
2352
js:returning: -4503599627370496
2453
got: -4503599627370496
2554
expected: -4503599627370496

0 commit comments

Comments
 (0)