#include "tconfig.h"
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
#include "unwind.h"
#include "gthr.h"
#ifdef __USING_SJLJ_EXCEPTIONS__
#ifdef DONT_USE_BUILTIN_SETJMP
#ifndef inhibit_libc
#include <setjmp.h>
#else
typedef void *jmp_buf[JMP_BUF_SIZE];
extern void longjmp(jmp_buf, int) __attribute__((noreturn));
#endif
#else
#define setjmp __builtin_setjmp
#define longjmp __builtin_longjmp
#endif
struct SjLj_Function_Context
{
struct SjLj_Function_Context *prev;
int call_site;
_Unwind_Word data[4];
_Unwind_Personality_Fn personality;
void *lsda;
#ifdef DONT_USE_BUILTIN_SETJMP
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;
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_init (void)
{
use_fc_key = __gthread_key_create (&fc_key, 0) == 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);
}
_Unwind_Word
_Unwind_GetGR (struct _Unwind_Context *context, int index)
{
return context->fc->data[index];
}
_Unwind_Word
_Unwind_GetCFA (struct _Unwind_Context *context __attribute__((unused)))
{
return (_Unwind_Word) 0;
}
void
_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
{
context->fc->data[index] = val;
}
_Unwind_Ptr
_Unwind_GetIP (struct _Unwind_Context *context)
{
return context->fc->call_site + 1;
}
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 __attribute__((unused)) )
{
return 0;
}
void *
_Unwind_FindEnclosingFunction (void *pc __attribute__((unused)))
{
return NULL;
}
#ifndef __ia64__
_Unwind_Ptr
_Unwind_GetDataRelBase (struct _Unwind_Context *context __attribute__((unused)) )
{
return 0;
}
_Unwind_Ptr
_Unwind_GetTextRelBase (struct _Unwind_Context *context __attribute__((unused)) )
{
return 0;
}
#endif
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 ();
}
static void __attribute__((noreturn))
uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
struct _Unwind_Context *target)
{
_Unwind_SjLj_SetContext (target->fc);
longjmp (target->fc->jbuf, 1);
}
static inline _Unwind_Ptr
uw_identify_context (struct _Unwind_Context *context)
{
return (_Unwind_Ptr) context->fc;
}
#define _Unwind_RaiseException _Unwind_SjLj_RaiseException
#define _Unwind_ForcedUnwind _Unwind_SjLj_ForcedUnwind
#define _Unwind_Resume _Unwind_SjLj_Resume
#define _Unwind_Resume_or_Rethrow _Unwind_SjLj_Resume_or_Rethrow
#include "unwind.inc"
#endif