diff --git a/src/lib/libaddfunction.js b/src/lib/libaddfunction.js index 195b5263df938..d0c4ec81e5288 100644 --- a/src/lib/libaddfunction.js +++ b/src/lib/libaddfunction.js @@ -114,7 +114,7 @@ addToLibrary({ #endif }, - $updateTableMap__deps: ['$getWasmTableEntry'], + $updateTableMap__deps: ['$getWasmTableEntry', '$functionsInTableMap'], $updateTableMap: (offset, count) => { if (functionsInTableMap) { for (var i = offset; i < offset + count; i++) { diff --git a/src/lib/libcore.js b/src/lib/libcore.js index f382ce245dcdd..73070bb830b2d 100644 --- a/src/lib/libcore.js +++ b/src/lib/libcore.js @@ -1408,6 +1408,7 @@ addToLibrary({ $timers: {}, $clearTimers__internal: true, + $clearTimers__deps: ['$timers'], $clearTimers: () => { for (var t of Object.values(timers)) { clearTimeout(t.id); @@ -2079,9 +2080,12 @@ addToLibrary({ emscripten_throw_string: (str) => { throw UTF8ToString(str); }, #if !MINIMAL_RUNTIME + $handleException__deps: [ + '$ExitStatus', #if STACK_OVERFLOW_CHECK - $handleException__deps: ['emscripten_stack_get_current'], + 'emscripten_stack_get_current', #endif + ], $handleException: (e) => { // Certain exception types we do not treat as errors since they are used for // internal control flow. diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 0c0b31aba402b..f4fe51f2fc3d9 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -16,7 +16,7 @@ const UNDEFINED_ADDR = to64(-1); var LibraryDylink = { #if FILESYSTEM - $registerWasmPlugin__deps: ['$preloadPlugins'], + $registerWasmPlugin__deps: ['$preloadPlugins', '$loadWebAssemblyModule', '$preloadedWasm'], $registerWasmPlugin: () => { // Use string keys here for public methods to avoid minification since the // plugin consumer also uses string keys. @@ -310,7 +310,7 @@ var LibraryDylink = { }, $reportUndefinedSymbols__internal: true, - $reportUndefinedSymbols__deps: ['$GOT', '$resolveGlobalSymbol'], + $reportUndefinedSymbols__deps: ['$GOT', '$resolveGlobalSymbol', '$addFunction'], $reportUndefinedSymbols: () => { #if DYLINK_DEBUG dbg('reportUndefinedSymbols'); @@ -393,7 +393,11 @@ var LibraryDylink = { // Allocate memory even if malloc isn't ready yet. The allocated memory here // must be zero initialized since its used for all static data, including bss. $getMemory__noleakcheck: true, - $getMemory__deps: ['emscripten_get_sbrk_ptr', '__heap_base', '$alignMemory', 'calloc'], + // `__heap_base` is also used below, but is added via `REQUIRED_EXPORTS` in + // `link.py` rather than `__deps` because `wasm-ld` processes stub library + // dependencies before synthesizing optional symbols like `__heap_base`. + // See https://github.com/llvm/llvm-project/issues/180632 + $getMemory__deps: ['emscripten_get_sbrk_ptr', '$alignMemory', 'calloc'], $getMemory: (size) => { // After the runtime is initialized, we must only use sbrk() normally. #if DYLINK_DEBUG @@ -684,6 +688,9 @@ var LibraryDylink = { '$loadDynamicLibrary', '$getDylinkMetadata', '$instantiateModule', +#if FILESYSTEM + '$findLibraryFS', +#endif ], $loadWebAssemblyModule: (binary, flags, libName, localScope, handle) => { #if DYLINK_DEBUG @@ -722,6 +729,7 @@ var LibraryDylink = { $instantiateModule__deps: [ '$getMemory', '$updateGOT', '$relocateExports', '$resolveGlobalSymbol', '$GOTHandler', + '$reportUndefinedSymbols', '$alignMemory', '$updateTableMap', '$wasmTable', '$addOnPostCtor', '$addEmAsm', '$addEmJs', @@ -996,6 +1004,7 @@ var LibraryDylink = { }, #endif + $newDSO__deps: ['$LDSO'], $newDSO: (name, handle, syms) => { var dso = { refcount: Infinity, @@ -1082,6 +1091,7 @@ var LibraryDylink = { '$mergeLibSymbols', '$newDSO', '$asyncLoad', #if FILESYSTEM + '$FS', '$preloadedWasm', '$findLibraryFS', #endif diff --git a/src/lib/libfs_shared.js b/src/lib/libfs_shared.js index eb13e1e2f2a61..75dbcda876240 100644 --- a/src/lib/libfs_shared.js +++ b/src/lib/libfs_shared.js @@ -107,6 +107,7 @@ addToLibrary({ return mode; }, + $FS_fileDataToTypedArray__deps: ['$intArrayFromString'], $FS_fileDataToTypedArray: (data) => { if (typeof data === 'string') { data = intArrayFromString(data, true); diff --git a/src/lib/libopenal.js b/src/lib/libopenal.js index 397c1028be4c0..64902650f6afc 100644 --- a/src/lib/libopenal.js +++ b/src/lib/libopenal.js @@ -3274,6 +3274,7 @@ var LibraryOpenAL = { // alDopplerVelocity() sets a multiplier for the speed of sound. // It's deprecated since it's equivalent to directly calling // alSpeedOfSound() with an appropriately premultiplied value. + alDopplerVelocity__deps: ['$warnOnce'], alDopplerVelocity__proxy: 'sync', alDopplerVelocity: (value) => { warnOnce('alDopplerVelocity() is deprecated, and only kept for compatibility with OpenAL 1.0. Use alSpeedOfSound() instead.'); diff --git a/src/lib/libpthread.js b/src/lib/libpthread.js index 9b2807e48d42a..df4687930deaa 100644 --- a/src/lib/libpthread.js +++ b/src/lib/libpthread.js @@ -81,15 +81,20 @@ const pthreadWorkerOptions = `{ var LibraryPThread = { $PThread__postset: 'PThread.init();', $PThread__deps: ['_emscripten_thread_init', + '$callUserCallback', + '$checkMailbox', '$terminateWorker', '$cleanupThread', -#if !MINIMAL_RUNTIME && PTHREAD_POOL_SIZE +#if !MINIMAL_RUNTIME + '$wasmMemory', +#if PTHREAD_POOL_SIZE '$addOnPreRun', #if !PTHREAD_POOL_DELAY_LOAD '$addRunDependency', '$removeRunDependency', #endif #endif +#endif #if MAIN_MODULE '$markAsFinished', #endif diff --git a/src/lib/libwasm_worker.js b/src/lib/libwasm_worker.js index dc5cd2ce3d5ad..d643645e8fc62 100644 --- a/src/lib/libwasm_worker.js +++ b/src/lib/libwasm_worker.js @@ -74,6 +74,7 @@ addToLibrary({ // which these postponed function calls can be dispatched. $_wasmWorkerDelayedMessageQueue: [], + $_wasmWorkerAppendToQueue__deps: ['$_wasmWorkerDelayedMessageQueue'], $_wasmWorkerAppendToQueue: (e) => { _wasmWorkerDelayedMessageQueue.push(e); }, diff --git a/src/lib/libwebaudio.js b/src/lib/libwebaudio.js index e3cb8d5e04376..23d464e4d4e08 100644 --- a/src/lib/libwebaudio.js +++ b/src/lib/libwebaudio.js @@ -161,6 +161,7 @@ var LibraryWebAudio = { // etc., but the created worklet does. _emscripten_create_audio_worklet__deps: [ '$_emAudioDispatchProcessorCallback', + '$emAudio', '$stackAlloc', '$stackRestore', '$stackSave', '$HEAP32', '$HEAPU32', '$HEAPF32', #if WASM_BIGINT || MEMORY64 '$HEAP64', '$HEAPU64', diff --git a/test/codesize/audio_worklet_wasm.expected.js b/test/codesize/audio_worklet_wasm.expected.js index 33b73ba3a777c..19d2688d03b02 100644 --- a/test/codesize/audio_worklet_wasm.expected.js +++ b/test/codesize/audio_worklet_wasm.expected.js @@ -102,9 +102,9 @@ u || (x = new WebAssembly.Memory({ shared: !0 }), y()); -var M = a => { +var L = [], M = a => { L.push(a); -}, L = [], N = a => { +}, N = a => { a = a.data; var b = a._wsc; b && A.get(b)(...a.x); @@ -114,7 +114,7 @@ var M = a => { a = a.data; var b = a._wsc; b && A.get(b)(...a.D); -}, ca = (a, b, c, k, d, g, f) => { +}, Q = {}, ca = (a, b, c, k, d, g, f) => { var l = Q[b], n = l.audioWorklet; d = () => { A.get(g)(b, 0, f); @@ -159,7 +159,7 @@ var M = a => { } else k += String.fromCharCode(d); } return k; -}, Q = {}, T = 0, ea = a => { +}, T = 0, ea = a => { if (a) { var b = G[a >> 2]; b = (b ? S(b) : "") || void 0; diff --git a/test/codesize/hello_wasm_worker_wasm.expected.js b/test/codesize/hello_wasm_worker_wasm.expected.js index 91cedd352ac24..732a8ca6e5191 100644 --- a/test/codesize/hello_wasm_worker_wasm.expected.js +++ b/test/codesize/hello_wasm_worker_wasm.expected.js @@ -16,9 +16,9 @@ e || (g = new WebAssembly.Memory({ shared: !0 })); -var l = a => { +var k = [], l = a => { k.push(a); -}, k = [], n = a => { +}, n = a => { a = a.data; var b = a._wsc; b && m.get(b)(...a.x); diff --git a/test/codesize/test_codesize_file_preload.expected.js b/test/codesize/test_codesize_file_preload.expected.js index 98a4f63d35151..38c676696afdf 100644 --- a/test/codesize/test_codesize_file_preload.expected.js +++ b/test/codesize/test_codesize_file_preload.expected.js @@ -663,6 +663,74 @@ var FS_createPreloadedFile = (parent, name, url, canRead, canWrite, onload, oner FS_preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish).then(onload).catch(onerror); }; +var lengthBytesUTF8 = str => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + var u = str.codePointAt(i); + if (u <= 127) { + len++; + } else if (u <= 2047) { + len += 2; + } else if (u <= 65535) { + len += 3; + } else { + len += 4; + // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16. + // We need to manually skip over the second code unit for correct iteration. + i++; + } + } + return len; +}; + +var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { + // Parameter maxBytesToWrite is not optional. Negative values, 0, null, + // undefined and false each don't write out any bytes. + if (!(maxBytesToWrite > 0)) return 0; + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; + // -1 for string null terminator. + for (var i = 0; i < str.length; ++i) { + // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description + // and https://www.ietf.org/rfc/rfc2279.txt + // and https://tools.ietf.org/html/rfc3629 + var u = str.codePointAt(i); + if (u <= 127) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u; + } else if (u <= 2047) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 192 | (u >> 6); + heap[outIdx++] = 128 | (u & 63); + } else if (u <= 65535) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 224 | (u >> 12); + heap[outIdx++] = 128 | ((u >> 6) & 63); + heap[outIdx++] = 128 | (u & 63); + } else { + if (outIdx + 3 >= endIdx) break; + heap[outIdx++] = 240 | (u >> 18); + heap[outIdx++] = 128 | ((u >> 12) & 63); + heap[outIdx++] = 128 | ((u >> 6) & 63); + heap[outIdx++] = 128 | (u & 63); + // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16. + // We need to manually skip over the second code unit for correct iteration. + i++; + } + } + // Null-terminate the pointer to the buffer. + heap[outIdx] = 0; + return outIdx - startIdx; +}; + +/** @type {function(string, boolean=, number=)} */ var intArrayFromString = (stringy, dontAddNull, length) => { + var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1; + var u8array = new Array(len); + var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); + if (dontAddNull) u8array.length = numBytesWritten; + return u8array; +}; + var FS_fileDataToTypedArray = data => { if (typeof data === "string") { data = intArrayFromString(data, true); @@ -1002,74 +1070,6 @@ var MEMFS = { var FS_stdin_getChar_buffer = []; -var lengthBytesUTF8 = str => { - var len = 0; - for (var i = 0; i < str.length; ++i) { - var u = str.codePointAt(i); - if (u <= 127) { - len++; - } else if (u <= 2047) { - len += 2; - } else if (u <= 65535) { - len += 3; - } else { - len += 4; - // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16. - // We need to manually skip over the second code unit for correct iteration. - i++; - } - } - return len; -}; - -var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { - // Parameter maxBytesToWrite is not optional. Negative values, 0, null, - // undefined and false each don't write out any bytes. - if (!(maxBytesToWrite > 0)) return 0; - var startIdx = outIdx; - var endIdx = outIdx + maxBytesToWrite - 1; - // -1 for string null terminator. - for (var i = 0; i < str.length; ++i) { - // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description - // and https://www.ietf.org/rfc/rfc2279.txt - // and https://tools.ietf.org/html/rfc3629 - var u = str.codePointAt(i); - if (u <= 127) { - if (outIdx >= endIdx) break; - heap[outIdx++] = u; - } else if (u <= 2047) { - if (outIdx + 1 >= endIdx) break; - heap[outIdx++] = 192 | (u >> 6); - heap[outIdx++] = 128 | (u & 63); - } else if (u <= 65535) { - if (outIdx + 2 >= endIdx) break; - heap[outIdx++] = 224 | (u >> 12); - heap[outIdx++] = 128 | ((u >> 6) & 63); - heap[outIdx++] = 128 | (u & 63); - } else { - if (outIdx + 3 >= endIdx) break; - heap[outIdx++] = 240 | (u >> 18); - heap[outIdx++] = 128 | ((u >> 12) & 63); - heap[outIdx++] = 128 | ((u >> 6) & 63); - heap[outIdx++] = 128 | (u & 63); - // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16. - // We need to manually skip over the second code unit for correct iteration. - i++; - } - } - // Null-terminate the pointer to the buffer. - heap[outIdx] = 0; - return outIdx - startIdx; -}; - -/** @type {function(string, boolean=, number=)} */ var intArrayFromString = (stringy, dontAddNull, length) => { - var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1; - var u8array = new Array(len); - var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); - if (dontAddNull) u8array.length = numBytesWritten; - return u8array; -}; - var FS_stdin_getChar = () => { if (!FS_stdin_getChar_buffer.length) { var result = null; diff --git a/test/codesize/test_codesize_file_preload.json b/test/codesize/test_codesize_file_preload.json index 6c1e178a3e7e6..14d23b775e57f 100644 --- a/test/codesize/test_codesize_file_preload.json +++ b/test/codesize/test_codesize_file_preload.json @@ -1,10 +1,10 @@ { "a.out.js": 22169, - "a.out.js.gz": 9236, + "a.out.js.gz": 9244, "a.out.nodebug.wasm": 1198, "a.out.nodebug.wasm.gz": 730, "total": 23367, - "total_gz": 9966, + "total_gz": 9974, "sent": [ "a (fd_write)" ], diff --git a/test/codesize/test_codesize_hello_dylink.json b/test/codesize/test_codesize_hello_dylink.json index 2082bdaa2e7b6..15ca5b6de0401 100644 --- a/test/codesize/test_codesize_hello_dylink.json +++ b/test/codesize/test_codesize_hello_dylink.json @@ -1,10 +1,10 @@ { - "a.out.js": 26228, - "a.out.js.gz": 11156, + "a.out.js": 26229, + "a.out.js.gz": 11137, "a.out.nodebug.wasm": 16986, "a.out.nodebug.wasm.gz": 8667, - "total": 43214, - "total_gz": 19823, + "total": 43215, + "total_gz": 19804, "sent": [ "__syscall_stat64", "emscripten_resize_heap", diff --git a/test/codesize/test_codesize_hello_dylink_all.json b/test/codesize/test_codesize_hello_dylink_all.json index b9418fa6e2aa4..4d4e9e1e31f10 100644 --- a/test/codesize/test_codesize_hello_dylink_all.json +++ b/test/codesize/test_codesize_hello_dylink_all.json @@ -1,7 +1,7 @@ { - "a.out.js": 272705, + "a.out.js": 272704, "a.out.nodebug.wasm": 589443, - "total": 862148, + "total": 862147, "sent": [ "IMG_Init", "IMG_Load", diff --git a/test/codesize/test_codesize_minimal_pthreads.json b/test/codesize/test_codesize_minimal_pthreads.json index 36439733e7e81..d7133be62a0cf 100644 --- a/test/codesize/test_codesize_minimal_pthreads.json +++ b/test/codesize/test_codesize_minimal_pthreads.json @@ -1,10 +1,10 @@ { - "a.out.js": 6893, - "a.out.js.gz": 3411, + "a.out.js": 6889, + "a.out.js.gz": 3404, "a.out.nodebug.wasm": 19139, "a.out.nodebug.wasm.gz": 8819, - "total": 26032, - "total_gz": 12230, + "total": 26028, + "total_gz": 12223, "sent": [ "a (memory)", "b (exit)", diff --git a/test/codesize/test_codesize_minimal_pthreads_memgrowth.json b/test/codesize/test_codesize_minimal_pthreads_memgrowth.json index ea983823bff5e..e209dad35c529 100644 --- a/test/codesize/test_codesize_minimal_pthreads_memgrowth.json +++ b/test/codesize/test_codesize_minimal_pthreads_memgrowth.json @@ -1,10 +1,10 @@ { - "a.out.js": 7350, - "a.out.js.gz": 3624, + "a.out.js": 7346, + "a.out.js.gz": 3620, "a.out.nodebug.wasm": 19140, "a.out.nodebug.wasm.gz": 8820, - "total": 26490, - "total_gz": 12444, + "total": 26486, + "total_gz": 12440, "sent": [ "a (memory)", "b (exit)", diff --git a/test/codesize/test_minimal_runtime_code_size_hello_wasm_worker.json b/test/codesize/test_minimal_runtime_code_size_hello_wasm_worker.json index dff9f01744b5e..99f623630e5ea 100644 --- a/test/codesize/test_minimal_runtime_code_size_hello_wasm_worker.json +++ b/test/codesize/test_minimal_runtime_code_size_hello_wasm_worker.json @@ -2,9 +2,9 @@ "a.html": 509, "a.html.gz": 352, "a.js": 923, - "a.js.gz": 581, + "a.js.gz": 582, "a.wasm": 2661, "a.wasm.gz": 1479, "total": 4093, - "total_gz": 2412 + "total_gz": 2413 } diff --git a/test/codesize/test_no_closure_code_size.json b/test/codesize/test_no_closure_code_size.json index e326524c53eb8..e53f62fb90d23 100644 --- a/test/codesize/test_no_closure_code_size.json +++ b/test/codesize/test_no_closure_code_size.json @@ -12,9 +12,9 @@ "strict.wasm": 1188, "strict.wasm.gz": 733, "files.js": 53250, - "files.js.gz": 14901, + "files.js.gz": 14880, "files.wasm": 371, "files.wasm.gz": 264, "total": 75918, - "total_gz": 24423 + "total_gz": 24402 } diff --git a/tools/link.py b/tools/link.py index 838e81125c207..062816b97464c 100644 --- a/tools/link.py +++ b/tools/link.py @@ -1278,7 +1278,12 @@ def limit_incoming_module_api(): settings.INCLUDE_FULL_LIBRARY = 1 # Called from preamble.js once the main module is instantiated. settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$loadDylibs'] - settings.REQUIRED_EXPORTS += ['__stack_pointer'] + # `__stack_pointer` is exported for PIC side modules. `__heap_base` is used + # by `$getMemory` in `libdylink.js` (cannot be in `$getMemory__deps` because + # `wasm-ld` processes stub library dependencies before synthesizing optional + # symbols like `__heap_base`). + # See https://github.com/llvm/llvm-project/issues/180632 + settings.REQUIRED_EXPORTS += ['__stack_pointer', '__heap_base'] if settings.MAIN_MODULE == 1 or settings.SIDE_MODULE == 1: settings.LINKABLE = 1