diff options
Diffstat (limited to 'py/nlr.h')
| -rw-r--r-- | py/nlr.h | 71 |
1 files changed, 37 insertions, 34 deletions
@@ -30,29 +30,29 @@ // exception handling, basically a stack of setjmp/longjmp buffers #include <limits.h> +#include <setjmp.h> #include <assert.h> #include "py/mpconfig.h" -// If MICROPY_NLR_SETJMP is not enabled then auto-detect the machine arch -// Allow a port to set MICROPY_NLR_NUM_REGS to define their own implementation -#if !MICROPY_NLR_SETJMP && !defined(MICROPY_NLR_NUM_REGS) +typedef struct _nlr_buf_t nlr_buf_t; +struct _nlr_buf_t { + // the entries here must all be machine word size + nlr_buf_t *prev; + void *ret_val; // always a concrete object (an exception instance) +#if !defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP #if defined(__i386__) - #define MICROPY_NLR_X86 (1) - #define MICROPY_NLR_NUM_REGS (6) + void *regs[6]; #elif defined(__x86_64__) - #define MICROPY_NLR_X64 (1) - #if defined(__CYGWIN__) - #define MICROPY_NLR_NUM_REGS (12) - #else - #define MICROPY_NLR_NUM_REGS (8) - #endif + #if defined(__CYGWIN__) + void *regs[12]; + #else + void *regs[8]; + #endif #elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__) - #define MICROPY_NLR_THUMB (1) - #define MICROPY_NLR_NUM_REGS (10) + void *regs[10]; #elif defined(__xtensa__) - #define MICROPY_NLR_XTENSA (1) - #define MICROPY_NLR_NUM_REGS (10) + void *regs[10]; #else #define MICROPY_NLR_SETJMP (1) //#warning "No native NLR support for this arch, using setjmp implementation" @@ -60,39 +60,41 @@ #endif #if MICROPY_NLR_SETJMP -#include <setjmp.h> -#endif - -typedef struct _nlr_buf_t nlr_buf_t; -struct _nlr_buf_t { - // the entries here must all be machine word size - nlr_buf_t *prev; - void *ret_val; // always a concrete object (an exception instance) - - #if MICROPY_NLR_SETJMP jmp_buf jmpbuf; - #else - void *regs[MICROPY_NLR_NUM_REGS]; - #endif +#endif #if MICROPY_ENABLE_PYSTACK void *pystack; #endif }; +// Helper macros to save/restore the pystack state +#if MICROPY_ENABLE_PYSTACK +#define MP_NLR_SAVE_PYSTACK(nlr_buf) (nlr_buf)->pystack = MP_STATE_THREAD(pystack_cur) +#define MP_NLR_RESTORE_PYSTACK(nlr_buf) MP_STATE_THREAD(pystack_cur) = (nlr_buf)->pystack +#else +#define MP_NLR_SAVE_PYSTACK(nlr_buf) (void)nlr_buf +#define MP_NLR_RESTORE_PYSTACK(nlr_buf) (void)nlr_buf +#endif + #if MICROPY_NLR_SETJMP +#include "py/mpstate.h" + +NORETURN void nlr_setjmp_jump(void *val); // nlr_push() must be defined as a macro, because "The stack context will be // invalidated if the function which called setjmp() returns." -// For this case it is safe to call nlr_push_tail() first. -#define nlr_push(buf) (nlr_push_tail(buf), setjmp((buf)->jmpbuf)) +#define nlr_push(buf) ( \ + (buf)->prev = MP_STATE_THREAD(nlr_top), \ + MP_NLR_SAVE_PYSTACK(buf), \ + MP_STATE_THREAD(nlr_top) = (buf), \ + setjmp((buf)->jmpbuf)) +#define nlr_pop() { MP_STATE_THREAD(nlr_top) = MP_STATE_THREAD(nlr_top)->prev; } +#define nlr_jump(val) nlr_setjmp_jump(val) #else unsigned int nlr_push(nlr_buf_t *); -#endif - -unsigned int nlr_push_tail(nlr_buf_t *top); void nlr_pop(void); NORETURN void nlr_jump(void *val); -NORETURN void nlr_jump_tail(nlr_buf_t *top); +#endif // 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 @@ -121,6 +123,7 @@ NORETURN void nlr_jump_fail(void *val); /* #define nlr_push(val) \ printf("nlr_push: before: nlr_top=%p, val=%p\n", MP_STATE_THREAD(nlr_top), val),assert(MP_STATE_THREAD(nlr_top) != val),nlr_push(val) +#endif */ #endif |
