-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Description
Please include the following in your bug report:
Version of emscripten/emsdk:
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 4.0.22 (0f3d2e62bccf8e14497ff19e05a1202c51eb0c65)
clang version 22.0.0git (https:/github.com/llvm/llvm-project c7706d9472fe880ba1d3418919ad4185710c9559)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /home/va_erie/Projects/emsdk/upstream/bin
When compiling even the simplest library, the __setitimer_js function is always included in the glue code and imported into the WebAssembly module:
var __setitimer_js = (which, timeout_ms) => {
// First, clear any existing timer.
if (timers[which]) {
clearTimeout(timers[which].id);
delete timers[which];
}
// A timeout of zero simply cancels the current timeout so we have nothing
// more to do.
if (!timeout_ms) return 0;
var id = setTimeout(() => {
delete timers[which];
callUserCallback(() => __emscripten_timeout(which, _emscripten_get_now()));
}, timeout_ms);
timers[which] = {
id,
timeout_ms
};
return 0;
};
// ...
var wasmImports = {
/** @export */ c: __abort_js,
/** @export */ b: __emscripten_runtime_keepalive_clear,
/** @export */ a: __setitimer_js,
/** @export */ d: _proc_exit
};This happens even if we don't call any functions that use timers, or even call libc functions at all. Simply linking to libc is sufficient to cause __setitimer_js to end up in the glue code.
I think this is caused by a circular dependency. The setitimer libc function calls _emscripten_timeout, which calls the JS-side _setitimer_js. This adds a dependency on the _setitimer_js function from libc.
Then on the JS side, _setitimer_js calls back into the WASM-side _emscripten_timeout, adding a dependency on it. Because we have a JS-side dependency on _emscripten_timeout, it cannot be DCE'd by the linker. Therefore, simply by importing libc, we end up including a bunch of timer glue code that is never actually called.
See also #22534.
You can reproduce this by creating some really simple C code:
int add(int a, int b) {
return a + b;
}And compiling it like so:
emcc \
-s MODULARIZE \
-s EXPORT_ES6 \
-s EXPORT_NAME=createAdd \
-s EXPORTED_FUNCTIONS='["_add"]' \
-s MAIN_MODULE=0 \
-s ENVIRONMENT=web \
-s MINIMAL_RUNTIME=1 \
-o add.js \
-Oz \
-flto \
--minify=0 \
--no-entry \
add.c