-
Notifications
You must be signed in to change notification settings - Fork 3.3k
/
stack_limits.S
137 lines (117 loc) · 3.51 KB
/
stack_limits.S
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
.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 () -> ()
# The heap base is where the stack grown down from.
#ifdef __PIC__
global.get __heap_base@GOT
#else
PTR.const __heap_base
#endif
global.set __stack_base
# The end of stack data is the limit of the stack growth
#ifdef __PIC__
global.get __data_end@GOT
#else
PTR.const __data_end
#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
#ifdef __wasm64__
i64.extend_i32_u
#endif
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