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