Skip to content

Commit 348f264

Browse files
authored
[wasm64] Add MAIN_THREAD_EM_ASM_PTR macro (#20261)
This compliments `MAIN_THREAD_EM_ASM_INT` in the same way that `EM_ASM_PTR` was added to compliment `EM_ASM_INT`. This is needed to fix the wasm64 SDL2 build. See libsdl-org/SDL#8241.
1 parent 783d0b8 commit 348f264

File tree

6 files changed

+85
-27
lines changed

6 files changed

+85
-27
lines changed

src/library.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2958,6 +2958,11 @@ addToLibrary({
29582958
return runMainThreadEmAsm(code, sigPtr, argbuf, 1);
29592959
},
29602960

2961+
emscripten_asm_const_ptr_sync_on_main_thread__deps: ['$runMainThreadEmAsm'],
2962+
emscripten_asm_const_ptr_sync_on_main_thread: (code, sigPtr, argbuf) => {
2963+
return runMainThreadEmAsm(code, sigPtr, argbuf, 1);
2964+
},
2965+
29612966
emscripten_asm_const_double_sync_on_main_thread: 'emscripten_asm_const_int_sync_on_main_thread',
29622967
emscripten_asm_const_async_on_main_thread__deps: ['$runMainThreadEmAsm'],
29632968
emscripten_asm_const_async_on_main_thread: (code, sigPtr, argbuf) => runMainThreadEmAsm(code, sigPtr, argbuf, 0),

src/library_sigs.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ sigs = {
565565
emscripten_asm_const_int__sig: 'ippp',
566566
emscripten_asm_const_int_sync_on_main_thread__sig: 'ippp',
567567
emscripten_asm_const_ptr__sig: 'pppp',
568+
emscripten_asm_const_ptr_sync_on_main_thread__sig: 'pppp',
568569
emscripten_async_call__sig: 'vppi',
569570
emscripten_async_load_script__sig: 'vppp',
570571
emscripten_async_run_script__sig: 'vpi',

system/include/emscripten/em_asm.h

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ extern "C" {
1111
#endif // __cplusplus
1212

1313
// You can use these functions by passing format string to arg_sigs.
14-
// Note that `code` requires you to provide a const C string known at compile time,
15-
// otherwise the "unable to find data for ASM/EM_JS const" error will be thrown.
14+
// Note that `code` requires you to provide a const C string known at compile
15+
// time, otherwise the "unable to find data for ASM/EM_JS const" error will be
16+
// thrown.
1617
// https://github.com/WebAssembly/binaryen/blob/51c8f2469f8fd05197b7694c65041b1567f2c6b5/src/wasm/wasm-emscripten.cpp#L183
1718

1819
// C++ needs the nothrow attribute so -O0 doesn't lower these calls as invokes.
@@ -27,6 +28,9 @@ __attribute__((nothrow))
2728
int emscripten_asm_const_int_sync_on_main_thread(
2829
const char* code, const char* arg_sigs, ...);
2930
__attribute__((nothrow))
31+
void* emscripten_asm_const_ptr_sync_on_main_thread(
32+
const char* code, const char* arg_sigs, ...);
33+
__attribute__((nothrow))
3034
double emscripten_asm_const_double_sync_on_main_thread(
3135
const char* code, const char* arg_sigs, ...);
3236

@@ -48,6 +52,7 @@ void emscripten_asm_const_async_on_main_thread(
4852
#define EM_ASM_DOUBLE(...) EM_ASM_ERROR
4953
#define MAIN_THREAD_EM_ASM(...) EM_ASM_ERROR
5054
#define MAIN_THREAD_EM_ASM_INT(...) EM_ASM_ERROR
55+
#define MAIN_THREAD_EM_ASM_PTR(...) EM_ASM_ERROR
5156
#define MAIN_THREAD_EM_ASM_DOUBLE(...) EM_ASM_ERROR
5257
#define MAIN_THREAD_ASYNC_EM_ASM(...) EM_ASM_ERROR
5358
#define EM_ASM_(...) EM_ASM_ERROR
@@ -201,52 +206,75 @@ const char __em_asm_sig_builder<__em_asm_type_tuple<Args...> >::buffer[] = { __e
201206
, __em_asm_sig_builder<__typeof__(__em_asm_make_type_tuple(__VA_ARGS__))>::buffer, ##__VA_ARGS__
202207
#endif // __cplusplus
203208

204-
// Note: If the code block in the EM_ASM() family of functions below contains a comma,
205-
// then wrap the whole code block inside parentheses (). See test/core/test_em_asm_2.cpp
206-
// for example code snippets.
209+
// Note: If the code block in the EM_ASM() family of functions below contains a
210+
// comma, then wrap the whole code block inside parentheses (). See
211+
// test/core/test_em_asm_2.cpp for example code snippets.
207212

208213
#define CODE_EXPR(code) (__extension__({ \
209214
__attribute__((section("em_asm"), aligned(1))) \
210215
static const char x[] = code; \
211216
x; \
212217
}))
213218

214-
// Runs the given JavaScript code on the calling thread (synchronously), and returns no value back.
219+
// Runs the given JavaScript code on the calling thread (synchronously), and
220+
// returns no value back.
215221
#define EM_ASM(code, ...) ((void)emscripten_asm_const_int(CODE_EXPR(#code) _EM_ASM_PREP_ARGS(__VA_ARGS__)))
216222

217-
// Runs the given JavaScript code on the calling thread (synchronously), and returns an i32 back.
223+
// Runs the given JavaScript code on the calling thread (synchronously), and
224+
// returns an i32 back.
218225
#define EM_ASM_INT(code, ...) emscripten_asm_const_int(CODE_EXPR(#code) _EM_ASM_PREP_ARGS(__VA_ARGS__))
219226

220-
// Runs the given JavaScript code on the calling thread (synchronously), and returns an pointer back.
221-
// On wasm32 this is the same as emscripten_asm_const_int but on wasm64 it returns an i64.
227+
// Runs the given JavaScript code on the calling thread (synchronously), and
228+
// returns an pointer back.
229+
// On wasm32 this is the same as emscripten_asm_const_int but on wasm64 it
230+
// returns an i64.
222231
#define EM_ASM_PTR(code, ...) emscripten_asm_const_ptr(CODE_EXPR(#code) _EM_ASM_PREP_ARGS(__VA_ARGS__))
223232

224-
// Runs the given JavaScript code on the calling thread (synchronously), and returns a double back.
233+
// Runs the given JavaScript code on the calling thread (synchronously), and
234+
// returns a double back.
225235
#define EM_ASM_DOUBLE(code, ...) emscripten_asm_const_double(CODE_EXPR(#code) _EM_ASM_PREP_ARGS(__VA_ARGS__))
226236

227-
// Runs the given JavaScript code synchronously on the main browser thread, and returns no value back.
228-
// Call this function for example to access DOM elements in a pthread when building with -pthread.
229-
// Avoid calling this function in performance sensitive code, because this will effectively sleep the
230-
// calling thread until the main browser thread is able to service the proxied function call. If you have
231-
// multiple MAIN_THREAD_EM_ASM() code blocks to call in succession, it will likely be much faster to
232-
// coalesce all the calls to a single MAIN_THREAD_EM_ASM() block. If you do not need synchronization nor
233-
// a return value back, consider using the function MAIN_THREAD_ASYNC_EM_ASM() instead, which will not block.
237+
// Runs the given JavaScript code synchronously on the main browser thread, and
238+
// returns no value back.
239+
// Call this function for example to access DOM elements in a pthread when
240+
// building with -pthread.
241+
// Avoid calling this function in performance sensitive code, because this will
242+
// effectively sleep the calling thread until the main browser thread is able to
243+
// service the proxied function call. If you have multiple MAIN_THREAD_EM_ASM()
244+
// code blocks to call in succession, it will likely be much faster to coalesce
245+
// all the calls to a single MAIN_THREAD_EM_ASM() block. If you do not need
246+
// synchronization nor a return value back, consider using the function
247+
// MAIN_THREAD_ASYNC_EM_ASM() instead, which will not block.
234248
// In single-threaded builds (including proxy-to-worker), MAIN_THREAD_EM_ASM*()
235-
// functions are direct aliases to the corresponding EM_ASM*() family of functions.
249+
// functions are direct aliases to the corresponding EM_ASM*() family of
250+
// functions.
236251
#define MAIN_THREAD_EM_ASM(code, ...) ((void)emscripten_asm_const_int_sync_on_main_thread(CODE_EXPR(#code) _EM_ASM_PREP_ARGS(__VA_ARGS__)))
237252

238-
// Runs the given JavaScript code synchronously on the main browser thread, and returns an integer back.
253+
// Runs the given JavaScript code synchronously on the main browser thread, and
254+
// returns an integer back.
239255
// The same considerations apply as with MAIN_THREAD_EM_ASM().
240256
#define MAIN_THREAD_EM_ASM_INT(code, ...) emscripten_asm_const_int_sync_on_main_thread(CODE_EXPR(#code) _EM_ASM_PREP_ARGS(__VA_ARGS__))
241257

242-
// Runs the given JavaScript code synchronously on the main browser thread, and returns a double back.
258+
// Runs the given JavaScript code synchronously on the main browser thread, and
259+
// returns an pointer back.
260+
// The same considerations apply as with MAIN_THREAD_EM_ASM().
261+
// On wasm32 this is the same as emscripten_asm_const_int but on wasm64 it
262+
// returns an i64.
263+
#define MAIN_THREAD_EM_ASM_PTR(code, ...) emscripten_asm_const_ptr_sync_on_main_thread(CODE_EXPR(#code) _EM_ASM_PREP_ARGS(__VA_ARGS__))
264+
265+
// Runs the given JavaScript code synchronously on the main browser thread, and
266+
// returns a double back.
243267
// The same considerations apply as with MAIN_THREAD_EM_ASM().
244268
#define MAIN_THREAD_EM_ASM_DOUBLE(code, ...) emscripten_asm_const_double_sync_on_main_thread(CODE_EXPR(#code) _EM_ASM_PREP_ARGS(__VA_ARGS__))
245269

246-
// Asynchronously dispatches the given JavaScript code to be run on the main browser thread.
247-
// If the calling thread is the main browser thread, then the specified JavaScript code is executed
248-
// synchronously. Otherwise an event will be queued on the main browser thread to execute the call
249-
// later (think postMessage()), and this call will immediately return without waiting. Be sure to guard any accesses to shared memory on the heap inside the JavaScript code with appropriate locking.
270+
// Asynchronously dispatches the given JavaScript code to be run on the main
271+
// browser thread.
272+
// If the calling thread is the main browser thread, then the specified
273+
// JavaScript code is executed synchronously. Otherwise an event will be queued
274+
// on the main browser thread to execute the call later (think postMessage()),
275+
// and this call will immediately return without waiting. Be sure to guard any
276+
// accesses to shared memory on the heap inside the JavaScript code with
277+
// appropriate locking.
250278
#define MAIN_THREAD_ASYNC_EM_ASM(code, ...) ((void)emscripten_asm_const_async_on_main_thread(CODE_EXPR(#code) _EM_ASM_PREP_ARGS(__VA_ARGS__)))
251279

252280
// Old forms for compatibility, no need to use these.

test/core/test_em_asm_2.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,15 @@ int main()
111111
// Note that expressions do not evaluate to return values, but the "return" keyword is needed. That is, the following line would return undefined and store i <- 0.
112112
// i = EM_ASM_INT(HEAP8.length); printf("returned statement %d\n", i);
113113

114+
void* p;
115+
116+
printf("\nEM_ASM_PTR: Return a pointer back.\n");
117+
p = EM_ASM_PTR(out('1. got arg ' + $0); return 3;, 42); printf("1. returned ptr %p\n", p);
118+
p = EM_ASM_PTR("out('2. got arg ' + $0); return 4;", 42); printf("2. returned ptr %p\n", p);
119+
p = EM_ASM_PTR({"out('3. got arg ' + $0); return 5;"}, 42); printf("3. returned ptr %p\n", p);
120+
p = EM_ASM_PTR({out('4. got arg ' + $0); return 6;}, 42); printf("4. returned ptr %p\n", p);
121+
p = EM_ASM_PTR("{out('5. got arg ' + $0); return 7;}", 42); printf("5. returned ptr %p\n", p);
122+
114123
double d;
115124

116125
printf("\nEM_ASM_DOUBLE: Pass no parameters, return a double.\n");

test/core/test_em_asm_2.out

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,18 @@ EM_ASM_INT: Return an integer in a single brief statement.
119119
4. returned statement 45
120120
5. returned statement 46
121121

122+
EM_ASM_PTR: Return a pointer back.
123+
1. got arg 42
124+
1. returned ptr 0x3
125+
2. got arg 42
126+
2. returned ptr 0x4
127+
3. got arg 42
128+
3. returned ptr 0x5
129+
4. got arg 42
130+
4. returned ptr 0x6
131+
5. got arg 42
132+
5. returned ptr 0x7
133+
122134
EM_ASM_DOUBLE: Pass no parameters, return a double.
123135
1. returning double
124136
1. got double 3.500000

test/test_core.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2196,9 +2196,12 @@ def test_em_asm_2(self):
21962196
self.emcc_args.append('-std=gnu89')
21972197
self.do_core_test('test_em_asm_2.cpp', force_c=True)
21982198

2199-
# Tests various different ways to invoke the MAIN_THREAD_EM_ASM(), MAIN_THREAD_EM_ASM_INT() and MAIN_THREAD_EM_ASM_DOUBLE() macros.
2200-
# This test is identical to test_em_asm_2, just search-replaces EM_ASM to MAIN_THREAD_EM_ASM on the test file. That way if new
2201-
# test cases are added to test_em_asm_2.cpp for EM_ASM, they will also get tested in MAIN_THREAD_EM_ASM form.
2199+
# Tests various different ways to invoke the MAIN_THREAD_EM_ASM(),
2200+
# MAIN_THREAD_EM_ASM_INT(), MAIN_THREAD_EM_ASM_PTR, and
2201+
# MAIN_THREAD_EM_ASM_DOUBLE() macros. This test is identical to
2202+
# test_em_asm_2, just search-replaces EM_ASM to MAIN_THREAD_EM_ASM on the test
2203+
# file. That way if new test cases are added to test_em_asm_2.cpp for EM_ASM,
2204+
# they will also get tested in MAIN_THREAD_EM_ASM form.
22022205
def test_main_thread_em_asm(self):
22032206
src = read_file(test_file('core/test_em_asm_2.cpp'))
22042207
create_file('src.cpp', src.replace('EM_ASM', 'MAIN_THREAD_EM_ASM'))

0 commit comments

Comments
 (0)