diff --git a/py/nlr.h b/py/nlr.h index ce62334fd43c5619f083521866957603af6b1631..4e931919dbbfb5e5eebe60b43c2cc442eb34f62f 100644 --- a/py/nlr.h +++ b/py/nlr.h @@ -27,6 +27,11 @@ unsigned int nlr_push(nlr_buf_t *); void nlr_pop(void); void nlr_jump(void *val) __attribute__((noreturn)); +// This must be implemented by a port. It's called by nlr_jump +// if no nlr buf has been pushed. It must not return, but rather +// should bail out with a fatal error. +void nlr_jump_fail(void *val); + // use nlr_raise instead of nlr_jump so that debugging is easier #ifndef DEBUG #define nlr_raise(val) nlr_jump(val) diff --git a/py/nlrthumb.S b/py/nlrthumb.S index 8c6eb95522fa8e2f5fe0f6167ec6196a73826a05..6a0c7ee1e1d99d61bc2bb3e0c8ec018a06643221 100644 --- a/py/nlrthumb.S +++ b/py/nlrthumb.S @@ -60,6 +60,8 @@ nlr_pop: nlr_jump: ldr r3, .L2 @ load addr of nlr_top ldr r2, [r3] @ load nlr_top + cmp r2, #0 @ test if nlr_top is NULL + beq nlr_jump_fail @ if nlr_top is NULL, transfer control to nlr_jump_fail str r0, [r2, #4] @ store return value ldr r0, [r2] @ load prev nlr_buf str r0, [r3] @ store prev nol_buf into nlr_top (to unlink list) diff --git a/py/nlrx64.S b/py/nlrx64.S index a4073981a58d56fb0b7a895410bfc19d7d7ef3e9..929a348caf23309b8191d2668b07c87e0a0d228d 100644 --- a/py/nlrx64.S +++ b/py/nlrx64.S @@ -61,6 +61,8 @@ nlr_jump: #endif movq %rdi, %rax # put return value in %rax movq nlr_top(%rip), %rdi # get nlr_top into %rdi + test %rdi, %rdi # check for nlr_top being NULL + je .fail # fail if nlr_top is NULL movq %rax, 8(%rdi) # store return value movq (%rdi), %rax # load prev nlr_buf movq %rax, nlr_top(%rip) # store prev nlr_buf (to unlink list) @@ -76,10 +78,14 @@ nlr_jump: xorq %rax, %rax # clear return register inc %al # increase to make 1, non-local return ret # return +.fail: + movq %rax, %rdi # put argument back in first-arg register + je nlr_jump_fail # transfer control to nlr_jump_fail #if !(defined(__APPLE__) && defined(__MACH__)) .size nlr_jump, .-nlr_jump #endif + .bss #if !(defined(__APPLE__) && defined(__MACH__)) .local nlr_top #endif @@ -107,12 +113,21 @@ nlr_push: xorq %rax, %rax # return 0, normal return ret # return -/* void nlr_jump(rcx=uint val) */ +/* void nlr_pop() */ + .globl nlr_pop +nlr_pop: + movq nlr_top(%rip), %rax # get nlr_top into %rax + movq (%rax), %rax # load prev nlr_buf + movq %rax, nlr_top(%rip) # store prev nlr_buf (to unlink list) + ret # return +/* void nlr_jump(rcx=uint val) */ .globl nlr_jump nlr_jump: movq %rcx, %rax # put return value in %rax - movq nlr_top(%rip), %rcx # get nlr_top into %rsi + movq nlr_top(%rip), %rcx # get nlr_top into %rcx + test %rcx, %rcx # check for nlr_top being NULL + je .fail # fail if nlr_top is NULL movq %rax, 8(%rcx) # store return value movq (%rcx), %rax # load prev nlr_buf movq %rax, nlr_top(%rip) # store prev nlr_buf (to unlink list) @@ -130,17 +145,13 @@ nlr_jump: xorq %rax, %rax # clear return register inc %al # increase to make 1, non-local return ret # return +.fail: + movq %rax, %rcx # put argument back in first-arg register + je nlr_jump_fail # transfer control to nlr_jump_fail + .bss .comm nlr_top,8,8 - /* void nlr_pop() */ - .globl nlr_pop -nlr_pop: - movq nlr_top(%rip), %rax # get nlr_top into %rax - movq (%rax), %rax # load prev nlr_buf - movq %rax, nlr_top(%rip) # store prev nlr_buf (to unlink list) - ret # return - #endif // !defined(__CYGWIN__) #endif // __x86_64__ diff --git a/py/nlrx86.S b/py/nlrx86.S index 5cfd4a8cfccb842543837c488d15450fc8be6fb5..003de5095fdf9fba341f886165632a2859381396 100644 --- a/py/nlrx86.S +++ b/py/nlrx86.S @@ -60,6 +60,8 @@ _nlr_jump: nlr_jump: #endif mov nlr_top, %edx # load nlr_top + test %edx, %edx # check for nlr_top being NULL + je nlr_jump_fail # fail if nlr_top is NULL mov 4(%esp), %eax # load return value mov %eax, 4(%edx) # store return value mov (%edx), %eax # load prev nlr_top @@ -78,6 +80,7 @@ nlr_jump: .size nlr_jump, .-nlr_jump #endif + .bss #ifndef _WIN32 .local nlr_top #endif diff --git a/stm/main.c b/stm/main.c index a11a813d2dadf5a4189cdf466ddaab126713e1df..636f900212957cef6f0920b3df0ee8bb46194db4 100644 --- a/stm/main.c +++ b/stm/main.c @@ -79,6 +79,11 @@ void __fatal_error(const char *msg) { } } +void nlr_jump_fail(void *val) { + printf("FATAL: uncaught exception %p\n", val); + __fatal_error(""); +} + STATIC mp_obj_t pyb_config_source_dir = MP_OBJ_NULL; STATIC mp_obj_t pyb_config_main = MP_OBJ_NULL; diff --git a/stmhal/main.c b/stmhal/main.c index 897271d14a8d9e418412fbdf65a7fe45c02a2274..e5ba67dc1d9af37a69de4a295dd45e05a79eefdb 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -73,6 +73,11 @@ void __fatal_error(const char *msg) { } } +void nlr_jump_fail(void *val) { + printf("FATAL: uncaught exception %p\n", val); + __fatal_error(""); +} + STATIC mp_obj_t pyb_config_source_dir = MP_OBJ_NULL; STATIC mp_obj_t pyb_config_main = MP_OBJ_NULL; STATIC mp_obj_t pyb_config_usb_mode = MP_OBJ_NULL; diff --git a/unix-cpy/main.c b/unix-cpy/main.c index 944d26e9f3ec060d03fb3b05b7a4d11f8a649b0c..6cdd72c5da8f78e5255b6f045a24735b7986292e 100644 --- a/unix-cpy/main.c +++ b/unix-cpy/main.c @@ -1,3 +1,4 @@ +#include <stdlib.h> #include <stdint.h> #include <stdio.h> #include <string.h> @@ -74,12 +75,11 @@ int main(int argc, char **argv) { return 0; } -// for sqrt -#include <math.h> -machine_float_t machine_sqrt(machine_float_t x) { - return sqrt(x); -} - mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } + +void nlr_jump_fail(void *val) { + printf("FATAL: uncaught NLR %p\n", val); + exit(1); +} diff --git a/unix/main.c b/unix/main.c index 11df4cadf29fe1da73045bd8727729bddbef8637..8065663011eb1a0c7a32ec55ee52b8bc75874bff 100644 --- a/unix/main.c +++ b/unix/main.c @@ -293,6 +293,7 @@ void pre_process_options(int argc, char **argv) { } int main(int argc, char **argv) { + nlr_jump(0); volatile int stack_dummy; stack_top = (void*)&stack_dummy; @@ -447,3 +448,8 @@ int DEBUG_printf(const char *fmt, ...) { va_end(ap); return ret; } + +void nlr_jump_fail(void *val) { + printf("FATAL: uncaught NLR %p\n", val); + exit(1); +}