OSDN Git Service

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