| .globl emscripten_stack_init |
| .globl emscripten_stack_set_limits |
| .globl emscripten_stack_get_free |
| .globl emscripten_stack_get_base |
| .globl emscripten_stack_get_end |
| |
| #ifdef __wasm64__ |
| #define PTR i64 |
| #define ALIGN 3 |
| #define PTRSTORE .int64 |
| #else |
| #define PTR i32 |
| #define ALIGN 2 |
| #define PTRSTORE .int32 |
| #endif |
| |
| .globaltype __stack_pointer, PTR |
| |
| # TODO(sbc): It would be nice if these we initialized directly |
| # using PTR.const rather than using the `emscripten_stack_init` |
| .globaltype __stack_end, PTR |
| __stack_end: |
| .globaltype __stack_base, PTR |
| __stack_base: |
| |
| emscripten_stack_get_base: |
| .functype emscripten_stack_get_base () -> (PTR) |
| global.get __stack_base |
| end_function |
| |
| emscripten_stack_get_end: |
| .functype emscripten_stack_get_end () -> (PTR) |
| global.get __stack_end |
| end_function |
| |
| emscripten_stack_init: |
| # Initialize __stack_end and __stack_base. |
| # This must be called before emscripten_stack_get_end, |
| # emscripten_stack_get_base, or emscripten_stack_get_free are called |
| .functype emscripten_stack_init () -> () |
| |
| # What llvm calls __stack_high is the high address from where is grows |
| # downwards. We call this the stack base here in emscripten. |
| #ifdef __PIC__ |
| global.get __stack_high@GOT |
| #else |
| PTR.const __stack_high |
| #endif |
| global.set __stack_base |
| |
| # What llvm calls __stack_low is that end of the stack |
| #ifdef __PIC__ |
| global.get __stack_low@GOT |
| #else |
| PTR.const __stack_low |
| #endif |
| # Align up to 16 bytes |
| PTR.const 0xf |
| PTR.add |
| PTR.const -0x10 |
| PTR.and |
| global.set __stack_end |
| |
| end_function |
| |
| emscripten_stack_set_limits: |
| .functype emscripten_stack_set_limits (PTR, PTR) -> () |
| local.get 0 |
| global.set __stack_base |
| local.get 1 |
| global.set __stack_end |
| end_function |
| |
| emscripten_stack_get_free: |
| .functype emscripten_stack_get_free () -> (PTR) |
| global.get __stack_pointer |
| global.get __stack_end |
| PTR.sub |
| end_function |
| |
| #ifdef __EMSCRIPTEN_WASM_WORKERS__ |
| # TODO: Relocate the following to its own file wasm_worker.S, but need to figure out how to reference |
| # __stack_base and __stack_end globals from a separate file as externs in order for that to work. |
| .globl emscripten_wasm_worker_initialize |
| emscripten_wasm_worker_initialize: |
| .functype emscripten_wasm_worker_initialize (PTR /*stackLowestAddress*/, i32 /*stackSize*/) -> () |
| |
| // __stack_end = stackLowestAddress + (__builtin_wasm_tls_size() + 15) & -16; |
| local.get 0 |
| .globaltype __tls_size, PTR, immutable |
| global.get __tls_size |
| PTR.add |
| PTR.const 0xf |
| PTR.add |
| PTR.const -0x10 |
| PTR.and |
| global.set __stack_end |
| |
| // __stack_base = stackLowestAddress + stackSize; |
| local.get 0 |
| local.get 1 |
| #ifdef __wasm64__ |
| i64.extend_i32_u |
| #endif |
| PTR.add |
| global.set __stack_base |
| |
| // TODO: We'd like to do this here to avoid JS side calls to __set_stack_limits. |
| // (or even better, we'd like to avoid duplicate versions of the stack variables) |
| // See https://github.com/emscripten-core/emscripten/issues/16496 |
| // global.get __stack_base |
| // global.get __stack_end |
| // .functype __set_stack_limits (PTR, PTR) -> () |
| // call __set_stack_limits |
| |
| // __wasm_init_tls(stackLowestAddress); |
| local.get 0 |
| .functype __wasm_init_tls (PTR) -> () |
| call __wasm_init_tls |
| |
| // N.b. The function __wasm_init_tls above does not need |
| // __stack_pointer initialized, and it destroys the value it was set to. |
| // So we must initialize __stack_pointer only *after* completing __wasm_init_tls: |
| |
| // __stack_pointer = __stack_base; |
| global.get __stack_base |
| global.set __stack_pointer |
| |
| end_function |
| #endif |
| |
| # Add emscripten_stack_init to static ctors |
| .section .init_array.1,"",@ |
| .p2align ALIGN |
| PTRSTORE emscripten_stack_init |