blob: 1171afa8174fc344d242a983380f356f26bd05c6 [file] [edit]
.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