Colin Hogben / micropython

Dependents:   micropython-repl

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers nlr.h Source File

nlr.h

00001 /*
00002  * This file is part of the Micro Python project, http://micropython.org/
00003  *
00004  * The MIT License (MIT)
00005  *
00006  * Copyright (c) 2013, 2014 Damien P. George
00007  *
00008  * Permission is hereby granted, free of charge, to any person obtaining a copy
00009  * of this software and associated documentation files (the "Software"), to deal
00010  * in the Software without restriction, including without limitation the rights
00011  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00012  * copies of the Software, and to permit persons to whom the Software is
00013  * furnished to do so, subject to the following conditions:
00014  *
00015  * The above copyright notice and this permission notice shall be included in
00016  * all copies or substantial portions of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00019  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00020  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00021  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00022  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00023  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00024  * THE SOFTWARE.
00025  */
00026 #ifndef __MICROPY_INCLUDED_PY_NLR_H__
00027 #define __MICROPY_INCLUDED_PY_NLR_H__
00028 
00029 // non-local return
00030 // exception handling, basically a stack of setjmp/longjmp buffers
00031 
00032 #include <limits.h>
00033 #include <setjmp.h>
00034 #include <assert.h>
00035 
00036 #include "py/mpconfig.h"
00037 
00038 typedef struct _nlr_buf_t nlr_buf_t;
00039 struct _nlr_buf_t {
00040     // the entries here must all be machine word size
00041     nlr_buf_t *prev;
00042     void *ret_val; // always a concrete object (an exception instance)
00043 #if !defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP
00044 #if defined(__i386__)
00045     void *regs[6];
00046 #elif defined(__x86_64__)
00047   #if defined(__CYGWIN__)
00048     void *regs[12];
00049   #else
00050     void *regs[8];
00051   #endif
00052 #elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__)
00053     void *regs[10];
00054 #elif defined(__xtensa__)
00055     void *regs[10];
00056 #else
00057     #define MICROPY_NLR_SETJMP (1)
00058     //#warning "No native NLR support for this arch, using setjmp implementation"
00059 #endif
00060 #endif
00061 
00062 #if MICROPY_NLR_SETJMP
00063     jmp_buf jmpbuf;
00064 #endif
00065 };
00066 
00067 #if MICROPY_NLR_SETJMP
00068 #include "py/mpstate.h"
00069 
00070 NORETURN void nlr_setjmp_jump(void *val);
00071 // nlr_push() must be defined as a macro, because "The stack context will be
00072 // invalidated if the function which called setjmp() returns."
00073 #define nlr_push(buf) ((buf)->prev = MP_STATE_VM(nlr_top), MP_STATE_VM(nlr_top) = (buf), setjmp((buf)->jmpbuf))
00074 #define nlr_pop() { MP_STATE_VM(nlr_top) = MP_STATE_VM(nlr_top)->prev; }
00075 #define nlr_jump(val) nlr_setjmp_jump(val)
00076 #else
00077 unsigned int nlr_push(nlr_buf_t *);
00078 void nlr_pop(void);
00079 NORETURN void nlr_jump(void *val);
00080 #endif
00081 
00082 // This must be implemented by a port.  It's called by nlr_jump
00083 // if no nlr buf has been pushed.  It must not return, but rather
00084 // should bail out with a fatal error.
00085 void nlr_jump_fail(void *val);
00086 
00087 // use nlr_raise instead of nlr_jump so that debugging is easier
00088 #ifndef DEBUG
00089 #define nlr_raise(val) nlr_jump(MP_OBJ_TO_PTR(val))
00090 #else
00091 #include "mpstate.h"
00092 #define nlr_raise(val) \
00093     do { \
00094         /*printf("nlr_raise: nlr_top=%p\n", MP_STATE_VM(nlr_top)); \
00095         fflush(stdout);*/ \
00096         void *_val = MP_OBJ_TO_PTR(val); \
00097         assert(_val != NULL); \
00098         assert(mp_obj_is_exception_instance(val)); \
00099         nlr_jump(_val); \
00100     } while (0)
00101 
00102 #if !MICROPY_NLR_SETJMP
00103 #define nlr_push(val) \
00104     assert(MP_STATE_VM(nlr_top) != val),nlr_push(val)
00105 
00106 /*
00107 #define nlr_push(val) \
00108     printf("nlr_push: before: nlr_top=%p, val=%p\n", MP_STATE_VM(nlr_top), val),assert(MP_STATE_VM(nlr_top) != val),nlr_push(val)
00109 #endif
00110 */
00111 #endif
00112 
00113 #endif
00114 
00115 #endif // __MICROPY_INCLUDED_PY_NLR_H__