From 91215057ea1713f26896c47e2cffe09a99a6170a Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 27 Jun 2022 17:28:14 -0700 Subject: [PATCH 01/18] Fill in dynCall_sig with a custom Wasm module if it is missing --- src/library.js | 155 ++++++++++++++++++++++++++++++++++++++- src/runtime_functions.js | 51 +++++++------ 2 files changed, 180 insertions(+), 26 deletions(-) diff --git a/src/library.js b/src/library.js index fa7a0422e920f..36c6985e92820 100644 --- a/src/library.js +++ b/src/library.js @@ -3188,8 +3188,6 @@ mergeInto(LibraryManager.library, { #if MINIMAL_RUNTIME assert(typeof dynCalls != 'undefined', 'Global dynCalls dictionary was not generated in the build! Pass -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$dynCall linker flag to include it!'); assert(sig in dynCalls, 'bad function pointer type - no table for sig \'' + sig + '\''); -#else - assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\''); #endif if (args && args.length) { // j (64-bit integer) must be passed in as two numbers [low 32, high 32]. @@ -3201,11 +3199,164 @@ mergeInto(LibraryManager.library, { #if MINIMAL_RUNTIME var f = dynCalls[sig]; #else + if (!('dynCall_' + sig in Module)) { + Module['dynCall_' + sig] = createDyncallWrapper(sig); + } var f = Module['dynCall_' + sig]; #endif return args && args.length ? f.apply(null, [ptr].concat(args)) : f.call(null, ptr); }, +#if MINIMAL_RUNTIME $dynCall__deps: ['$dynCallLegacy', '$getWasmTableEntry'], +#else + $dynCall__deps: ['$dynCallLegacy', '$getWasmTableEntry', '$createDyncallWrapper'], +#endif +#endif +#if DYNCALLS || !WASM_BIGINT + $createDyncallWrapper: function(sig) { + var sections = []; + var prelude = [ + 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm") + 0x01, 0x00, 0x00, 0x00, // version: 1 + ]; + sections.push(prelude); + var insig = [sig[0] === "j" ? "i" : sig[0], "i",]; + for (var i = 1; i < sig.length; i++) { + var cur = sig[i]; + if (cur === "j") { + insig.push("ii") + } else { + insig.push(cur); + } + } + insig = insig.join(""); + + // The module is static, with the exception of the type section, which is + // generated based on the signature passed in. + var typeSection = [ + 0x03, // count: 3 + ].concat(generate_func_type(insig), generate_func_type(sig), generate_func_type("vi")); + + // Write the section code and overall length of the type section into the + // section header + typeSection = [0x01 /* Type section code */].concat( + uleb128Encode(typeSection.length), + typeSection + ); + sections.push(typeSection); + + var importSection = [ + 0x02, // import section + 0x0F, // byte length + 0x02, // 2 imports + 0x01, 0x65, // name "e" + 0x01, 0x74, // name "t" + 0x01, 0x70, // importing a table + 0x00, // with no max # of elements + 0x00, // and min of 0 elements + 0x01, 0x65, // name "e" + 0x01, 0x72, // name "r" + 0x00, // importing a function + 0x02, // type 2 + ]; + sections.push(importSection); + + var functionSection = [ + 0x03, // function section + 0x02, // length in bytes + 0x01, // number of functions + 0x00, // type 0 + ]; + sections.push(functionSection); + + var exportSection = [ + 0x07, 0x05, // export section + 0x01, // One export + 0x01, 0x66, // name "f" + 0x00, // type: function + 0x01, // the wrapper function (index 0 is ret0) + ]; + sections.push(exportSection); + + var convert_code = []; + if (sig[0] === "j") { + convert_code = [0x01, 0x01, 0x7e]; + } else { + convert_code.push(0x00); // no additional local variables + } + + var j = 1; + for (var i = 1; i < sig.length; i++) { + if (sig[i] == "j") { + convert_code = convert_code.concat( + [0x20], // local.get + uleb128Encode(j + 1), + [ + 0xad, // i64.extend_i32_unsigned + 0x42, // i64.const + 0x20, // 32 + 0x86, // i64.shl, + 0x20, // local.get + ], + uleb128Encode(j), + [ + 0xac, // i64.extend_i32_signed + 0x84, // i64.or + ] + ); + j+=2; + } else { + convert_code.push(0x20); // local.get + convert_code = convert_code.concat(uleb128Encode(j)); + j++; + } + } + + convert_code = convert_code.concat([ + 0x20, 0x00, // local.get 0 (put function pointer on stack) + 0x11, 0x01, 0x00, // call_indirect 1 0 + ]); + + if (sig[0] === "j") { + convert_code = convert_code.concat([ + 0x22, // tee + ...uleb128Encode(j), + 0x42, 0x20, // i64.const 32 + 0x88, // i64.shr_u + 0xa7, // i32.wrap_i64 + 0x10, 0x00, // Call function 0 + 0x20, ...uleb128Encode(j), // local.get + 0xa7, // i32.wrap_i64 + ]); + } + convert_code.push(0x0b); // end + + var codeSection = [].concat( + [0x01], // one code + uleb128Encode(convert_code.length), + convert_code, + ); + codeSection = [0x0A /* Code section code */].concat( + uleb128Encode(codeSection.length), + codeSection + ); + sections.push(codeSection); + + var bytes = new Uint8Array([].concat.apply([], sections)); + const fs = require("fs") + fs.writeFileSync("blah.wasm", bytes); + + // We can compile this wasm module synchronously because it is small. + var module = new WebAssembly.Module(bytes); + var instance = new WebAssembly.Instance(module, { + 'e': { + 't': wasmTable, + 'r': setTempRet0, + } + }); + var wrappedFunc = instance.exports['f']; + return wrappedFunc; + }, #endif // Used in library code to get JS function from wasm function pointer. diff --git a/src/runtime_functions.js b/src/runtime_functions.js index 91b5b5e5760aa..ad4ffc287b43f 100644 --- a/src/runtime_functions.js +++ b/src/runtime_functions.js @@ -43,26 +43,7 @@ function sigToWasmTypes(sig) { return type; } -// Wraps a JS function as a wasm function with a given signature. -function convertJsFunctionToWasm(func, sig) { -#if WASM2JS - return func; -#else // WASM2JS - - // If the type reflection proposal is available, use the new - // "WebAssembly.Function" constructor. - // Otherwise, construct a minimal wasm module importing the JS function and - // re-exporting it. - if (typeof WebAssembly.Function == "function") { - return new WebAssembly.Function(sigToWasmTypes(sig), func); - } - - // The module is static, with the exception of the type section, which is - // generated based on the signature passed in. - var typeSection = [ - 0x01, // count: 1 - 0x60, // form: func - ]; +function generate_func_type(sig){ var sigRet = sig.slice(0, 1); var sigParam = sig.slice(1); var typeCodes = { @@ -78,22 +59,44 @@ function convertJsFunctionToWasm(func, sig) { }; // Parameters, length + signatures - typeSection = typeSection.concat(uleb128Encode(sigParam.length)); + var result = [ 0x60, /* form: func */]; + result = result.concat(uleb128Encode(sigParam.length)); for (var i = 0; i < sigParam.length; ++i) { #if ASSERTIONS assert(sigParam[i] in typeCodes, 'invalid signature char: ' + sigParam[i]); #endif - typeSection.push(typeCodes[sigParam[i]]); + result.push(typeCodes[sigParam[i]]); } // Return values, length + signatures // With no multi-return in MVP, either 0 (void) or 1 (anything else) if (sigRet == 'v') { - typeSection.push(0x00); + result.push(0x00); } else { - typeSection = typeSection.concat([0x01, typeCodes[sigRet]]); + result = result.concat([0x01, typeCodes[sigRet]]); } + return result; +} +// Wraps a JS function as a wasm function with a given signature. +function convertJsFunctionToWasm(func, sig) { +#if WASM2JS + return func; +#else // WASM2JS + + // If the type reflection proposal is available, use the new + // "WebAssembly.Function" constructor. + // Otherwise, construct a minimal wasm module importing the JS function and + // re-exporting it. + if (typeof WebAssembly.Function == "function") { + return new WebAssembly.Function(sigToWasmTypes(sig), func); + } + + // The module is static, with the exception of the type section, which is + // generated based on the signature passed in. + var typeSection = [ + 0x01, // count: 1 + ].concat(generate_func_type(sig)); // Write the section code and overall length of the type section into the // section header typeSection = [0x01 /* Type section code */].concat( From 380052c9b7f99131e8ba3c5d9d33ec4f4c1a990b Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 29 Jun 2022 07:01:06 -0700 Subject: [PATCH 02/18] generate_func_type ==> generateFuncType --- src/library.js | 2 +- src/runtime_functions.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/library.js b/src/library.js index 36c6985e92820..153839fab4b04 100644 --- a/src/library.js +++ b/src/library.js @@ -3235,7 +3235,7 @@ mergeInto(LibraryManager.library, { // generated based on the signature passed in. var typeSection = [ 0x03, // count: 3 - ].concat(generate_func_type(insig), generate_func_type(sig), generate_func_type("vi")); + ].concat(generateFuncType(insig), generateFuncType(sig), generateFuncType("vi")); // Write the section code and overall length of the type section into the // section header diff --git a/src/runtime_functions.js b/src/runtime_functions.js index ad4ffc287b43f..e818022fa5573 100644 --- a/src/runtime_functions.js +++ b/src/runtime_functions.js @@ -43,7 +43,7 @@ function sigToWasmTypes(sig) { return type; } -function generate_func_type(sig){ +function generateFuncType(sig){ var sigRet = sig.slice(0, 1); var sigParam = sig.slice(1); var typeCodes = { @@ -96,7 +96,7 @@ function convertJsFunctionToWasm(func, sig) { // generated based on the signature passed in. var typeSection = [ 0x01, // count: 1 - ].concat(generate_func_type(sig)); + ].concat(generateFuncType(sig)); // Write the section code and overall length of the type section into the // section header typeSection = [0x01 /* Type section code */].concat( From b678b9401e0b004505cd6db2199f1382aa22b30d Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 29 Jun 2022 07:04:58 -0700 Subject: [PATCH 03/18] Update #ifdef guards --- src/library.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/library.js b/src/library.js index 153839fab4b04..a9b95c73c4597 100644 --- a/src/library.js +++ b/src/library.js @@ -3199,20 +3199,18 @@ mergeInto(LibraryManager.library, { #if MINIMAL_RUNTIME var f = dynCalls[sig]; #else + #if MAIN_MODULE == 1 if (!('dynCall_' + sig in Module)) { Module['dynCall_' + sig] = createDyncallWrapper(sig); } + #endif var f = Module['dynCall_' + sig]; #endif return args && args.length ? f.apply(null, [ptr].concat(args)) : f.call(null, ptr); }, -#if MINIMAL_RUNTIME $dynCall__deps: ['$dynCallLegacy', '$getWasmTableEntry'], -#else - $dynCall__deps: ['$dynCallLegacy', '$getWasmTableEntry', '$createDyncallWrapper'], -#endif -#endif -#if DYNCALLS || !WASM_BIGINT +#if MAIN_MODULE == 1 + $dynCallLegacy__deps: ['$createDyncallWrapper'], $createDyncallWrapper: function(sig) { var sections = []; var prelude = [ @@ -3357,6 +3355,7 @@ mergeInto(LibraryManager.library, { var wrappedFunc = instance.exports['f']; return wrappedFunc; }, +#endif #endif // Used in library code to get JS function from wasm function pointer. From 99b057d1213683a38f49a08dac64b8d5308e7c12 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 29 Jun 2022 07:28:38 -0700 Subject: [PATCH 04/18] Remove debug statement, add more comments --- src/library.js | 84 +++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/src/library.js b/src/library.js index a9b95c73c4597..68f904ab2af77 100644 --- a/src/library.js +++ b/src/library.js @@ -3218,40 +3218,40 @@ mergeInto(LibraryManager.library, { 0x01, 0x00, 0x00, 0x00, // version: 1 ]; sections.push(prelude); - var insig = [sig[0] === "j" ? "i" : sig[0], "i",]; - for (var i = 1; i < sig.length; i++) { - var cur = sig[i]; - if (cur === "j") { - insig.push("ii") - } else { - insig.push(cur); - } - } - insig = insig.join(""); + var wrappersig = [ + // if return type is j, we will put the upper 32 bits into tempRet0. + sig[0].replace("j", "i"), + "i", // The first argument is the function pointer to call + // in the rest of the argument list, one 64 bit integer is legalized into + // two 32 bit integers. + sig.slice(1).replace("j", "ii"), + ].join(""); - // The module is static, with the exception of the type section, which is - // generated based on the signature passed in. var typeSection = [ - 0x03, // count: 3 - ].concat(generateFuncType(insig), generateFuncType(sig), generateFuncType("vi")); + 0x03, // number of types = 3 + ].concat( + generateFuncType(wrappersig), // The signature of the wrapper we are generating + generateFuncType(sig), // the signature of the function pointer we will call + generateFuncType("vi"), // the signature of setTempRet0 + ); - // Write the section code and overall length of the type section into the - // section header typeSection = [0x01 /* Type section code */].concat( - uleb128Encode(typeSection.length), + uleb128Encode(typeSection.length), // length of section in bytes typeSection ); sections.push(typeSection); var importSection = [ - 0x02, // import section - 0x0F, // byte length - 0x02, // 2 imports + 0x02, // import section code + 0x0F, // length of section in bytes + 0x02, // number of imports = 2 + // Import the wasmTable, which we will call "t" 0x01, 0x65, // name "e" 0x01, 0x74, // name "t" 0x01, 0x70, // importing a table 0x00, // with no max # of elements 0x00, // and min of 0 elements + // Import the setTempRet0 function, which we will call "r" 0x01, 0x65, // name "e" 0x01, 0x72, // name "r" 0x00, // importing a function @@ -3260,41 +3260,47 @@ mergeInto(LibraryManager.library, { sections.push(importSection); var functionSection = [ - 0x03, // function section - 0x02, // length in bytes - 0x01, // number of functions - 0x00, // type 0 + 0x03, // function section code + 0x02, // length of section in bytes + 0x01, // number of functions = 1 + 0x00, // type 0 = wrappersig ]; sections.push(functionSection); var exportSection = [ - 0x07, 0x05, // export section + 0x07, // export section code + 0x05, // length of section in bytes 0x01, // One export 0x01, 0x66, // name "f" 0x00, // type: function - 0x01, // the wrapper function (index 0 is ret0) + 0x01, // function index 1 = the wrapper function (index 0 is setTempRet0) ]; sections.push(exportSection); var convert_code = []; if (sig[0] === "j") { - convert_code = [0x01, 0x01, 0x7e]; + // Add a single extra i64 local. In order to legalize the return value we + // need a local to store it in. Local variables are run length encoded. + convert_code = [ + 0x01, // One run + 0x01, // of length 1 + 0x7e, // of i64 + ]; } else { - convert_code.push(0x00); // no additional local variables + convert_code.push(0x00); // no local variables (except the arguments) } var j = 1; for (var i = 1; i < sig.length; i++) { if (sig[i] == "j") { convert_code = convert_code.concat( - [0x20], // local.get + [0x20], // local.get j + 1 uleb128Encode(j + 1), [ 0xad, // i64.extend_i32_unsigned - 0x42, // i64.const - 0x20, // 32 + 0x42, 0x20, // i64.const 32 0x86, // i64.shl, - 0x20, // local.get + 0x20, // local.get j ], uleb128Encode(j), [ @@ -3304,7 +3310,7 @@ mergeInto(LibraryManager.library, { ); j+=2; } else { - convert_code.push(0x20); // local.get + convert_code.push(0x20); // local.get j convert_code = convert_code.concat(uleb128Encode(j)); j++; } @@ -3312,18 +3318,20 @@ mergeInto(LibraryManager.library, { convert_code = convert_code.concat([ 0x20, 0x00, // local.get 0 (put function pointer on stack) - 0x11, 0x01, 0x00, // call_indirect 1 0 + 0x11, 0x01, 0x00, // call_indirect type 1 = wrapped_sig, table 0 = only table ]); if (sig[0] === "j") { convert_code = convert_code.concat([ - 0x22, // tee + // tee into j (after the argument handling loop, j is one past the + // argument list so it points to the i64 local we added) + 0x22, ...uleb128Encode(j), - 0x42, 0x20, // i64.const 32 + 0x42, 0x20, // i64.const 32 0x88, // i64.shr_u 0xa7, // i32.wrap_i64 0x10, 0x00, // Call function 0 - 0x20, ...uleb128Encode(j), // local.get + 0x20, ...uleb128Encode(j), // local.get j 0xa7, // i32.wrap_i64 ]); } @@ -3341,8 +3349,6 @@ mergeInto(LibraryManager.library, { sections.push(codeSection); var bytes = new Uint8Array([].concat.apply([], sections)); - const fs = require("fs") - fs.writeFileSync("blah.wasm", bytes); // We can compile this wasm module synchronously because it is small. var module = new WebAssembly.Module(bytes); From 905e4c555b6e499c33a92346a0fd060257ee5dc0 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 15 Jul 2022 07:53:02 +0300 Subject: [PATCH 05/18] Fix createDyncallWrapper --- src/library.js | 69 +++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/library.js b/src/library.js index 46fb573916260..1a1449c0ff108 100644 --- a/src/library.js +++ b/src/library.js @@ -3235,6 +3235,7 @@ mergeInto(LibraryManager.library, { $dynCall__deps: ['$dynCallLegacy', '$getWasmTableEntry'], #if MAIN_MODULE == 1 $dynCallLegacy__deps: ['$createDyncallWrapper'], + $createDyncallWrapper__deps: ['$generateFuncType', '$uleb128Encode'], $createDyncallWrapper: function(sig) { var sections = []; var prelude = [ @@ -3251,18 +3252,16 @@ mergeInto(LibraryManager.library, { sig.slice(1).replace("j", "ii"), ].join(""); - var typeSection = [ + var typeSectionBody = [ 0x03, // number of types = 3 - ].concat( - generateFuncType(wrappersig), // The signature of the wrapper we are generating - generateFuncType(sig), // the signature of the function pointer we will call - generateFuncType("vi"), // the signature of setTempRet0 - ); + ]; + generateFuncType(wrappersig, typeSectionBody); // The signature of the wrapper we are generating + generateFuncType(sig, typeSectionBody); // the signature of the function pointer we will call + generateFuncType("vi", typeSectionBody); // the signature of setTempRet0 - typeSection = [0x01 /* Type section code */].concat( - uleb128Encode(typeSection.length), // length of section in bytes - typeSection - ); + typeSection = [0x01 /* Type section code */]; + uleb128Encode(typeSection.length, typeSection); // length of section in bytes + typeSection.push.apply(typeSection, typeSectionBody); sections.push(typeSection); var importSection = [ @@ -3317,59 +3316,61 @@ mergeInto(LibraryManager.library, { var j = 1; for (var i = 1; i < sig.length; i++) { if (sig[i] == "j") { - convert_code = convert_code.concat( - [0x20], // local.get j + 1 - uleb128Encode(j + 1), - [ + convert_code.push( + 0x20 // local.get j + 1 + ); + uleb128Encode(j + 1, convert_code); + convert_code.push( 0xad, // i64.extend_i32_unsigned 0x42, 0x20, // i64.const 32 0x86, // i64.shl, 0x20, // local.get j - ], - uleb128Encode(j), - [ + ) + uleb128Encode(j, convert_code); + convert_code.push( 0xac, // i64.extend_i32_signed 0x84, // i64.or - ] ); j+=2; } else { convert_code.push(0x20); // local.get j - convert_code = convert_code.concat(uleb128Encode(j)); + uleb128Encode(j, convert_code); j++; } } - convert_code = convert_code.concat([ + convert_code.push( 0x20, 0x00, // local.get 0 (put function pointer on stack) 0x11, 0x01, 0x00, // call_indirect type 1 = wrapped_sig, table 0 = only table - ]); + ); if (sig[0] === "j") { - convert_code = convert_code.concat([ + convert_code.push( // tee into j (after the argument handling loop, j is one past the // argument list so it points to the i64 local we added) 0x22, - ...uleb128Encode(j), + ) + uleb128Encode(j, convert_code); + convert_code.push( 0x42, 0x20, // i64.const 32 0x88, // i64.shr_u 0xa7, // i32.wrap_i64 0x10, 0x00, // Call function 0 - 0x20, ...uleb128Encode(j), // local.get j + 0x20 + ); + uleb128Encode(j, convert_code); // local.get j + convert_code.push( 0xa7, // i32.wrap_i64 - ]); + ); } convert_code.push(0x0b); // end - var codeSection = [].concat( - [0x01], // one code - uleb128Encode(convert_code.length), - convert_code, - ); - codeSection = [0x0A /* Code section code */].concat( - uleb128Encode(codeSection.length), - codeSection - ); + var codeBody = [0x01]; // one code + uleb128Encode(convert_code.length, codeBody); + codeBody.push.apply(codeBody, convert_code); + var codeSection = [0x0A /* Code section code */]; + uleb128Encode(codeBody.length, codeSection); + codeSection.push.apply(codeSection, codeBody); sections.push(codeSection); var bytes = new Uint8Array([].concat.apply([], sections)); From e1e0e0a64cd0f28771f59bdb2ce6e9127f28c169 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 22 Jul 2022 21:03:04 +0100 Subject: [PATCH 06/18] Make localGet function --- src/library.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/library.js b/src/library.js index 1a1449c0ff108..043d41cdbfa82 100644 --- a/src/library.js +++ b/src/library.js @@ -3313,28 +3313,28 @@ mergeInto(LibraryManager.library, { convert_code.push(0x00); // no local variables (except the arguments) } + function localGet(j){ + convert_code.push(0x20); // local.get + uleb128Encode(j, convert_code); + } + var j = 1; for (var i = 1; i < sig.length; i++) { if (sig[i] == "j") { - convert_code.push( - 0x20 // local.get j + 1 - ); - uleb128Encode(j + 1, convert_code); + localGet(j + 1); convert_code.push( 0xad, // i64.extend_i32_unsigned 0x42, 0x20, // i64.const 32 0x86, // i64.shl, - 0x20, // local.get j ) - uleb128Encode(j, convert_code); + localGet(j); convert_code.push( 0xac, // i64.extend_i32_signed 0x84, // i64.or ); j+=2; } else { - convert_code.push(0x20); // local.get j - uleb128Encode(j, convert_code); + localGet(j); j++; } } @@ -3356,9 +3356,8 @@ mergeInto(LibraryManager.library, { 0x88, // i64.shr_u 0xa7, // i32.wrap_i64 0x10, 0x00, // Call function 0 - 0x20 ); - uleb128Encode(j, convert_code); // local.get j + localGet(j); convert_code.push( 0xa7, // i32.wrap_i64 ); From 2a2bb84a2c730b0bd8db2369bca8b131c66f91df Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 22 Jul 2022 21:37:32 +0100 Subject: [PATCH 07/18] Address some review comments --- src/library_addfunction.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/library_addfunction.js b/src/library_addfunction.js index 73279578b54fb..4e1e48781c5cc 100644 --- a/src/library_addfunction.js +++ b/src/library_addfunction.js @@ -50,11 +50,11 @@ mergeInto(LibraryManager.library, { var sigParam = sig.slice(1); var typeCodes = { 'i': 0x7f, // i32 - #if MEMORY64 +#if MEMORY64 'p': 0x7e, // i64 - #else +#else 'p': 0x7f, // i32 - #endif +#endif 'j': 0x7e, // i64 'f': 0x7d, // f32 'd': 0x7c, // f64 @@ -64,9 +64,9 @@ mergeInto(LibraryManager.library, { target.push(0x60 /* form: func */); uleb128Encode(sigParam.length, target); for (var i = 0; i < sigParam.length; ++i) { - #if ASSERTIONS +#if ASSERTIONS assert(sigParam[i] in typeCodes, 'invalid signature char: ' + sigParam[i]); - #endif +#endif target.push(typeCodes[sigParam[i]]); } @@ -75,7 +75,7 @@ mergeInto(LibraryManager.library, { if (sigRet == 'v') { target.push(0x00); } else { - target = target.concat([0x01, typeCodes[sigRet]]); + target.push(0x01, typeCodes[sigRet]); } }, // Wraps a JS function as a wasm function with a given signature. From ab67a527084592e77398046066d0331553dc8fc2 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 22 Jul 2022 21:47:43 +0100 Subject: [PATCH 08/18] Move createDyncallWrapper into separate file --- src/library.js | 157 +------------------------------------ src/library_makeDynCall | 0 src/library_makeDynCall.js | 154 ++++++++++++++++++++++++++++++++++++ src/modules.js | 1 + 4 files changed, 159 insertions(+), 153 deletions(-) create mode 100644 src/library_makeDynCall create mode 100644 src/library_makeDynCall.js diff --git a/src/library.js b/src/library.js index f2e2123614c14..826258245191e 100644 --- a/src/library.js +++ b/src/library.js @@ -3208,6 +3208,10 @@ mergeInto(LibraryManager.library, { }, #if DYNCALLS || !WASM_BIGINT +#if MAIN_MODULE == 1 + // createDyncallWrapper is defined in library_makeDynCall + $dynCallLegacy__deps: ['$createDyncallWrapper'], +#endif $dynCallLegacy: function(sig, ptr, args) { #if ASSERTIONS #if MINIMAL_RUNTIME @@ -3234,159 +3238,6 @@ mergeInto(LibraryManager.library, { return args && args.length ? f.apply(null, [ptr].concat(args)) : f.call(null, ptr); }, $dynCall__deps: ['$dynCallLegacy', '$getWasmTableEntry'], -#if MAIN_MODULE == 1 - $dynCallLegacy__deps: ['$createDyncallWrapper'], - $createDyncallWrapper__deps: ['$generateFuncType', '$uleb128Encode'], - $createDyncallWrapper: function(sig) { - var sections = []; - var prelude = [ - 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm") - 0x01, 0x00, 0x00, 0x00, // version: 1 - ]; - sections.push(prelude); - var wrappersig = [ - // if return type is j, we will put the upper 32 bits into tempRet0. - sig[0].replace("j", "i"), - "i", // The first argument is the function pointer to call - // in the rest of the argument list, one 64 bit integer is legalized into - // two 32 bit integers. - sig.slice(1).replace("j", "ii"), - ].join(""); - - var typeSectionBody = [ - 0x03, // number of types = 3 - ]; - generateFuncType(wrappersig, typeSectionBody); // The signature of the wrapper we are generating - generateFuncType(sig, typeSectionBody); // the signature of the function pointer we will call - generateFuncType("vi", typeSectionBody); // the signature of setTempRet0 - - typeSection = [0x01 /* Type section code */]; - uleb128Encode(typeSection.length, typeSection); // length of section in bytes - typeSection.push.apply(typeSection, typeSectionBody); - sections.push(typeSection); - - var importSection = [ - 0x02, // import section code - 0x0F, // length of section in bytes - 0x02, // number of imports = 2 - // Import the wasmTable, which we will call "t" - 0x01, 0x65, // name "e" - 0x01, 0x74, // name "t" - 0x01, 0x70, // importing a table - 0x00, // with no max # of elements - 0x00, // and min of 0 elements - // Import the setTempRet0 function, which we will call "r" - 0x01, 0x65, // name "e" - 0x01, 0x72, // name "r" - 0x00, // importing a function - 0x02, // type 2 - ]; - sections.push(importSection); - - var functionSection = [ - 0x03, // function section code - 0x02, // length of section in bytes - 0x01, // number of functions = 1 - 0x00, // type 0 = wrappersig - ]; - sections.push(functionSection); - - var exportSection = [ - 0x07, // export section code - 0x05, // length of section in bytes - 0x01, // One export - 0x01, 0x66, // name "f" - 0x00, // type: function - 0x01, // function index 1 = the wrapper function (index 0 is setTempRet0) - ]; - sections.push(exportSection); - - var convert_code = []; - if (sig[0] === "j") { - // Add a single extra i64 local. In order to legalize the return value we - // need a local to store it in. Local variables are run length encoded. - convert_code = [ - 0x01, // One run - 0x01, // of length 1 - 0x7e, // of i64 - ]; - } else { - convert_code.push(0x00); // no local variables (except the arguments) - } - - function localGet(j){ - convert_code.push(0x20); // local.get - uleb128Encode(j, convert_code); - } - - var j = 1; - for (var i = 1; i < sig.length; i++) { - if (sig[i] == "j") { - localGet(j + 1); - convert_code.push( - 0xad, // i64.extend_i32_unsigned - 0x42, 0x20, // i64.const 32 - 0x86, // i64.shl, - ) - localGet(j); - convert_code.push( - 0xac, // i64.extend_i32_signed - 0x84, // i64.or - ); - j+=2; - } else { - localGet(j); - j++; - } - } - - convert_code.push( - 0x20, 0x00, // local.get 0 (put function pointer on stack) - 0x11, 0x01, 0x00, // call_indirect type 1 = wrapped_sig, table 0 = only table - ); - - if (sig[0] === "j") { - convert_code.push( - // tee into j (after the argument handling loop, j is one past the - // argument list so it points to the i64 local we added) - 0x22, - ) - uleb128Encode(j, convert_code); - convert_code.push( - 0x42, 0x20, // i64.const 32 - 0x88, // i64.shr_u - 0xa7, // i32.wrap_i64 - 0x10, 0x00, // Call function 0 - ); - localGet(j); - convert_code.push( - 0xa7, // i32.wrap_i64 - ); - } - convert_code.push(0x0b); // end - - var codeBody = [0x01]; // one code - uleb128Encode(convert_code.length, codeBody); - codeBody.push.apply(codeBody, convert_code); - var codeSection = [0x0A /* Code section code */]; - uleb128Encode(codeBody.length, codeSection); - codeSection.push.apply(codeSection, codeBody); - sections.push(codeSection); - - var bytes = new Uint8Array([].concat.apply([], sections)); - - // We can compile this wasm module synchronously because it is small. - var module = new WebAssembly.Module(bytes); - var instance = new WebAssembly.Instance(module, { - 'e': { - 't': wasmTable, - 'r': setTempRet0, - } - }); - var wrappedFunc = instance.exports['f']; - return wrappedFunc; - }, -#endif #endif // Used in library code to get JS function from wasm function pointer. diff --git a/src/library_makeDynCall b/src/library_makeDynCall new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/library_makeDynCall.js b/src/library_makeDynCall.js new file mode 100644 index 0000000000000..0b7f84d22fdb4 --- /dev/null +++ b/src/library_makeDynCall.js @@ -0,0 +1,154 @@ +/** + * @license + * Copyright 2020 The Emscripten Authors + * SPDX-License-Identifier: MIT + */ + +mergeInto(LibraryManager.library, { + $createDyncallWrapper__deps: ['$generateFuncType', '$uleb128Encode'], + $createDyncallWrapper: function(sig) { + var sections = []; + var prelude = [ + 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm") + 0x01, 0x00, 0x00, 0x00, // version: 1 + ]; + sections.push(prelude); + var wrappersig = [ + // if return type is j, we will put the upper 32 bits into tempRet0. + sig[0].replace("j", "i"), + "i", // The first argument is the function pointer to call + // in the rest of the argument list, one 64 bit integer is legalized into + // two 32 bit integers. + sig.slice(1).replace("j", "ii"), + ].join(""); + + var typeSectionBody = [ + 0x03, // number of types = 3 + ]; + generateFuncType(wrappersig, typeSectionBody); // The signature of the wrapper we are generating + generateFuncType(sig, typeSectionBody); // the signature of the function pointer we will call + generateFuncType("vi", typeSectionBody); // the signature of setTempRet0 + + typeSection = [0x01 /* Type section code */]; + uleb128Encode(typeSection.length, typeSection); // length of section in bytes + typeSection.push.apply(typeSection, typeSectionBody); + sections.push(typeSection); + + var importSection = [ + 0x02, // import section code + 0x0F, // length of section in bytes + 0x02, // number of imports = 2 + // Import the wasmTable, which we will call "t" + 0x01, 0x65, // name "e" + 0x01, 0x74, // name "t" + 0x01, 0x70, // importing a table + 0x00, // with no max # of elements + 0x00, // and min of 0 elements + // Import the setTempRet0 function, which we will call "r" + 0x01, 0x65, // name "e" + 0x01, 0x72, // name "r" + 0x00, // importing a function + 0x02, // type 2 + ]; + sections.push(importSection); + + var functionSection = [ + 0x03, // function section code + 0x02, // length of section in bytes + 0x01, // number of functions = 1 + 0x00, // type 0 = wrappersig + ]; + sections.push(functionSection); + + var exportSection = [ + 0x07, // export section code + 0x05, // length of section in bytes + 0x01, // One export + 0x01, 0x66, // name "f" + 0x00, // type: function + 0x01, // function index 1 = the wrapper function (index 0 is setTempRet0) + ]; + sections.push(exportSection); + + var convert_code = []; + if (sig[0] === "j") { + // Add a single extra i64 local. In order to legalize the return value we + // need a local to store it in. Local variables are run length encoded. + convert_code = [ + 0x01, // One run + 0x01, // of length 1 + 0x7e, // of i64 + ]; + } else { + convert_code.push(0x00); // no local variables (except the arguments) + } + + function localGet(j){ + convert_code.push(0x20); // local.get + uleb128Encode(j, convert_code); + } + + var j = 1; + for (var i = 1; i < sig.length; i++) { + if (sig[i] == "j") { + localGet(j + 1); + convert_code.push( + 0xad, // i64.extend_i32_unsigned + 0x42, 0x20, // i64.const 32 + 0x86, // i64.shl, + ) + localGet(j); + convert_code.push( + 0xac, // i64.extend_i32_signed + 0x84, // i64.or + ); + j+=2; + } else { + localGet(j); + j++; + } + } + + convert_code.push( + 0x20, 0x00, // local.get 0 (put function pointer on stack) + 0x11, 0x01, 0x00, // call_indirect type 1 = wrapped_sig, table 0 = only table + ); +if (sig[0] === "j") { + // tee into j (after the argument handling loop, j is one past the + // argument list so it points to the i64 local we added) + convert_code.push(0x22); + uleb128Encode(j, convert_code); + convert_code.push( + 0x42, 0x20, // i64.const 32 + 0x88, // i64.shr_u + 0xa7, // i32.wrap_i64 + 0x10, 0x00, // Call function 0 + ); + localGet(j); + convert_code.push( + 0xa7, // i32.wrap_i64 + ); + } + convert_code.push(0x0b); // end + + var codeBody = [0x01]; // one code + uleb128Encode(convert_code.length, codeBody); + codeBody.push.apply(codeBody, convert_code); + var codeSection = [0x0A /* Code section code */]; + uleb128Encode(codeBody.length, codeSection); + codeSection.push.apply(codeSection, codeBody); + sections.push(codeSection); + + var bytes = new Uint8Array([].concat.apply([], sections)); + // We can compile this wasm module synchronously because it is small. + var module = new WebAssembly.Module(bytes); + var instance = new WebAssembly.Instance(module, { + 'e': { + 't': wasmTable, + 'r': setTempRet0, + } + }); + var wrappedFunc = instance.exports['f']; + return wrappedFunc; + }, +}); \ No newline at end of file diff --git a/src/modules.js b/src/modules.js index 6ce678a195a2f..49b0842dcc107 100644 --- a/src/modules.js +++ b/src/modules.js @@ -50,6 +50,7 @@ global.LibraryManager = { 'library_stack_trace.js', 'library_wasi.js', 'library_dylink.js', + 'library_makeDynCall.js', 'library_eventloop.js', ]; From 14a3c1a804ea9881249de03aed48e529e1308b72 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 23 Jul 2022 09:02:47 +0100 Subject: [PATCH 09/18] Fix closure error --- src/library_makeDynCall | 0 src/library_makeDynCall.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 src/library_makeDynCall diff --git a/src/library_makeDynCall b/src/library_makeDynCall deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/src/library_makeDynCall.js b/src/library_makeDynCall.js index 0b7f84d22fdb4..0b44486b8c53a 100644 --- a/src/library_makeDynCall.js +++ b/src/library_makeDynCall.js @@ -29,7 +29,7 @@ mergeInto(LibraryManager.library, { generateFuncType(sig, typeSectionBody); // the signature of the function pointer we will call generateFuncType("vi", typeSectionBody); // the signature of setTempRet0 - typeSection = [0x01 /* Type section code */]; + var typeSection = [0x01 /* Type section code */]; uleb128Encode(typeSection.length, typeSection); // length of section in bytes typeSection.push.apply(typeSection, typeSectionBody); sections.push(typeSection); From 1341807f86346970248d671a9aec462816a01f00 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 23 Jul 2022 09:33:47 +0100 Subject: [PATCH 10/18] Fix type section --- src/library_makeDynCall.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library_makeDynCall.js b/src/library_makeDynCall.js index 0b44486b8c53a..62abd5ae3910f 100644 --- a/src/library_makeDynCall.js +++ b/src/library_makeDynCall.js @@ -30,7 +30,7 @@ mergeInto(LibraryManager.library, { generateFuncType("vi", typeSectionBody); // the signature of setTempRet0 var typeSection = [0x01 /* Type section code */]; - uleb128Encode(typeSection.length, typeSection); // length of section in bytes + uleb128Encode(typeSectionBody.length, typeSection); // length of section in bytes typeSection.push.apply(typeSection, typeSectionBody); sections.push(typeSection); From 5cde82bfdc4129709a031b33acb4b1ae61bf5fda Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 23 Jul 2022 09:41:54 +0100 Subject: [PATCH 11/18] Add test --- tests/test_other.py | 4 ++++ tests/test_runtime_dyncall_wrapper.c | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/test_runtime_dyncall_wrapper.c diff --git a/tests/test_other.py b/tests/test_other.py index eab4e2bdbb5cb..4a2ef3fbfac4d 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -12384,3 +12384,7 @@ def test_warn_once(self): } ''') self.do_runf('main.c', 'warning: foo\ndone\n') + + def test_dyncallwrapper(self): + self.set_setting('MAIN_MODULE', 1) + self.do_runf(test_file('test_runtime_dyncall_wrapper.c'),"2 7\ni: 2 j: 8589934599 f: 3.120000 d: 77.120000") diff --git a/tests/test_runtime_dyncall_wrapper.c b/tests/test_runtime_dyncall_wrapper.c new file mode 100644 index 0000000000000..950a54cece0a3 --- /dev/null +++ b/tests/test_runtime_dyncall_wrapper.c @@ -0,0 +1,24 @@ +#include +#include "stdint.h" +#include "stdio.h" + +uint64_t f1(uint64_t x){ + return x; +} + +void f2(int i, uint64_t j, float f, double d){ + printf("i: %d j: %lld f: %f d: %lf\n", i, j, f, d); +} + + +int main(){ + EM_ASM({ + var w = createDyncallWrapper("jj"); + console.log(w($0, 2, 7), tempRet0); + }, f1); + + EM_ASM({ + var w = createDyncallWrapper("vijfd"); + w($0, 2, 7, 2, 3.12, 77.12); + }, f2); +} \ No newline at end of file From 0ff7b967f5e4f5e5c25b02b7ca2a73c581367703 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 23 Jul 2022 10:09:48 +0100 Subject: [PATCH 12/18] Fix formatting --- tests/test_other.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_other.py b/tests/test_other.py index 4a2ef3fbfac4d..9b45d6b9836f3 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -12387,4 +12387,5 @@ def test_warn_once(self): def test_dyncallwrapper(self): self.set_setting('MAIN_MODULE', 1) - self.do_runf(test_file('test_runtime_dyncall_wrapper.c'),"2 7\ni: 2 j: 8589934599 f: 3.120000 d: 77.120000") + expected = "2 7\ni: 2 j: 8589934599 f: 3.120000 d: 77.120000" + self.do_runf(test_file('test_runtime_dyncall_wrapper.c'), expected) From fd40684cf246e7e8a86c011b5fe0cdb81d6676c9 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 16 Aug 2022 20:32:07 +0200 Subject: [PATCH 13/18] Apply suggestions from code review Co-authored-by: Alon Zakai --- src/library.js | 5 ++--- src/library_makeDynCall.js | 4 ++-- tests/test_runtime_dyncall_wrapper.c | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/library.js b/src/library.js index 826258245191e..5a9b01e959c28 100644 --- a/src/library.js +++ b/src/library.js @@ -3209,7 +3209,6 @@ mergeInto(LibraryManager.library, { #if DYNCALLS || !WASM_BIGINT #if MAIN_MODULE == 1 - // createDyncallWrapper is defined in library_makeDynCall $dynCallLegacy__deps: ['$createDyncallWrapper'], #endif $dynCallLegacy: function(sig, ptr, args) { @@ -3228,11 +3227,11 @@ mergeInto(LibraryManager.library, { #if MINIMAL_RUNTIME var f = dynCalls[sig]; #else - #if MAIN_MODULE == 1 +#if MAIN_MODULE == 1 if (!('dynCall_' + sig in Module)) { Module['dynCall_' + sig] = createDyncallWrapper(sig); } - #endif +#endif var f = Module['dynCall_' + sig]; #endif return args && args.length ? f.apply(null, [ptr].concat(args)) : f.call(null, ptr); diff --git a/src/library_makeDynCall.js b/src/library_makeDynCall.js index 62abd5ae3910f..ad6750ebb2bd8 100644 --- a/src/library_makeDynCall.js +++ b/src/library_makeDynCall.js @@ -83,7 +83,7 @@ mergeInto(LibraryManager.library, { convert_code.push(0x00); // no local variables (except the arguments) } - function localGet(j){ + function localGet(j) { convert_code.push(0x20); // local.get uleb128Encode(j, convert_code); } @@ -151,4 +151,4 @@ if (sig[0] === "j") { var wrappedFunc = instance.exports['f']; return wrappedFunc; }, -}); \ No newline at end of file +}); diff --git a/tests/test_runtime_dyncall_wrapper.c b/tests/test_runtime_dyncall_wrapper.c index 950a54cece0a3..a36028ee97be1 100644 --- a/tests/test_runtime_dyncall_wrapper.c +++ b/tests/test_runtime_dyncall_wrapper.c @@ -21,4 +21,4 @@ int main(){ var w = createDyncallWrapper("vijfd"); w($0, 2, 7, 2, 3.12, 77.12); }, f2); -} \ No newline at end of file +} From 49ab4c200a60d7577a4f4ae70e1c6eedb75874eb Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 26 Aug 2022 11:54:39 -0700 Subject: [PATCH 14/18] add getTempRet0 to REQUIRED_EXPORTS --- emcc.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/emcc.py b/emcc.py index 788dfa07588a6..f3073934306ae 100755 --- a/emcc.py +++ b/emcc.py @@ -2386,8 +2386,15 @@ def check_memory_setting(setting): options.memory_init_file = True settings.MEM_INIT_IN_WASM = True - if settings.MAYBE_WASM2JS or settings.AUTODEBUG or settings.LINKABLE or not settings.DISABLE_EXCEPTION_CATCHING: - settings.REQUIRED_EXPORTS += ['getTempRet0', 'setTempRet0'] + if ( + settings.MAYBE_WASM2JS + or settings.AUTODEBUG + or settings.LINKABLE + or not settings.DISABLE_EXCEPTION_CATCHING + or (settings.MAIN_MODULE == 1 and (settings.DYNCALLS or not settings.WASM_BIGINT)) + ): + settings.REQUIRED_EXPORTS += ["getTempRet0", "setTempRet0"] + if settings.LEGALIZE_JS_FFI: settings.REQUIRED_EXPORTS += ['__get_temp_ret', '__set_temp_ret'] From 195032182a6762267d0a8607860aac3569337df5 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 26 Aug 2022 12:37:22 -0700 Subject: [PATCH 15/18] Fix flake errors --- emcc.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/emcc.py b/emcc.py index f3073934306ae..b3cd09cd5cf4f 100755 --- a/emcc.py +++ b/emcc.py @@ -2387,15 +2387,14 @@ def check_memory_setting(setting): settings.MEM_INIT_IN_WASM = True if ( - settings.MAYBE_WASM2JS - or settings.AUTODEBUG - or settings.LINKABLE - or not settings.DISABLE_EXCEPTION_CATCHING - or (settings.MAIN_MODULE == 1 and (settings.DYNCALLS or not settings.WASM_BIGINT)) + settings.MAYBE_WASM2JS or + settings.AUTODEBUG or + settings.LINKABLE or + not settings.DISABLE_EXCEPTION_CATCHING or + (settings.MAIN_MODULE == 1 and (settings.DYNCALLS or not settings.WASM_BIGINT)) ): settings.REQUIRED_EXPORTS += ["getTempRet0", "setTempRet0"] - if settings.LEGALIZE_JS_FFI: settings.REQUIRED_EXPORTS += ['__get_temp_ret', '__set_temp_ret'] From d9891266fe71b5b54d567418102e5d18779e067d Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sun, 28 Aug 2022 08:55:01 -0700 Subject: [PATCH 16/18] Fix test --- test/test_runtime_dyncall_wrapper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_runtime_dyncall_wrapper.c b/test/test_runtime_dyncall_wrapper.c index a36028ee97be1..d54a19dd8821a 100644 --- a/test/test_runtime_dyncall_wrapper.c +++ b/test/test_runtime_dyncall_wrapper.c @@ -14,7 +14,7 @@ void f2(int i, uint64_t j, float f, double d){ int main(){ EM_ASM({ var w = createDyncallWrapper("jj"); - console.log(w($0, 2, 7), tempRet0); + console.log(w($0, 2, 7), getTempRet0()); }, f1); EM_ASM({ From c32bf3b4e583ee6f5970a450bab127ef3948a49e Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sun, 28 Aug 2022 09:52:21 -0700 Subject: [PATCH 17/18] Fix flake8 --- emcc.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/emcc.py b/emcc.py index b3cd09cd5cf4f..4aceed4542e08 100755 --- a/emcc.py +++ b/emcc.py @@ -2387,10 +2387,10 @@ def check_memory_setting(setting): settings.MEM_INIT_IN_WASM = True if ( - settings.MAYBE_WASM2JS or - settings.AUTODEBUG or - settings.LINKABLE or - not settings.DISABLE_EXCEPTION_CATCHING or + settings.MAYBE_WASM2JS or + settings.AUTODEBUG or + settings.LINKABLE or + not settings.DISABLE_EXCEPTION_CATCHING or (settings.MAIN_MODULE == 1 and (settings.DYNCALLS or not settings.WASM_BIGINT)) ): settings.REQUIRED_EXPORTS += ["getTempRet0", "setTempRet0"] From bc559963719c12f64c4409ce4329da6d0b4b0cb1 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sun, 28 Aug 2022 09:54:30 -0700 Subject: [PATCH 18/18] Fix two more tests --- emcc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/emcc.py b/emcc.py index 4aceed4542e08..65ebe28e454fb 100755 --- a/emcc.py +++ b/emcc.py @@ -2390,6 +2390,7 @@ def check_memory_setting(setting): settings.MAYBE_WASM2JS or settings.AUTODEBUG or settings.LINKABLE or + settings.INCLUDE_FULL_LIBRARY or not settings.DISABLE_EXCEPTION_CATCHING or (settings.MAIN_MODULE == 1 and (settings.DYNCALLS or not settings.WASM_BIGINT)) ):