1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
.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
.section .globals,"",@
# 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:
.section .text,"",@
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
|