]> git.lizzy.rs Git - rust.git/blobdiff - src/rt/arch/x86_64/morestack.S
auto merge of #15999 : Kimundi/rust/fix_folder, r=nikomatsakis
[rust.git] / src / rt / arch / x86_64 / morestack.S
index 5378a1dcc60fcef095aceab6aa5438e6c90c1c26..c82da57c12847af48603e9bbc1660d0a57a4e36f 100644 (file)
@@ -1,42 +1,27 @@
-    .text
+// Mark stack as non-executable
+#if defined(__linux__) && defined(__ELF__)
+.section       .note.GNU-stack, "", @progbits
+#endif
+
+/* See i386/morestack.S for the lengthy, general explanation. */
 
-// __morestack
-//
-// LLVM generates a call to this to allocate more stack space in a functiono
-// prolog when we run out.
+.text
 
-#if defined(__APPLE__) || defined(_WIN32)
-#define UPCALL_NEW_STACK        _upcall_new_stack
-#define UPCALL_DEL_STACK        _upcall_del_stack
-#define UPCALL_CALL_C           _upcall_call_shim_on_c_stack
+#if defined(__APPLE__)
 #define MORESTACK               ___morestack
 #else
-#define UPCALL_NEW_STACK        upcall_new_stack
-#define UPCALL_DEL_STACK        upcall_del_stack
-#define UPCALL_CALL_C           upcall_call_shim_on_c_stack
 #define MORESTACK               __morestack
 #endif
 
-        // Naturally, nobody can agree as to
-        // which arguments should go in which
-        // registers:
-#if defined(_WIN32)
-#  define ARG0 %rcx
-#  define ARG1 %rdx
-#  define ARG2 %r8
+#if defined(__APPLE__)
+#define EXHAUSTED               _rust_stack_exhausted
+#elif defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
+#define EXHAUSTED               rust_stack_exhausted@PLT
 #else
-#  define ARG0 %rdi
-#  define ARG1 %rsi
-#  define ARG2 %rdx
+#define EXHAUSTED               rust_stack_exhausted
 #endif
 
-.globl UPCALL_NEW_STACK
-.globl UPCALL_DEL_STACK
-.globl UPCALL_CALL_C
-.globl MORESTACK
-
-// FIXME: What about _WIN32?   
-#if defined(__linux__)
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
        .hidden MORESTACK
 #else
 #if defined(__APPLE__)
        .type MORESTACK,@function
 #endif
 
-#if defined(__linux__) || defined(__APPLE__)
+.globl MORESTACK
 MORESTACK:
        .cfi_startproc
-       
-       // Set up a normal backtrace
+
        pushq %rbp
+       // The CFA is 24 bytes above the register that it will
+       // be associated with for this frame (%rbp). That is 8
+       // bytes greater than a normal frame, to allow the unwinder
+       // to skip the partial frame of the original function.
        .cfi_def_cfa_offset 24
-       .cfi_offset %rbp, -24
-       movq %rsp, %rbp
-       .cfi_def_cfa_register %rbp
-
-       // Save the grandparent stack pointer for the unwinder
-       leaq 24(%rbp), %rax
-       pushq %rax
-
-       // FIXME: libgcc also saves rax. not sure if we need to
-
-       // Save argument registers
-       pushq   %rdi
-       pushq   %rsi
-       pushq   %rdx
-       pushq   %rcx
-       pushq   %r8
-       pushq   %r9
-
-       // Calculate the address of the stack arguments.
-       // We have the base pointer, __morestack's return address,
-       // and __morestack's caller's return address to skip
-       movq %rbp, %rcx
-       addq $24, %rcx  // Base pointer, return address x2
 
-       pushq %r11 // Size of stack arguments
-       pushq %rcx // Address of stack arguments
-       pushq %r10 // The amount of stack needed
-       pushq $0   // Out pointer
-
-       movq UPCALL_NEW_STACK@GOTPCREL(%rip), %rsi
-       movq %rsp, %rdi
-#ifdef __APPLE__
-       call UPCALL_CALL_C
-#endif
-#ifdef __linux__
-       call UPCALL_CALL_C@PLT
+#if defined(__APPLE__)
+       // The pattern of the return address being saved twice to the same location
+       // tells the OS X linker that it should not attempt to convert the DWARF
+       // unwind information to the compact format.
+       .cfi_offset %rip, -8
+       .cfi_offset %rip, -8
 #endif
 
-       // Pop the new_stack_args struct
-       popq %rax
-       addq $24, %rsp
-
-       // Pop the saved arguments
-       popq %r9
-       popq %r8
-       popq %rcx
-       popq %rdx
-       popq %rsi
-       popq %rdi
-
-       // Pop the unwinding %rsp
-       addq $8, %rsp
-
-        movq 8(%rbp),%r10       // Grab the return pointer.
-        incq %r10               // Skip past the `ret` in our parent frame
-        movq %rax,%rsp          // Switch to the new stack.
+       // %rbp is -24 bytes from the CFA
+       .cfi_offset %rbp, -24
+       movq %rsp, %rbp
+       // Calculate the CFA as on offset from %ebp
+       .cfi_def_cfa_register %rbp
 
-        call *%r10              // Reenter the caller function
+        // re-align the stack
+        subq $8, %rsp
 
-       // Switch back to the rust stack
-       movq %rbp, %rsp
+        // kill this program
+        call EXHAUSTED
 
-       // Align the stack again
-       pushq $0
-       
-       movq UPCALL_DEL_STACK@GOTPCREL(%rip), %rsi
-       movq $0, %rdi
-#ifdef __APPLE__
-       call UPCALL_CALL_C
-#endif
-#ifdef __linux__
-       call UPCALL_CALL_C@PLT
-#endif
+        // the exhaustion function guarantees that it can't return
 
-       addq $8, %rsp
-       popq %rbp
-       .cfi_restore %rbp
-       .cfi_def_cfa %rsp, 16
-       ret
-       
        .cfi_endproc
-
-#else
-MORESTACK:
-       ret
-#endif