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).
Этот коммит содержится в:
Ayke van Laethem 2022-06-17 01:28:14 +02:00 коммит произвёл Ron Evans
родитель c119721e3b
коммит 49e22fe678
7 изменённых файлов: 24 добавлений и 19 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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
}
}