]> git.lizzy.rs Git - rust.git/blob - src/rt/arch/x86_64/morestack.S
rt: Add lots of documentation to __morestack
[rust.git] / src / rt / arch / x86_64 / morestack.S
1 /*
2         __morestack
3
4         See i386/morestack.S for the lengthy, general explanation.
5 */
6
7 .text
8
9 #if defined(__APPLE__) || defined(_WIN32)
10 #define UPCALL_NEW_STACK        _upcall_new_stack
11 #define UPCALL_DEL_STACK        _upcall_del_stack
12 #define UPCALL_CALL_C           _upcall_call_shim_on_c_stack
13 #define MORESTACK               ___morestack
14 #else
15 #define UPCALL_NEW_STACK        upcall_new_stack
16 #define UPCALL_DEL_STACK        upcall_del_stack
17 #define UPCALL_CALL_C           upcall_call_shim_on_c_stack
18 #define MORESTACK               __morestack
19 #endif
20
21 .globl UPCALL_NEW_STACK
22 .globl UPCALL_DEL_STACK
23 .globl UPCALL_CALL_C
24 .globl MORESTACK
25
26 #if defined(__linux__)
27         .hidden MORESTACK
28 #else
29 #if defined(__APPLE__)
30         .private_extern MORESTACK
31 #endif
32 #endif
33
34 #ifdef __ELF__
35         .type MORESTACK,@function
36 #endif
37
38
39 #if defined(__linux__) || defined(__APPLE__)
40 MORESTACK:
41         .cfi_startproc
42
43         pushq %rbp
44         // The CFA is 24 bytes above the register that it will
45         // be associated with for this frame (%rbp). That is 8
46         // bytes greater than a normal frame, to allow the unwinder
47         // to skip the partial frame of the original function.
48         .cfi_def_cfa_offset 24
49         // %rbp is -24 bytes from the CFA
50         .cfi_offset %rbp, -24
51         movq %rsp, %rbp
52         // Calculate the CFA as on offset from %ebp
53         .cfi_def_cfa_register %rbp
54
55         // Save the grandparent stack pointer for the unwinder
56         // FIXME: This isn't used
57         leaq 24(%rbp), %rax
58         pushq %rax
59
60         // FIXME: libgcc also saves rax. not sure if we need to
61
62         // Save argument registers of the original function
63         pushq   %rdi
64         pushq   %rsi
65         pushq   %rdx
66         pushq   %rcx
67         pushq   %r8
68         pushq   %r9
69
70         // Calculate the address of the stack arguments.
71         // We have the base pointer, __morestack's return address,
72         // and __morestack's caller's return address to skip
73         movq %rbp, %rcx
74         addq $24, %rcx  // Base pointer, return address x2
75
76         // The arguments to __morestack are passed in %r10 & %r11
77
78         pushq %r11 // Size of stack arguments
79         pushq %rcx // Address of stack arguments
80         pushq %r10 // The amount of stack needed
81         pushq $0   // Out pointer
82
83         movq UPCALL_NEW_STACK@GOTPCREL(%rip), %rsi
84         movq %rsp, %rdi
85 #ifdef __APPLE__
86         call UPCALL_CALL_C
87 #endif
88 #ifdef __linux__
89         call UPCALL_CALL_C@PLT
90 #endif
91
92         // Pop the new_stack_args struct
93         popq %rax
94         addq $24, %rsp
95
96         // Pop the saved arguments
97         popq %r9
98         popq %r8
99         popq %rcx
100         popq %rdx
101         popq %rsi
102         popq %rdi
103
104         // Pop the unwinding %rsp
105         addq $8, %rsp
106
107         movq 8(%rbp),%r10       // Grab the return pointer.
108         incq %r10               // Skip past the `ret` in our parent frame
109         movq %rax,%rsp          // Switch to the new stack.
110
111         call *%r10              // Reenter the caller function
112
113         // Switch back to the rust stack
114         movq %rbp, %rsp
115
116         // Align the stack again
117         pushq $0
118
119         // FIXME: Should preserve %rax here
120         movq UPCALL_DEL_STACK@GOTPCREL(%rip), %rsi
121         movq $0, %rdi
122 #ifdef __APPLE__
123         call UPCALL_CALL_C
124 #endif
125 #ifdef __linux__
126         call UPCALL_CALL_C@PLT
127 #endif
128
129         addq $8, %rsp
130         popq %rbp
131         // FIXME: I don't think these rules are necessary
132         // since the unwinder should never encounter an instruction
133         // pointer pointing here.
134         .cfi_restore %rbp
135         .cfi_def_cfa %rsp, 16
136         ret
137         
138         .cfi_endproc
139
140 #else
141 MORESTACK:
142         ret
143 #endif