summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-04-17 17:26:19 +0100
committerDamien George <damien.p.george@gmail.com>2014-04-17 17:26:19 +0100
commiteeffbb694809d6ee1434842bc234eb44714c25ac (patch)
tree1cf175198f43d4f099a362a575e0b845b5c69dc7
parent594d0ddbb2740996b460dd596f76fc21f092e9fc (diff)
parent3a83b805fcb759344ef7e4055f124d5eb989ac34 (diff)
downloadmicropython-eeffbb694809d6ee1434842bc234eb44714c25ac.tar.gz
micropython-eeffbb694809d6ee1434842bc234eb44714c25ac.zip
Merge pull request #507 from pfalcon/nlr-setjmp
nlr: Add implementation using setjmp/longjmp.
-rw-r--r--py/nlr.h20
-rw-r--r--py/nlrsetjmp.c16
-rw-r--r--py/py.mk1
3 files changed, 36 insertions, 1 deletions
diff --git a/py/nlr.h b/py/nlr.h
index 4e931919db..05fe63d22d 100644
--- a/py/nlr.h
+++ b/py/nlr.h
@@ -2,12 +2,14 @@
// exception handling, basically a stack of setjmp/longjmp buffers
#include <limits.h>
+#include <setjmp.h>
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;
+#if !MICROPY_NLR_SETJMP
#if defined(__i386__)
void *regs[6];
#elif defined(__x86_64__)
@@ -19,13 +21,29 @@ struct _nlr_buf_t {
#elif defined(__thumb2__)
void *regs[10];
#else
-#error Unknown arch in nlr.h
+ #define MICROPY_NLR_SETJMP (1)
+ #warning "No native NLR support for this arch, using setjmp implementation"
+#endif
+#endif
+
+#if MICROPY_NLR_SETJMP
+ jmp_buf jmpbuf;
#endif
};
+#if MICROPY_NLR_SETJMP
+extern nlr_buf_t *nlr_setjmp_top;
+void nlr_setjmp_jump(void *val) __attribute__((noreturn));
+// nlr_push() must be defined as a macro, because "The stack context will be
+// invalidated if the function which called setjmp() returns."
+#define nlr_push(buf) ((buf)->prev = nlr_setjmp_top, nlr_setjmp_top = (buf), setjmp((buf)->jmpbuf))
+#define nlr_pop() { nlr_setjmp_top = nlr_setjmp_top->prev; }
+#define nlr_jump(val) nlr_setjmp_jump(val)
+#else
unsigned int nlr_push(nlr_buf_t *);
void nlr_pop(void);
void nlr_jump(void *val) __attribute__((noreturn));
+#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
diff --git a/py/nlrsetjmp.c b/py/nlrsetjmp.c
new file mode 100644
index 0000000000..a97c8634b2
--- /dev/null
+++ b/py/nlrsetjmp.c
@@ -0,0 +1,16 @@
+#include <setjmp.h>
+#include <stdio.h>
+#include "nlr.h"
+
+#if MICROPY_NLR_SETJMP
+
+nlr_buf_t *nlr_setjmp_top;
+
+void nlr_setjmp_jump(void *val) {
+ nlr_buf_t *buf = nlr_setjmp_top;
+ nlr_setjmp_top = buf->prev;
+ buf->ret_val = val;
+ longjmp(buf->jmpbuf, 1);
+}
+
+#endif
diff --git a/py/py.mk b/py/py.mk
index 996cbee4e3..1bd536718e 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -10,6 +10,7 @@ PY_O_BASENAME = \
nlrx86.o \
nlrx64.o \
nlrthumb.o \
+ nlrsetjmp.o \
malloc.o \
gc.o \
qstr.o \