summaryrefslogtreecommitdiff
path: root/py/nlr.h
diff options
context:
space:
mode:
Diffstat (limited to 'py/nlr.h')
-rw-r--r--py/nlr.h71
1 files changed, 37 insertions, 34 deletions
diff --git a/py/nlr.h b/py/nlr.h
index 012a73c31..1235f1460 100644
--- a/py/nlr.h
+++ b/py/nlr.h
@@ -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