diff --git a/src/runtime/asm_386.S b/src/runtime/asm_386.S index 1854be6a..faaa7c3a 100644 --- a/src/runtime/asm_386.S +++ b/src/runtime/asm_386.S @@ -28,6 +28,7 @@ tinygo_scanCurrentStack: tinygo_longjmp: // Note: the code we jump to assumes eax is set to a non-zero value if we // jump from here. - movl 8(%esp), %eax // jumpPC (stash in volatile register) - movl 4(%esp), %esp // jumpSP + movl 4(%esp), %eax + movl 0(%eax), %esp // jumpSP + movl 4(%eax), %eax // jumpPC (stash in volatile register) jmpl *%eax diff --git a/src/runtime/asm_amd64.S b/src/runtime/asm_amd64.S index 2168a6f4..79f26ff5 100644 --- a/src/runtime/asm_amd64.S +++ b/src/runtime/asm_amd64.S @@ -37,11 +37,11 @@ tinygo_longjmp: .global _tinygo_longjmp _tinygo_longjmp: #endif - // Note: the code we jump to assumes rax is non-zero so we have to load it - // with some value here. - movq $1, %rax - movq %rdi, %rsp // jumpSP - jmpq *%rsi // jumpPC + // Note: the code we jump to assumes rax is set to a non-zero value if we + // jump from here, so we use rax as the temporary value for jumpPC. + movq 0(%rdi), %rsp // jumpSP + movq 8(%rdi), %rax // jumpPC + jmpq *%rax #ifdef __MACH__ // Darwin diff --git a/src/runtime/asm_amd64_windows.S b/src/runtime/asm_amd64_windows.S index 2e717baf..19052397 100644 --- a/src/runtime/asm_amd64_windows.S +++ b/src/runtime/asm_amd64_windows.S @@ -24,8 +24,8 @@ tinygo_scanCurrentStack: .section .text.tinygo_longjmp,"ax" .global tinygo_longjmp tinygo_longjmp: - // Note: the code we jump to assumes rax is non-zero so we have to load it - // with some value here. - movq $1, %rax - movq %rcx, %rsp // jumpSP - jmpq *%rdx // jumpPC + // Note: the code we jump to assumes rax is set to a non-zero value if we + // jump from here, so we use rax as the temporary value for jumpPC. + movq 0(%rcx), %rsp // jumpSP + movq 8(%rcx), %rax // jumpPC + jmpq *%rax diff --git a/src/runtime/asm_arm.S b/src/runtime/asm_arm.S index d1de455c..a0077b92 100644 --- a/src/runtime/asm_arm.S +++ b/src/runtime/asm_arm.S @@ -40,6 +40,8 @@ tinygo_longjmp: .cfi_startproc // Note: the code we jump to assumes r0 is set to a non-zero value if we // jump from here (which is conveniently already the case). + + ldm r0, {r0, r1} mov sp, r0 // jumpSP mov pc, r1 // jumpPC .cfi_endproc diff --git a/src/runtime/asm_arm64.S b/src/runtime/asm_arm64.S index 1eb26e8b..679f55fa 100644 --- a/src/runtime/asm_arm64.S +++ b/src/runtime/asm_arm64.S @@ -43,5 +43,6 @@ tinygo_longjmp: #endif // Note: the code we jump to assumes x0 is set to a non-zero value if we // jump from here (which is conveniently already the case). - mov sp, x0 // jumpSP - br x1 // jumpPC + ldp x1, x2, [x0] // jumpSP, jumpPC + mov sp, x1 + br x2 diff --git a/src/runtime/asm_riscv.S b/src/runtime/asm_riscv.S index 9a99fbc4..c028d6d5 100644 --- a/src/runtime/asm_riscv.S +++ b/src/runtime/asm_riscv.S @@ -46,6 +46,7 @@ tinygo_scanCurrentStack: .global tinygo_longjmp tinygo_longjmp: // Note: the code we jump to assumes a0 is non-zero, which is already the - // case because that's jumpSP (the stack pointer). - mv sp, a0 // jumpSP - jr a1 // jumpPC + // case because that's the defer frame pointer. + lw sp, 0(a0) // jumpSP + lw a1, REGSIZE(a0) // jumpPC + jr a1 diff --git a/src/runtime/panic.go b/src/runtime/panic.go index dda9e9a9..143f53df 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -13,7 +13,7 @@ func trap() // Inline assembly stub. It is essentially C longjmp but modified a bit for the // purposes of TinyGo. It restores the stack pointer and jumps to the given pc. //export tinygo_longjmp -func tinygo_longjmp(sp, pc unsafe.Pointer) +func tinygo_longjmp(frame *task.DeferFrame) // Compiler intrinsic. // Returns whether recover is supported on the current architecture. @@ -26,7 +26,7 @@ func _panic(message interface{}) { if frame != nil { frame.PanicValue = message frame.Panicking = true - tinygo_longjmp(frame.JumpSP, frame.JumpPC) + tinygo_longjmp(frame) // unreachable } }