From 49e22fe6788aada2582f36fc219b0c47cf92c616 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Fri, 17 Jun 2022 01:28:14 +0200 Subject: [PATCH] runtime: load sp and pc inside tinygo_longjmp This is a small change to make it easier to support architectures that need to restore more than just the sp and pc registers. In particular, it is needed for the AVR architecture that needs to restore the frame pointer (Y register). --- src/runtime/asm_386.S | 5 +++-- src/runtime/asm_amd64.S | 10 +++++----- src/runtime/asm_amd64_windows.S | 10 +++++----- src/runtime/asm_arm.S | 2 ++ src/runtime/asm_arm64.S | 5 +++-- src/runtime/asm_riscv.S | 7 ++++--- src/runtime/panic.go | 4 ++-- 7 files changed, 24 insertions(+), 19 deletions(-) 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 } }