Skip to content

Commit bbce5d7

Browse files
authored
Allow character substitution of wasm symbol names (#13477)
* Allow character substitution of wasm symbol names to avoid working around complex string escaping issues in operating system shells and build systems. * Fix doc. * Fix doc. * Add ChangeLog entry * Fix test_asyncify_tricky_function_sig
1 parent 2dcfec9 commit bbce5d7

File tree

5 files changed

+74
-0
lines changed

5 files changed

+74
-0
lines changed

ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ Current Trunk
4747
of ccache via emsdk, or from https://github.com/juj/ccache/tree/emscripten,
4848
and run explicitly with "ccache emcc ..." after installing, or automatically
4949
just with "emcc ..." after activating ccache via emsdk (#13498).
50+
- Added support to use a custom set of substitution characters . # and ? to
51+
ease passing arrays of C symbols on the command line to ASYNCIFY_* settings.
52+
(#13477)
5053
- Using EM_ASM and EM_JS in a side module will now result in an error (since
5154
this is not implemented yet). This could effect users were previously
5255
inadvertently including (but not actually using) EM_ASM or EM_JS functions in

emcc.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,15 @@ def is_dash_s_for_emcc(args, i):
627627
return arg.isidentifier() and arg.isupper()
628628

629629

630+
def unmangle_symbols_from_cmdline(symbols):
631+
def unmangle(x):
632+
return x.replace('.', ' ').replace('#', '&').replace('?', ',')
633+
634+
if type(symbols) is list:
635+
return [unmangle(x) for x in symbols]
636+
return unmangle(symbols)
637+
638+
630639
def parse_s_args(args):
631640
settings_changes = []
632641
for i in range(len(args)):
@@ -1459,6 +1468,10 @@ def default_setting(name, new_default):
14591468
'_emscripten_stack_get_end',
14601469
'_emscripten_stack_set_limits']
14611470

1471+
shared.Settings.ASYNCIFY_ADD = unmangle_symbols_from_cmdline(shared.Settings.ASYNCIFY_ADD)
1472+
shared.Settings.ASYNCIFY_REMOVE = unmangle_symbols_from_cmdline(shared.Settings.ASYNCIFY_REMOVE)
1473+
shared.Settings.ASYNCIFY_ONLY = unmangle_symbols_from_cmdline(shared.Settings.ASYNCIFY_ONLY)
1474+
14621475
# SSEx is implemented on top of SIMD128 instruction set, but do not pass SSE flags to LLVM
14631476
# so it won't think about generating native x86 SSE code.
14641477
newargs = [x for x in newargs if x not in SIMD_INTEL_FEATURE_TOWER and x not in SIMD_NEON_FLAGS]

src/settings.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,7 @@ var ASYNCIFY_STACK_SIZE = 4096;
719719
// to know you got this right), so this is not recommended unless you
720720
// really know what are doing, and need to optimize every bit of speed
721721
// and size.
722+
//
722723
// The names in this list are names from the WebAssembly Names section. The
723724
// wasm backend will emit those names in *human-readable* form instead of
724725
// typical C++ mangling. For example, you should write Struct::func()
@@ -730,7 +731,23 @@ var ASYNCIFY_STACK_SIZE = 4096;
730731
// changes which would mean a single list couldn't work for both -O0 and -O1
731732
// builds, etc.). You can inspect the wasm binary to look for the actual names,
732733
// either directly or using wasm-objdump or wasm-dis, etc.
734+
//
733735
// Simple '*' wildcard matching is supported.
736+
//
737+
// To avoid dealing with limitations in operating system shells or build system
738+
// escaping, the following substitutions can be made:
739+
// - ' ' -> '.',
740+
// - '&' -> '#',
741+
// - ',' -> '?'.
742+
//
743+
// That is, the function
744+
// "foo(char const*, int&)" can be inputted as
745+
// "foo(char.const*?.int#)" on the command line instead.
746+
//
747+
// Note: Whitespace is part of the function signature! I.e.
748+
// "foo(char const *, int &)" will not match "foo(char const*, int&)", and
749+
// neither would "foo(const char*, int &)".
750+
//
734751
// [link]
735752
var ASYNCIFY_REMOVE = [];
736753

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <stdio.h>
2+
#include <emscripten.h>
3+
4+
volatile int x;
5+
6+
int bar() { return 1; }
7+
8+
__attribute__((noinline))
9+
int foo(const char *str, int &i)
10+
{
11+
if (x == 1337) return bar(); // don't inline me
12+
printf("foo %s\n", str);
13+
emscripten_sleep(1);
14+
printf("foo %d\n", i);
15+
return 42;
16+
}
17+
18+
__attribute__((noinline))
19+
int foo2()
20+
{
21+
if (x == 1337) return bar(); // don't inline me
22+
printf("foo2 1\n");
23+
emscripten_sleep(1);
24+
printf("foo2 2\n");
25+
return 43;
26+
}
27+
28+
int main()
29+
{
30+
printf("main 1\n");
31+
int j = 42;
32+
const char *str = "hello";
33+
int ret = foo(str, j);
34+
printf("main %d\n", ret);
35+
int ret2 = foo2();
36+
printf("ret2 %d\n", ret2);
37+
REPORT_RESULT(ret + ret2);
38+
}

tests/test_browser.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3210,6 +3210,9 @@ def test_async(self):
32103210
print(opts)
32113211
self.btest('browser/async.cpp', '1', args=['-O' + str(opts), '-g2', '-s', 'ASYNCIFY'])
32123212

3213+
def test_asyncify_tricky_function_sig(self):
3214+
self.btest('browser/test_asyncify_tricky_function_sig.cpp', '85', args=['-s', 'ASYNCIFY_ONLY=[foo(char.const*?.int#),foo2(),main,__original_main]', '-s', 'ASYNCIFY=1'])
3215+
32133216
@requires_threads
32143217
def test_async_in_pthread(self):
32153218
self.btest('browser/async.cpp', '1', args=['-s', 'ASYNCIFY', '-s', 'USE_PTHREADS', '-s', 'PROXY_TO_PTHREAD', '-g'])

0 commit comments

Comments
 (0)