OSDN Git Service

Add fix test from irix_stdio_dummy_va_list
[pf3gnuchains/gcc-fork.git] / gcc / unwind-sjlj.c
1 /* DWARF2 exception handling and frame unwind runtime interface routines.
2    Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3
4    This file is part of GNU CC.
5
6    GNU CC is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    GNU CC is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GNU CC; see the file COPYING.  If not, write to
18    the Free Software Foundation, 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include "tconfig.h"
22 #include "tsystem.h"
23 #include "unwind.h"
24 #include "gthr.h"
25
26 #if USING_SJLJ_EXCEPTIONS
27
28 #ifdef DONT_USE_BUILTIN_SETJMP
29 #include <setjmp.h>
30 #else
31 #define setjmp __builtin_setjmp
32 #define longjmp __builtin_longjmp
33 #endif
34
35 /* This structure is allocated on the stack of the target function.
36    This must match the definition created in except.c:init_eh.  */
37 struct SjLj_Function_Context
38 {
39   /* This is the chain through all registered contexts.  It is
40      filled in by _Unwind_SjLj_Register.  */
41   struct SjLj_Function_Context *prev;
42
43   /* This is assigned in by the target function before every call
44      to the index of the call site in the lsda.  It is assigned by
45      the personality routine to the landing pad index.  */
46   int call_site;
47
48   /* This is how data is returned from the personality routine to
49      the target function's handler.  */
50   _Unwind_Word data[4];
51
52   /* These are filled in once by the target function before any
53      exceptions are expected to be handled.  */
54   _Unwind_Personality_Fn personality;
55   void *lsda;
56
57 #ifdef DONT_USE_BUILTIN_SETJMP
58   /* We don't know what sort of alignment requirements the system
59      jmp_buf has.  We over estimated in except.c, and now we have
60      to match that here just in case the system *didn't* have more 
61      restrictive requirements.  */
62   jmp_buf jbuf __attribute__((aligned));
63 #else
64   void *jbuf[];
65 #endif
66 };
67
68 struct _Unwind_Context
69 {
70   struct SjLj_Function_Context *fc;
71 };
72
73 typedef struct 
74 {
75   _Unwind_Personality_Fn personality;
76 } _Unwind_FrameState;
77
78 \f
79 /* Manage the chain of registered function contexts.  */
80
81 /* Single threaded fallback chain.  */
82 static struct SjLj_Function_Context *fc_static;
83
84 #if __GTHREADS
85 static __gthread_key_t fc_key;
86 static int use_fc_key = -1;
87
88 static void
89 fc_key_dtor (void *ptr)
90 {
91   __gthread_key_dtor (fc_key, ptr);
92 }
93
94 static void
95 fc_key_init (void)
96 {
97   use_fc_key = __gthread_key_create (&fc_key, fc_key_dtor) == 0;
98 }
99
100 static void
101 fc_key_init_once (void)
102 {
103   static __gthread_once_t once = __GTHREAD_ONCE_INIT;
104   if (__gthread_once (&once, fc_key_init) != 0 || use_fc_key < 0)
105     use_fc_key = 0;
106 }
107 #endif
108
109 void
110 _Unwind_SjLj_Register (struct SjLj_Function_Context *fc)
111 {
112 #if __GTHREADS
113   if (use_fc_key < 0)
114     fc_key_init_once ();
115
116   if (use_fc_key)
117     {
118       fc->prev = __gthread_getspecific (fc_key);
119       __gthread_setspecific (fc_key, fc);
120     }
121   else
122 #endif
123     {
124       fc->prev = fc_static;
125       fc_static = fc;
126     }
127 }
128
129 static inline struct SjLj_Function_Context *
130 _Unwind_SjLj_GetContext (void)
131 {
132 #if __GTHREADS
133   if (use_fc_key < 0)
134     fc_key_init_once ();
135
136   if (use_fc_key)
137     return __gthread_getspecific (fc_key);
138 #endif
139   return fc_static;
140 }
141
142 static inline void
143 _Unwind_SjLj_SetContext (struct SjLj_Function_Context *fc)
144 {
145 #if __GTHREADS
146   if (use_fc_key < 0)
147     fc_key_init_once ();
148
149   if (use_fc_key)
150     __gthread_setspecific (fc_key, fc);
151   else
152 #endif
153     fc_static = fc;
154 }
155
156 void
157 _Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc)
158 {
159   _Unwind_SjLj_SetContext (fc->prev);
160 }
161
162 \f
163 /* Get/set the return data value at INDEX in CONTEXT.  */
164
165 _Unwind_Word
166 _Unwind_GetGR (struct _Unwind_Context *context, int index)
167 {
168   return context->fc->data[index];
169 }
170
171 void
172 _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
173 {
174   context->fc->data[index] = val;
175 }
176
177 /* Get the call-site index as saved in CONTEXT.  */
178
179 _Unwind_Ptr
180 _Unwind_GetIP (struct _Unwind_Context *context)
181 {
182   return context->fc->call_site + 1;
183 }
184
185 /* Set the return landing pad index in CONTEXT.  */
186
187 void
188 _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
189 {
190   context->fc->call_site = val - 1;
191 }
192
193 void *
194 _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
195 {
196   return context->fc->lsda;
197 }
198
199 _Unwind_Ptr
200 _Unwind_GetRegionStart (struct _Unwind_Context *context)
201 {
202   return 0;
203 }
204
205 #ifndef __ia64__
206 _Unwind_Ptr
207 _Unwind_GetDataRelBase (struct _Unwind_Context *context)
208 {
209   return 0;
210 }
211
212 _Unwind_Ptr
213 _Unwind_GetTextRelBase (struct _Unwind_Context *context)
214 {
215   return 0;
216 }
217 #endif
218 \f
219 static inline _Unwind_Reason_Code
220 uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
221 {
222   if (context->fc == NULL)
223     {
224       fs->personality = NULL;
225       return _URC_END_OF_STACK;
226     }
227   else
228     {
229       fs->personality = context->fc->personality;
230       return _URC_NO_REASON;
231     }
232 }
233
234 static inline void
235 uw_update_context (struct _Unwind_Context *context,
236                    _Unwind_FrameState *fs __attribute__((unused)) )
237 {
238   context->fc = context->fc->prev;
239 }
240
241 static inline void 
242 uw_init_context (struct _Unwind_Context *context)
243 {
244   context->fc = _Unwind_SjLj_GetContext ();
245 }
246
247 /* ??? There appear to be bugs in integrate.c wrt __builtin_longjmp and
248    virtual-stack-vars.  An inline version of this segfaults on Sparc.  */
249 #define uw_install_context(CURRENT, TARGET)     \
250   do {                                          \
251     _Unwind_SjLj_SetContext ((TARGET)->fc);     \
252     longjmp ((TARGET)->fc->jbuf, 1);            \
253   } while (0)
254
255
256 static inline _Unwind_Ptr
257 uw_identify_context (struct _Unwind_Context *context)
258 {
259   return (_Unwind_Ptr) context->fc;
260 }
261
262
263 /* Play games with unwind symbols so that we can have call frame
264    and sjlj symbols in the same shared library.  Not that you can
265    use them simultaneously...  */
266 #define _Unwind_RaiseException          _Unwind_SjLj_RaiseException
267 #define _Unwind_ForcedUnwind            _Unwind_SjLj_ForcedUnwind
268 #define _Unwind_Resume                  _Unwind_SjLj_Resume
269
270 #include "unwind.inc"
271
272 #endif /* USING_SJLJ_EXCEPTIONS */