summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2017-12-28 16:46:30 +1100
committerDamien George <damien.p.george@gmail.com>2017-12-28 16:46:30 +1100
commitb25f92160b318a096c516c430afde5472a944c19 (patch)
tree18022d1de245f9fca253f2a8076c4e8c79f6fca8
parent5bf8e85fc828974199d469db711aa2f9649c467b (diff)
py/nlr: Factor out common NLR code to macro and generic funcs in nlr.c.
Each NLR implementation (Thumb, x86, x64, xtensa, setjmp) duplicates a lot of the NLR code, specifically that dealing with pushing and popping the NLR pointer to maintain the linked-list of NLR buffers. This patch factors all of that code out of the specific implementations into generic functions in nlr.c, along with a helper macro in nlr.h. This eliminates duplicated code.
-rw-r--r--py/nlr.c51
-rw-r--r--py/nlr.h27
-rw-r--r--py/nlrsetjmp.c6
-rw-r--r--py/nlrthumb.c25
-rw-r--r--py/nlrx64.c23
-rw-r--r--py/nlrx86.c23
-rw-r--r--py/nlrxtensa.c23
-rw-r--r--py/py.mk1
8 files changed, 76 insertions, 103 deletions
diff --git a/py/nlr.c b/py/nlr.c
new file mode 100644
index 000000000..52d56afb8
--- /dev/null
+++ b/py/nlr.c
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2017 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/mpstate.h"
+
+#if !MICROPY_NLR_SETJMP
+// When not using setjmp, nlr_push_tail is called from inline asm so needs special c
+#if MICROPY_NLR_X86 && (defined(_WIN32) || defined(__CYGWIN__))
+// On these 32-bit platforms make sure nlr_push_tail doesn't have a leading undersco
+unsigned int nlr_push_tail(nlr_buf_t *nlr) asm("nlr_push_tail");
+#else
+// LTO can't see inside inline asm functions so explicitly mark nlr_push_tail as use
+__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr);
+#endif
+#endif
+
+unsigned int nlr_push_tail(nlr_buf_t *nlr) {
+ nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
+ nlr->prev = *top;
+ MP_NLR_SAVE_PYSTACK(nlr);
+ *top = nlr;
+ return 0; // normal return
+}
+
+void nlr_pop(void) {
+ nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
+ *top = (*top)->prev;
+}
diff --git a/py/nlr.h b/py/nlr.h
index bd9fcc884..e4dfa6896 100644
--- a/py/nlr.h
+++ b/py/nlr.h
@@ -88,24 +88,29 @@ struct _nlr_buf_t {
#define MP_NLR_RESTORE_PYSTACK(nlr_buf) (void)nlr_buf
#endif
-#if MICROPY_NLR_SETJMP
-#include "py/mpstate.h"
+// Helper macro to use at the start of a specific nlr_jump implementation
+#define MP_NLR_JUMP_HEAD(val, top) \
+ nlr_buf_t **_top_ptr = &MP_STATE_THREAD(nlr_top); \
+ nlr_buf_t *top = *_top_ptr; \
+ if (top == NULL) { \
+ nlr_jump_fail(val); \
+ } \
+ top->ret_val = val; \
+ MP_NLR_RESTORE_PYSTACK(top); \
+ *_top_ptr = top->prev; \
-NORETURN void nlr_setjmp_jump(void *val);
+#if MICROPY_NLR_SETJMP
// 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 = 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)
+// For this case it is safe to call nlr_push_tail() first.
+#define nlr_push(buf) (nlr_push_tail(buf), setjmp((buf)->jmpbuf))
#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);
-#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
index 63376a553..960dd86f5 100644
--- a/py/nlrsetjmp.c
+++ b/py/nlrsetjmp.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2013-2017 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,11 +24,11 @@
* THE SOFTWARE.
*/
-#include "py/nlr.h"
+#include "py/mpstate.h"
#if MICROPY_NLR_SETJMP
-void nlr_setjmp_jump(void *val) {
+void nlr_jump(void *val) {
nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
nlr_buf_t *top = *top_ptr;
if (top == NULL) {
diff --git a/py/nlrthumb.c b/py/nlrthumb.c
index cc081e3ff..fb0a92236 100644
--- a/py/nlrthumb.c
+++ b/py/nlrthumb.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013-2016 Damien P. George
+ * Copyright (c) 2013-2017 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -82,29 +82,8 @@ __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) {
#endif
}
-__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- nlr->prev = *top;
- MP_NLR_SAVE_PYSTACK(nlr);
- *top = nlr;
- return 0; // normal return
-}
-
-void nlr_pop(void) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- *top = (*top)->prev;
-}
-
NORETURN void nlr_jump(void *val) {
- nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
- nlr_buf_t *top = *top_ptr;
- if (top == NULL) {
- nlr_jump_fail(val);
- }
-
- top->ret_val = val;
- MP_NLR_RESTORE_PYSTACK(top);
- *top_ptr = top->prev;
+ MP_NLR_JUMP_HEAD(val, top)
__asm volatile (
"mov r0, %0 \n" // r0 points to nlr_buf
diff --git a/py/nlrx64.c b/py/nlrx64.c
index 927b21591..663a457b7 100644
--- a/py/nlrx64.c
+++ b/py/nlrx64.c
@@ -88,29 +88,8 @@ unsigned int nlr_push(nlr_buf_t *nlr) {
return 0; // needed to silence compiler warning
}
-__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- nlr->prev = *top;
- MP_NLR_SAVE_PYSTACK(nlr);
- *top = nlr;
- return 0; // normal return
-}
-
-void nlr_pop(void) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- *top = (*top)->prev;
-}
-
NORETURN void nlr_jump(void *val) {
- nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
- nlr_buf_t *top = *top_ptr;
- if (top == NULL) {
- nlr_jump_fail(val);
- }
-
- top->ret_val = val;
- MP_NLR_RESTORE_PYSTACK(top);
- *top_ptr = top->prev;
+ MP_NLR_JUMP_HEAD(val, top)
__asm volatile (
"movq %0, %%rcx \n" // %rcx points to nlr_buf
diff --git a/py/nlrx86.c b/py/nlrx86.c
index 0e03eef6f..9490c4f42 100644
--- a/py/nlrx86.c
+++ b/py/nlrx86.c
@@ -70,29 +70,8 @@ unsigned int nlr_push(nlr_buf_t *nlr) {
return 0; // needed to silence compiler warning
}
-__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- nlr->prev = *top;
- MP_NLR_SAVE_PYSTACK(nlr);
- *top = nlr;
- return 0; // normal return
-}
-
-void nlr_pop(void) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- *top = (*top)->prev;
-}
-
NORETURN void nlr_jump(void *val) {
- nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
- nlr_buf_t *top = *top_ptr;
- if (top == NULL) {
- nlr_jump_fail(val);
- }
-
- top->ret_val = val;
- MP_NLR_RESTORE_PYSTACK(top);
- *top_ptr = top->prev;
+ MP_NLR_JUMP_HEAD(val, top)
__asm volatile (
"mov %0, %%edx \n" // %edx points to nlr_buf
diff --git a/py/nlrxtensa.c b/py/nlrxtensa.c
index 73f14385d..cd3dee364 100644
--- a/py/nlrxtensa.c
+++ b/py/nlrxtensa.c
@@ -55,29 +55,8 @@ unsigned int nlr_push(nlr_buf_t *nlr) {
return 0; // needed to silence compiler warning
}
-__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- nlr->prev = *top;
- MP_NLR_SAVE_PYSTACK(nlr);
- *top = nlr;
- return 0; // normal return
-}
-
-void nlr_pop(void) {
- nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
- *top = (*top)->prev;
-}
-
NORETURN void nlr_jump(void *val) {
- nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
- nlr_buf_t *top = *top_ptr;
- if (top == NULL) {
- nlr_jump_fail(val);
- }
-
- top->ret_val = val;
- MP_NLR_RESTORE_PYSTACK(top);
- *top_ptr = top->prev;
+ MP_NLR_JUMP_HEAD(val, top)
__asm volatile (
"mov.n a2, %0 \n" // a2 points to nlr_buf
diff --git a/py/py.mk b/py/py.mk
index 0b5d5f8c4..de82a971b 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -103,6 +103,7 @@ endif
# py object files
PY_O_BASENAME = \
mpstate.o \
+ nlr.o \
nlrx86.o \
nlrx64.o \
nlrthumb.o \