`EMSCRIPTEN_KEEPALIVE` doesn't work for static functions
Please include the following in your bug report:
Version of emscripten/emsdk: 3.1.74
Hi, I just met some problems when using the EMSCRIPTEN_KEEPALIVE flag with static function definitions. It seems that for static functions, adding EMSCRIPTEN_KEEPALIVE couldn't guarantee that the code would be preserved, as shown in the following example.
Thank you very much for your consideration!
Source code (test_keepalive.cpp):
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE static int test_keepalive() {
return 1 + 1;
}
Compilation command:
$ emcc test_keepalive.cpp -o test.wasm -g --no-entry
$ wasm2wat test.wasm -o test.wat
Result:
(module $test.wasm
(type (;0;) (func (result i32)))
(type (;1;) (func))
(type (;2;) (func (param i32)))
(func $__wasm_call_ctors (type 1)
call $emscripten_stack_init)
(func $_initialize (type 1)
block ;; label = @1
i32.const 1
i32.eqz
br_if 0 (;@1;)
call $__wasm_call_ctors
end)
(func $emscripten_stack_init (type 1)
i32.const 65536
global.set $__stack_base
i32.const 0
i32.const 15
i32.add
i32.const -16
i32.and
global.set $__stack_end)
(func $emscripten_stack_get_free (type 0) (result i32)
global.get $__stack_pointer
global.get $__stack_end
i32.sub)
(func $emscripten_stack_get_base (type 0) (result i32)
global.get $__stack_base)
(func $emscripten_stack_get_end (type 0) (result i32)
global.get $__stack_end)
(func $_emscripten_stack_restore (type 2) (param i32)
local.get 0
global.set $__stack_pointer)
(func $emscripten_stack_get_current (type 0) (result i32)
global.get $__stack_pointer)
(table (;0;) 2 2 funcref)
(memory (;0;) 257 257)
(global $__stack_pointer (mut i32) (i32.const 65536))
(global $__stack_end (mut i32) (i32.const 0))
(global $__stack_base (mut i32) (i32.const 0))
(export "memory" (memory 0))
(export "__indirect_function_table" (table 0))
(export "_initialize" (func $_initialize))
(export "emscripten_stack_init" (func $emscripten_stack_init))
(export "emscripten_stack_get_free" (func $emscripten_stack_get_free))
(export "emscripten_stack_get_base" (func $emscripten_stack_get_base))
(export "emscripten_stack_get_end" (func $emscripten_stack_get_end))
(export "_emscripten_stack_restore" (func $_emscripten_stack_restore))
(export "emscripten_stack_get_current" (func $emscripten_stack_get_current))
(elem (;0;) (i32.const 1) func $__wasm_call_ctors))
Yes, this is mostly just a artifact of how EMSCRIPTEN_KEEPALIVE works. Currently its implemented as __attribute__((used)).
The core problem is that static functions are internal of the object file so don't even show up in the linker's symbol table. Marking a function as static and exporting it is kind of a contradiction so I don't think its is a huge issues, and is perhaps just something that should be documented somewhere.