- .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
- .cfi_def_cfa_offset 16
- .cfi_offset %rbp, -16
- movq %rsp, %rbp
- .cfi_def_cfa_register %rbp
-
- // During unwinding we want to skip our caller since it's not
- // a complete frame and will make the unwinder sad
- // Don't understand this line
- .cfi_offset 16, 0
- // Tell the unwinding where to get the stack pointer for
- // our grandparent frame
- .cfi_offset %rsp, -24
-
- // Save the grandparent stack pointer for the unwinder
- leaq 16(%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
+ 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
- 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, 8
- ret
-
.cfi_endproc
-
-#else
-MORESTACK:
- ret
-#endif
\ No newline at end of file