blob: c7b5928430af34e10be30d47fe764d86afb6ec95 [file] [log] [blame]
Damience89a212013-10-15 22:25:17 +01001// non-local return
2// exception handling, basically a stack of setjmp/longjmp buffers
3
4#include <limits.h>
Paul Sokolovsky3a83b802014-04-17 00:16:45 +03005#include <setjmp.h>
Paul Sokolovskye9085912014-04-30 05:35:18 +03006#include "mpconfig.h"
Damience89a212013-10-15 22:25:17 +01007
Damience89a212013-10-15 22:25:17 +01008typedef struct _nlr_buf_t nlr_buf_t;
9struct _nlr_buf_t {
10 // the entries here must all be machine word size
11 nlr_buf_t *prev;
12 void *ret_val;
Paul Sokolovsky3a83b802014-04-17 00:16:45 +030013#if !MICROPY_NLR_SETJMP
Paul Sokolovsky82a165d2014-02-27 18:01:43 +020014#if defined(__i386__)
Damience89a212013-10-15 22:25:17 +010015 void *regs[6];
Paul Sokolovsky82a165d2014-02-27 18:01:43 +020016#elif defined(__x86_64__)
Damien George4b34c762014-04-03 23:51:16 +010017 #if defined(__CYGWIN__)
18 void *regs[12];
19 #else
Damience89a212013-10-15 22:25:17 +010020 void *regs[8];
Damien George4b34c762014-04-03 23:51:16 +010021 #endif
Paul Sokolovsky82a165d2014-02-27 18:01:43 +020022#elif defined(__thumb2__)
Damien152568b2013-10-16 00:46:39 +010023 void *regs[10];
Paul Sokolovsky82a165d2014-02-27 18:01:43 +020024#else
Paul Sokolovsky3a83b802014-04-17 00:16:45 +030025 #define MICROPY_NLR_SETJMP (1)
Paul Sokolovsky851c8562014-04-30 04:14:31 +030026 //#warning "No native NLR support for this arch, using setjmp implementation"
Paul Sokolovsky3a83b802014-04-17 00:16:45 +030027#endif
28#endif
29
30#if MICROPY_NLR_SETJMP
31 jmp_buf jmpbuf;
Damience89a212013-10-15 22:25:17 +010032#endif
33};
34
Paul Sokolovsky3a83b802014-04-17 00:16:45 +030035#if MICROPY_NLR_SETJMP
36extern nlr_buf_t *nlr_setjmp_top;
Paul Sokolovskye9085912014-04-30 05:35:18 +030037NORETURN void nlr_setjmp_jump(void *val);
Paul Sokolovsky3a83b802014-04-17 00:16:45 +030038// nlr_push() must be defined as a macro, because "The stack context will be
39// invalidated if the function which called setjmp() returns."
40#define nlr_push(buf) ((buf)->prev = nlr_setjmp_top, nlr_setjmp_top = (buf), setjmp((buf)->jmpbuf))
41#define nlr_pop() { nlr_setjmp_top = nlr_setjmp_top->prev; }
42#define nlr_jump(val) nlr_setjmp_jump(val)
43#else
Damience89a212013-10-15 22:25:17 +010044unsigned int nlr_push(nlr_buf_t *);
Damien8b3a7c22013-10-23 20:20:17 +010045void nlr_pop(void);
Paul Sokolovskye9085912014-04-30 05:35:18 +030046NORETURN void nlr_jump(void *val);
Paul Sokolovsky3a83b802014-04-17 00:16:45 +030047#endif
Damien Georgeea13f402014-04-05 18:32:08 +010048
Damien George26cf55a2014-04-08 14:08:14 +000049// This must be implemented by a port. It's called by nlr_jump
50// if no nlr buf has been pushed. It must not return, but rather
51// should bail out with a fatal error.
52void nlr_jump_fail(void *val);
53
Damien Georgeea13f402014-04-05 18:32:08 +010054// use nlr_raise instead of nlr_jump so that debugging is easier
55#ifndef DEBUG
56#define nlr_raise(val) nlr_jump(val)
57#else
58#define nlr_raise(val) \
59 do { \
60 void *_val = val; \
61 assert(_val != NULL); \
62 assert(mp_obj_is_exception_instance(_val)); \
63 nlr_jump(_val); \
64 } while (0)
65#endif