Skip to content

Commit 48a1620

Browse files
jujkripken
andauthored
Fix Closure compile of small builds that use legacy DYNCALLS mode (#13883)
* Fix Closure compile of small builds that use legacy DYNCALLS mode but do not export any wasm function with signature 'v' or 'vi'. * Address review * Update tests/test_other.py * Address review * Remove duplicate hasExportedFunction * Use hasExportedFunction() * Generalize closure optimization to makeDynCall macro * Clean up Closure warnings Co-authored-by: Alon Zakai <[email protected]>
1 parent a2d0b4e commit 48a1620

File tree

3 files changed

+31
-0
lines changed

3 files changed

+31
-0
lines changed

src/library.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3276,8 +3276,13 @@ LibraryManager.library = {
32763276
var func = callback.func;
32773277
if (typeof func == 'number') {
32783278
if (callback.arg === undefined) {
3279+
// Run the wasm function ptr with signature 'v'. If no function
3280+
// with such signature was exported, this call does not need
3281+
// to be emitted (and would confuse Closure)
32793282
{{{ makeDynCall('v', 'func') }}}();
32803283
} else {
3284+
// If any function with signature 'vi' was exported, run
3285+
// the callback with that signature.
32813286
{{{ makeDynCall('vi', 'func') }}}(callback.arg);
32823287
}
32833288
} else {

src/parseTools.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,13 +832,28 @@ New syntax is {{{ makeDynCall("${sig}", "funcPtr") }}}(arg1, arg2, ...). \
832832
Please update to new syntax.`);
833833

834834
if (DYNCALLS) {
835+
if (!hasExportedFunction(`dynCall_${sig}`)) {
836+
if (ASSERTIONS) {
837+
return `(function(${args}) { throw 'Internal Error! Attempted to invoke wasm function pointer with signature "${sig}", but no such functions have gotten exported!'; })`;
838+
} else {
839+
return `(function(${args}) { /* a dynamic function call to signature ${sig}, but there are no exported function pointers with that signature, so this path should never be taken. Build with ASSERTIONS enabled to validate. */ })`;
840+
}
841+
}
835842
return `(function(cb, ${args}) { ${returnExpr} getDynCaller("${sig}", cb)(${args}) })`;
836843
} else {
837844
return `(function(cb, ${args}) { ${returnExpr} getWasmTableEntry(cb)(${args}) })`;
838845
}
839846
}
840847

841848
if (DYNCALLS) {
849+
if (!hasExportedFunction(`dynCall_${sig}`)) {
850+
if (ASSERTIONS) {
851+
return `(function(${args}) { throw 'Internal Error! Attempted to invoke wasm function pointer with signature "${sig}", but no such functions have gotten exported!'; })`;
852+
} else {
853+
return `(function(${args}) { /* a dynamic function call to signature ${sig}, but there are no exported function pointers with that signature, so this path should never be taken. Build with ASSERTIONS enabled to validate. */ })`;
854+
}
855+
}
856+
842857
const dyncall = exportedAsmFunc(`dynCall_${sig}`);
843858
if (sig.length > 1) {
844859
return `(function(${args}) { ${returnExpr} ${dyncall}.apply(null, [${funcPtr}, ${args}]); })`;
@@ -1058,6 +1073,9 @@ function _asmjsDemangle(symbol) {
10581073
if (symbol in WASM_SYSTEM_EXPORTS) {
10591074
return symbol;
10601075
}
1076+
if (symbol.startsWith('dynCall_')) {
1077+
return symbol;
1078+
}
10611079
// Strip leading "_"
10621080
assert(symbol.startsWith('_'));
10631081
return symbol.substr(1);

tests/test_other.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10815,6 +10815,14 @@ def test_old_makeDynCall_syntax(self):
1081510815
err = self.run_process([EMCC, test_file('test_old_dyncall_format.c'), '--js-library', test_file('library_test_old_dyncall_format.js')], stderr=PIPE).stderr
1081610816
self.assertContained('syntax for makeDynCall has changed', err)
1081710817

10818+
# Tests that dynCalls are produced in Closure-safe way in DYNCALLS mode when no actual dynCalls are used
10819+
@parameterized({
10820+
'plain': [[]],
10821+
'asyncify': [['-sASYNCIFY']],
10822+
'asyncify_bigint': [['-sASYNCIFY', '-sWASM_BIGINT']]})
10823+
def test_closure_safe(self, args):
10824+
self.run_process([EMCC, test_file('hello_world.c'), '--closure=1'] + args)
10825+
1081810826
def test_post_link(self):
1081910827
err = self.run_process([EMCC, test_file('hello_world.c'), '--oformat=bare', '-o', 'bare.wasm'], stderr=PIPE).stderr
1082010828
self.assertContained('--oformat=bare/--post-link are experimental and subject to change', err)

0 commit comments

Comments
 (0)