github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/internal/task/task_stack_amd64.S (about)

     1  #ifdef __MACH__ // Darwin
     2  .global  _tinygo_startTask
     3  _tinygo_startTask:
     4  #else // Linux etc
     5  .section .text.tinygo_startTask
     6  .global  tinygo_startTask
     7  tinygo_startTask:
     8  #endif
     9      .cfi_startproc
    10      // Small assembly stub for starting a goroutine. This is already run on the
    11      // new stack, with the callee-saved registers already loaded.
    12      // Most importantly, r12 contain the pc of the to-be-started function and
    13      // r13 contain the only argument it is given. Multiple arguments are packed
    14      // into one by storing them in a new allocation.
    15  
    16      // Indicate to the unwinder that there is nothing to unwind, this is the
    17      // root frame. It avoids bogus extra frames in GDB like here:
    18      //     #10 0x00000000004277b6 in <goroutine wrapper> () at [...]
    19      //     #11 0x00000000004278f3 in tinygo_startTask () at [...]
    20      //     #12 0x0000000000002030 in ?? ()
    21      //     #13 0x0000000000000071 in ?? ()
    22      .cfi_undefined rip
    23  
    24      // Set the first argument of the goroutine start wrapper, which contains all
    25      // the arguments.
    26      movq %r13, %rdi
    27  
    28      // Branch to the "goroutine start" function.
    29      callq *%r12
    30  
    31      // After return, exit this goroutine. This is a tail call.
    32      #ifdef __MACH__
    33      jmp _tinygo_pause
    34      #else
    35      jmp tinygo_pause
    36      #endif
    37      .cfi_endproc
    38  
    39  #ifdef __MACH__ // Darwin
    40  .global _tinygo_swapTask
    41  _tinygo_swapTask:
    42  #else // Linux etc
    43  .global tinygo_swapTask
    44  .section .text.tinygo_swapTask
    45  tinygo_swapTask:
    46  #endif
    47      // This function gets the following parameters:
    48      // %rdi = newStack uintptr
    49      // %rsi = oldStack *uintptr
    50  
    51      // Save all callee-saved registers:
    52      pushq %r15
    53      pushq %r14
    54      pushq %r13
    55      pushq %r12
    56      pushq %rbp
    57      pushq %rbx
    58  
    59      // Save the current stack pointer in oldStack.
    60      movq %rsp, (%rsi)
    61  
    62      // Switch to the new stack pointer.
    63      movq %rdi, %rsp
    64  
    65      // Load saved register from the new stack.
    66      popq %rbx
    67      popq %rbp
    68      popq %r12
    69      popq %r13
    70      popq %r14
    71      popq %r15
    72  
    73      // Return into the new task, as if tinygo_swapTask was a regular call.
    74      ret
    75  
    76  #ifdef __MACH__ // Darwin
    77  // allow these symbols to stripped as dead code
    78  .subsections_via_symbols
    79  #endif