Skip to content

Commit dd59daa

Browse files
authored
[wasm64] Fix wasm64 + MINIMAL_RUNTIME (#16956)
Move the instrumentWasmExportsForMemory64 helper out into its own file so we have be used under MINIMAL_RUNTIME too. In the long run this function should be replaced with something more data driven but for now this works. Split out from #16922
1 parent 9b15472 commit dd59daa

File tree

6 files changed

+81
-53
lines changed

6 files changed

+81
-53
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ jobs:
381381
executor: bionic
382382
steps:
383383
- run-tests-linux:
384-
test_targets: "wasm64.test_hello_world wasm64.test_ccall wasm64l.test_hello_world wasm64l.test_mmap wasm64l.test_unistd_* skip:wasm64l.test_unistd_sysconf wasm64l.test_mmap_file wasm64l.test_ccall wasm64l.test_signals wasm64l.test_emscripten_get_compiler_setting wasm64l.test_float_builtins wasm64l.test_getopt wasm64l.test_em_asm*"
384+
test_targets: "wasm64.test_hello_world wasm64.test_ccall wasm64l.test_hello_world wasm64l.test_mmap wasm64l.test_unistd_* skip:wasm64l.test_unistd_sysconf wasm64l.test_mmap_file wasm64l.test_ccall wasm64l.test_signals wasm64l.test_emscripten_get_compiler_setting wasm64l.test_float_builtins wasm64l.test_getopt wasm64l.test_em_asm* wasm64l.test_minimal_runtime_utf8_invalid"
385385
test-other:
386386
executor: bionic
387387
steps:

embuilder.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
'libc++-noexcept',
4141
'libal',
4242
'libdlmalloc',
43+
'libdlmalloc-noerrno',
4344
'libdlmalloc-debug',
4445
'libemmalloc',
4546
'libemmalloc-debug',

src/postamble_minimal.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ WebAssembly.instantiate(Module['wasm'], imports).then(function(output) {
199199
asm = output.instance.exports;
200200
#endif
201201

202+
#if MEMORY64
203+
asm = instrumentWasmExportsForMemory64(asm);
204+
#endif
205+
202206
#if USE_OFFSET_CONVERTER
203207
#if USE_PTHREADS
204208
if (!ENVIRONMENT_IS_PTHREAD)

src/preamble.js

Lines changed: 4 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ if (typeof WebAssembly != 'object') {
5050
#include "runtime_asan.js"
5151
#endif
5252

53+
#if MEMORY64
54+
#include "runtime_wasm64.js"
55+
#endif
56+
5357
// Wasm globals
5458

5559
var wasmMemory;
@@ -772,58 +776,6 @@ function instrumentWasmTableWithAbort() {
772776
}
773777
#endif
774778

775-
#if MEMORY64
776-
// In memory64 mode wasm pointers are 64-bit. To support that in JS we must use
777-
// BigInts. For now we keep JS as much the same as it always was, that is,
778-
// stackAlloc() receives and returns a Number from the JS point of view -
779-
// we translate BigInts automatically for that.
780-
// TODO: support minified export names, so we can turn MINIFY_WASM_IMPORTS_AND_EXPORTS
781-
// back on for MEMORY64.
782-
function instrumentWasmExportsForMemory64(exports) {
783-
var instExports = {};
784-
for (var name in exports) {
785-
(function(name) {
786-
var original = exports[name];
787-
var replacement = original;
788-
if (name === 'stackAlloc' || name === 'malloc' || name === 'emscripten_builtin_malloc') {
789-
// get one i64, return an i64
790-
replacement = (x) => {
791-
var r = Number(original(BigInt(x)));
792-
return r;
793-
};
794-
} else if (name === 'free') {
795-
// get one i64
796-
replacement = (x) => {
797-
original(BigInt(x));
798-
};
799-
} else if (name === 'emscripten_stack_get_end' ||
800-
name === 'emscripten_stack_get_base' ||
801-
name === 'emscripten_stack_get_current') {
802-
// return an i64
803-
replacement = () => {
804-
var r = Number(original());
805-
return r;
806-
};
807-
} else if (name === 'emscripten_builtin_memalign') {
808-
// get two i64, return an i64
809-
replacement = (x, y) => {
810-
var r = Number(original(BigInt(x), BigInt(y)));
811-
return r;
812-
};
813-
} else if (name === 'main') {
814-
// get a i64 as second arg
815-
replacement = (x, y) => {
816-
var r = original(x, BigInt(y));
817-
return r;
818-
};
819-
}
820-
instExports[name] = replacement;
821-
})(name);
822-
}
823-
return instExports;
824-
}
825-
#endif MEMORY64
826-
827779
var wasmBinaryFile;
828780
#if EXPORT_ES6 && USE_ES6_IMPORT_META && !SINGLE_FILE
829781
if (Module['locateFile']) {

src/preamble_minimal.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
#include "runtime_asan.js"
1313
#endif
1414

15+
#if MEMORY64
16+
#include "runtime_wasm64.js"
17+
#endif
18+
1519
#if ASSERTIONS || SAFE_HEAP
1620
/** @type {function(*, string=)} */
1721
function assert(condition, text) {

src/runtime_wasm64.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* @license
3+
* Copyright 2022 The Emscripten Authors
4+
* SPDX-License-Identifier: MIT
5+
*/
6+
7+
#if !MEMORY64
8+
#error "should only be inclded in MEMORY64 mode"
9+
#endif
10+
11+
// In memory64 mode wasm pointers are 64-bit. In JS these show up as BigInts.
12+
// For now, we keep JS as much the same as it always was, that is, stackAlloc()
13+
// receives and returns a Number from the JS point of view - we translate
14+
// BigInts automatically for that.
15+
// TODO: support minified export names, so we can turn
16+
// MINIFY_WASM_IMPORTS_AND_EXPORTS back on for MEMORY64.
17+
// TODO: Remove this hacky mechanism and replace with something more like the
18+
// `__sig` attributes we have in JS library code.
19+
function instrumentWasmExportsForMemory64(exports) {
20+
var instExports = {};
21+
for (var name in exports) {
22+
(function(name) {
23+
var original = exports[name];
24+
var replacement = original;
25+
if (['stackAlloc', 'emscripten_builtin_malloc', 'malloc', '__getTypeName'].includes(name)) {
26+
// get one i64, return an i64.
27+
replacement = (x) => {
28+
var r = Number(original(BigInt(x)));
29+
return r;
30+
};
31+
} else if (['setThrew', 'free', 'stackRestore', '__cxa_is_pointer_type'].includes(name)) {
32+
// get one i64
33+
replacement = (x) => {
34+
original(BigInt(x));
35+
};
36+
} else if (['stackSave', 'emscripten_stack_get_end',
37+
'emscripten_stack_get_base', 'pthread_self',
38+
'emscripten_stack_get_current',
39+
'__errno_location'].includes(name)) {
40+
// return an i64
41+
replacement = () => {
42+
var r = Number(original());
43+
return r;
44+
};
45+
} else if (name === 'emscripten_builtin_memalign') {
46+
// get two i64, return an i64
47+
replacement = (x, y) => {
48+
var r = Number(original(BigInt(x), BigInt(y)));
49+
return r;
50+
};
51+
} else if (name === 'main') {
52+
// Special case for main. Use `function` here rather than arrow
53+
// function to avoid implicit `strict`.
54+
replacement = function(x, y) {
55+
// Pass an extra 0 in case its a 3-argument form of main. Sadly we
56+
// can't just omit that argument like we can for wasm32 because the
57+
// missing third argument will generate:
58+
// `TypeError: Cannot convert undefined to a BigInt`.
59+
// See https://github.com/WebAssembly/JS-BigInt-integration/issues/12
60+
return original(x, BigInt(y ? y : 0), BigInt(0));
61+
};
62+
}
63+
instExports[name] = replacement;
64+
})(name);
65+
}
66+
return instExports;
67+
}

0 commit comments

Comments
 (0)