diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-03-28 11:04:51 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-03-28 11:04:51 +0000 |
commit | df4b504cae7856b864a073ab9e6e61cf2ad23a97 (patch) | |
tree | a923c8785a06871784c5177530130063c4925f5a /gcc/unwind-sjlj.c | |
parent | d3ab49408bd5b876d10076caea78dc81a5f85dd7 (diff) | |
download | gcc-df4b504cae7856b864a073ab9e6e61cf2ad23a97.tar.gz |
IA-64 ABI Exception Handling.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@40924 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/unwind-sjlj.c')
-rw-r--r-- | gcc/unwind-sjlj.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/gcc/unwind-sjlj.c b/gcc/unwind-sjlj.c new file mode 100644 index 00000000000..662968bd001 --- /dev/null +++ b/gcc/unwind-sjlj.c @@ -0,0 +1,259 @@ +/* DWARF2 exception handling and frame unwind runtime interface routines. + Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + This file is part of GNU CC. + + GNU CC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU CC; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "tconfig.h" +#include "tsystem.h" +#include "unwind.h" +#include "gthr.h" + +#if USING_SJLJ_EXCEPTIONS + +#ifdef DONT_USE_BUILTIN_SETJMP +#include <setjmp.h> +#else +#define setjmp __builtin_setjmp +#define longjmp __builtin_longjmp +#endif + +/* This structure is allocated on the stack of the target function. + This must match the definition created in except.c:init_eh. */ +struct SjLj_Function_Context +{ + /* This is the chain through all registered contexts. It is + filled in by _Unwind_SjLj_Register. */ + struct SjLj_Function_Context *prev; + + /* This is assigned in by the target function before every call + to the index of the call site in the lsda. It is assigned by + the personality routine to the landing pad index. */ + int call_site; + + /* This is how data is returned from the personality routine to + the target function's handler. */ + _Unwind_Word data[4]; + + /* These are filled in once by the target function before any + exceptions are expected to be handled. */ + _Unwind_Personality_Fn personality; + void *lsda; + +#ifdef DONT_USE_BUILTIN_SETJMP + /* We don't know what sort of alignment requirements the system + jmp_buf has. We over estimated in except.c, and now we have + to match that here just in case the system *didn't* have more + restrictive requirements. */ + jmp_buf jbuf __attribute__((aligned)); +#else + void *jbuf[]; +#endif +}; + +struct _Unwind_Context +{ + struct SjLj_Function_Context *fc; +}; + +typedef struct +{ + _Unwind_Personality_Fn personality; +} _Unwind_FrameState; + + +/* Manage the chain of registered function contexts. */ + +/* Single threaded fallback chain. */ +static struct SjLj_Function_Context *fc_static; + +#if __GTHREADS +static __gthread_key_t fc_key; +static int use_fc_key = -1; + +static void +fc_key_dtor (void *ptr) +{ + __gthread_key_dtor (fc_key, ptr); +} + +static void +fc_key_init (void) +{ + use_fc_key = __gthread_key_create (&fc_key, fc_key_dtor) == 0; +} + +static void +fc_key_init_once (void) +{ + static __gthread_once_t once = __GTHREAD_ONCE_INIT; + if (__gthread_once (&once, fc_key_init) != 0 || use_fc_key < 0) + use_fc_key = 0; +} +#endif + +void +_Unwind_SjLj_Register (struct SjLj_Function_Context *fc) +{ +#if __GTHREADS + if (use_fc_key < 0) + fc_key_init_once (); + + if (use_fc_key) + { + fc->prev = __gthread_getspecific (fc_key); + __gthread_setspecific (fc_key, fc); + } + else +#endif + { + fc->prev = fc_static; + fc_static = fc; + } +} + +static inline struct SjLj_Function_Context * +_Unwind_SjLj_GetContext (void) +{ +#if __GTHREADS + if (use_fc_key < 0) + fc_key_init_once (); + + if (use_fc_key) + return __gthread_getspecific (fc_key); +#endif + return fc_static; +} + +static inline void +_Unwind_SjLj_SetContext (struct SjLj_Function_Context *fc) +{ +#if __GTHREADS + if (use_fc_key < 0) + fc_key_init_once (); + + if (use_fc_key) + __gthread_setspecific (fc_key, fc); + else +#endif + fc_static = fc; +} + +void +_Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc) +{ + _Unwind_SjLj_SetContext (fc->prev); +} + + +/* Get/set the return data value at INDEX in CONTEXT. */ + +_Unwind_Word +_Unwind_GetGR (struct _Unwind_Context *context, int index) +{ + return context->fc->data[index]; +} + +void +_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val) +{ + context->fc->data[index] = val; +} + +/* Get the call-site index as saved in CONTEXT. */ + +_Unwind_Ptr +_Unwind_GetIP (struct _Unwind_Context *context) +{ + return context->fc->call_site + 1; +} + +/* Set the return landing pad index in CONTEXT. */ + +void +_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val) +{ + context->fc->call_site = val - 1; +} + +void * +_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context) +{ + return context->fc->lsda; +} + +_Unwind_Ptr +_Unwind_GetRegionStart (struct _Unwind_Context *context) +{ + return 0; +} + + +static inline _Unwind_Reason_Code +uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) +{ + if (context->fc == NULL) + { + fs->personality = NULL; + return _URC_END_OF_STACK; + } + else + { + fs->personality = context->fc->personality; + return _URC_NO_REASON; + } +} + +static inline void +uw_update_context (struct _Unwind_Context *context, + _Unwind_FrameState *fs __attribute__((unused)) ) +{ + context->fc = context->fc->prev; +} + +static inline void +uw_init_context (struct _Unwind_Context *context) +{ + context->fc = _Unwind_SjLj_GetContext (); +} + +/* ??? There appear to be bugs in integrate.c wrt __builtin_longjmp and + virtual-stack-vars. An inline version of this segfaults on Sparc. */ +#define uw_install_context(CURRENT, TARGET) \ + do { \ + _Unwind_SjLj_SetContext ((TARGET)->fc); \ + longjmp ((TARGET)->fc->jbuf, 1); \ + } while (0) + + +static inline _Unwind_Ptr +uw_identify_context (struct _Unwind_Context *context) +{ + return (_Unwind_Ptr) context->fc; +} + + +/* Play games with unwind symbols so that we can have call frame + and sjlj symbols in the same shared library. Not that you can + use them simultaneously... */ +#define _Unwind_RaiseException _Unwind_SjLj_RaiseException +#define _Unwind_ForcedUnwind _Unwind_SjLj_ForcedUnwind +#define _Unwind_Resume _Unwind_SjLj_Resume + +#include "unwind.inc" + +#endif /* USING_SJLJ_EXCEPTIONS */ |