]> git.lizzy.rs Git - rust.git/blob - src/rt/arch/x86_64/morestack.S
rt: Remove the stack pointer field of stk_seg
[rust.git] / src / rt / arch / x86_64 / morestack.S
1     .text
2
3 // __morestack
4 //
5 // LLVM generates a call to this to allocate more stack space in a functiono
6 // prolog when we run out.
7
8 #if defined(__APPLE__) || defined(_WIN32)
9 #define RUST_NEW_STACK2     _rust_new_stack2
10 #define RUST_DEL_STACK      _rust_del_stack
11 #define RUST_DEL_STACK      _rust_del_stack
12 #define UPCALL_CALL_C       _upcall_call_shim_on_c_stack
13 #define MORESTACK           ___morestack
14 #else
15 #define RUST_NEW_STACK2     rust_new_stack2
16 #define RUST_DEL_STACK      rust_del_stack
17 #define RUST_DEL_STACK      rust_del_stack
18 #define UPCALL_CALL_C       upcall_call_shim_on_c_stack
19 #define MORESTACK           __morestack
20 #endif
21
22         // Naturally, nobody can agree as to
23         // which arguments should go in which
24         // registers:
25 #if defined(_WIN32)
26 #  define ARG0 %rcx
27 #  define ARG1 %rdx
28 #  define ARG2 %r8
29 #else
30 #  define ARG0 %rdi
31 #  define ARG1 %rsi
32 #  define ARG2 %rdx
33 #endif
34
35 .globl RUST_NEW_STACK2
36 .globl RUST_DEL_STACK
37 .globl UPCALL_CALL_C
38 .globl MORESTACK
39
40 // FIXME: What about _WIN32?    
41 #if defined(__linux__)
42         .hidden MORESTACK
43 #else
44 #if defined(__APPLE__)
45         .private_extern MORESTACK
46 #endif
47 #endif
48
49 #ifdef __ELF__
50         .type MORESTACK,@function
51 #endif
52
53 #if defined(__linux__)
54 MORESTACK:
55         .cfi_startproc
56
57         # Set up a normal backtrace
58         pushq %rbp
59         .cfi_def_cfa_offset 16
60         .cfi_offset %rbp, -16
61         movq %rsp, %rbp
62         .cfi_def_cfa_register %rbp
63
64         // FIXME: libgcc also saves rax. not sure if we need to
65
66         // Save argument registers
67         pushq   %rdi
68         pushq   %rsi
69         pushq   %rdx
70         pushq   %rcx
71         pushq   %r8
72         pushq   %r9
73
74         // Calculate the address of the stack arguments.
75         // We have the base pointer, __morestack's return address,
76         // and __morestack's caller's return address to skip
77         movq %rbp, %rcx
78         addq $24, %rcx  // Base pointer, return address x2
79
80         pushq %r11 // Size of stack arguments
81         pushq %rcx // Address of stack arguments
82         pushq %r10 // The amount of stack needed
83
84         leaq RUST_NEW_STACK2@PLT(%rip), %rsi
85         movq %rsp, %rdi
86         call UPCALL_CALL_C@PLT
87
88         // Pop the new_stack_args struct
89         addq $24, %rsp
90
91         // Pop the saved arguments
92         popq %r9
93         popq %r8
94         popq %rcx
95         popq %rdx
96         popq %rsi
97         popq %rdi
98         
99         movq 8(%rbp),%r10       // Grab the return pointer.
100         incq %r10               // Skip past the `ret` in our parent frame
101         movq %rax,%rsp          // Switch to the new stack.
102
103         call *%r10              // Reenter the caller function
104
105         // Switch back to the rust stack
106         movq %rbp, %rsp
107
108         // Align the stack again
109         pushq $0
110         
111         leaq RUST_DEL_STACK@PLT(%rip), %rsi
112         movq $0, %rdi
113         call UPCALL_CALL_C@PLT
114
115         addq $8, %rsp
116         popq %rbp
117         ret
118         
119         .cfi_endproc
120 #else
121 MORESTACK:
122         ret
123 #endif