emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.86k stars 3.32k forks source link

`-s PURE_WASI` doesn't import WASI `random_get`, but then fails when using `std::random_device` #22841

Open geraintluff opened 2 weeks ago

geraintluff commented 2 weeks ago

Since WASI has a random_get() function, I expected to be able to use std::random_device from C++ when compiling with -s PURE_WASI.

Version of emscripten/emsdk: emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.68 (ceee49d2ecdab36a3feb85a684f8e5a453dde910) clang version 20.0.0git (https:/github.com/llvm/llvm-project 5cc64bf60bc04b9315de3c679eb753de4d554a8a) Target: wasm32-unknown-emscripten Thread model: posix InstalledDir: /Users/geraintluff/Development/emsdk/upstream/bin

Failing command line in full:

CPP source:

#include <iostream>
#include <random>

int main() {
    std::random_device device;
    std::random_device::result_type v = device();
    std::cout << "random value: " << v << "\n";
}

Compiled like:

emcc main.cpp -o main.wasm -s PURE_WASI

In a web-page, list the imports and then run:

<body>
    <script type="module">
        import {WASI} from 'https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.3.0/+esm';

        let module = await WebAssembly.compileStreaming(fetch('./main.wasm'));
        // List imports
        console.log(WebAssembly.Module.imports(module));

        let wasi = new WASI([], [], []);
        let instance = await WebAssembly.instantiate(module, {
            "wasi_snapshot_preview1": wasi.wasiImport,
        });
        wasi.start(instance);
    </script>
</body>

The imports are: proc_exit, fd_seek, fd_write, fd_read, fd_close, environ_sizes_get, environ_get from wasi_snapshot_preview1. No random_get.

However running the instance throws:

main.wasm:0x4fd9 Uncaught RuntimeError: unreachable
    at main.wasm._abort_js (main.wasm:0x4fd9)
    at main.wasm.abort (main.wasm:0x24bc)
    at main.wasm.getentropy (main.wasm:0x503d)
    at main.wasm.std::__2::random_device::operator(tmp/)() (http://localhost:8000/main.wasm)
    at main.wasm.__original_main (main.wasm:0xd97)
    at main.wasm._start (main.wasm:0x2201)
    at E.start (wasi.js:1:252)
    at tmp/:13:8

If the call to device() in the C++ code is replaced with something else, it runs fine with no errors.

Full link command and output with -v appended:

geraintluff@Geraints-Mac-mini tmp % emcc main.cpp -o main.wasm -s PURE_WASI -v
 /Users/geraintluff/Development/emsdk/upstream/bin/clang -target wasm32-unknown-emscripten -fignore-exceptions -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --sysroot=/Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot -DEMSCRIPTEN -Werror=implicit-function-declaration -Xclang -iwithsysroot/include/fakesdl -Xclang -iwithsysroot/include/compat -v main.cpp -c -o /var/folders/z2/nxv7b4n94njg_wqj_mk1pwj40000gn/T/emscripten_temp_ufsr8rs3/main_0.o
clang version 20.0.0git (https:/github.com/llvm/llvm-project 5cc64bf60bc04b9315de3c679eb753de4d554a8a)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /Users/geraintluff/Development/emsdk/upstream/bin
 (in-process)
 "/Users/geraintluff/Development/emsdk/upstream/bin/clang-20" -cc1 -triple wasm32-unknown-emscripten -emit-obj -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main.cpp -mrelocation-model static -mframe-pointer=none -ffp-contract=on -fno-rounding-math -mconstructor-aliases -target-cpu generic -fvisibility=hidden -debugger-tuning=gdb -fdebug-compilation-dir=/Users/geraintluff/Development/tmp/emrandom -v -fcoverage-compilation-dir=/Users/geraintluff/Development/tmp/emrandom -resource-dir /Users/geraintluff/Development/emsdk/upstream/lib/clang/20 -D EMSCRIPTEN -isysroot /Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot -cxx-isystem /Users/geraintluff/Development/include -internal-isystem /Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten/c++/v1 -internal-isystem /Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1 -internal-isystem /Users/geraintluff/Development/emsdk/upstream/lib/clang/20/include -internal-isystem /Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten -internal-isystem /Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot/include -Werror=implicit-function-declaration -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fignore-exceptions -fexceptions -fcolor-diagnostics -iwithsysroot/include/fakesdl -iwithsysroot/include/compat -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -o /var/folders/z2/nxv7b4n94njg_wqj_mk1pwj40000gn/T/emscripten_temp_ufsr8rs3/main_0.o -x c++ main.cpp
clang -cc1 version 20.0.0git based upon LLVM 20.0.0git default target x86_64-apple-darwin24.0.0
ignoring nonexistent directory "/Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten/c++/v1"
ignoring nonexistent directory "/Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten"
#include "..." search starts here:
#include <...> search starts here:
 /Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot/include/fakesdl
 /Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot/include/compat
 /Users/geraintluff/Development/include
 /Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1
 /Users/geraintluff/Development/emsdk/upstream/lib/clang/20/include
 /Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot/include
End of search list.
 /Users/geraintluff/Development/emsdk/upstream/bin/clang --version
 /Users/geraintluff/Development/emsdk/upstream/bin/wasm-ld -o main.wasm /var/folders/z2/nxv7b4n94njg_wqj_mk1pwj40000gn/T/emscripten_temp_ufsr8rs3/main_0.o -L/Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten /Users/geraintluff/Development/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/crt1.o -lGL-getprocaddr -lal -lhtml5 -lbulkmemory -lstandalonewasm-nocatch-pure -lstubs-debug -lc-debug -ldlmalloc -lcompiler_rt -lc++-noexcept -lc++abi-debug-noexcept -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -disable-lsr /var/folders/z2/nxv7b4n94njg_wqj_mk1pwj40000gn/T/tmpcdam7562libemscripten_js_symbols.so --strip-debug --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-if-defined=__start_em_lib_deps --export-if-defined=__stop_em_lib_deps --export-if-defined=__start_em_js --export-if-defined=__stop_em_js --export-table -z stack-size=65536 --no-growable-memory --initial-heap=16777216 --stack-first --table-base=1
 /Users/geraintluff/Development/emsdk/upstream/bin/llvm-objcopy main.wasm main.wasm --remove-section=.debug* --remove-section=producers
kripken commented 2 weeks ago

This might have been fixed by https://github.com/emscripten-core/emscripten/pull/22820

To test it, you can use a tip of tree build, emsdk install tot