OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [unwind.inc] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Exception handling and frame unwind runtime interface routines. -*- C -*-
2
   Copyright (C) 2001, 2003 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
   In addition to the permissions in the GNU General Public License, the
12
   Free Software Foundation gives you unlimited permission to link the
13
   compiled version of this file into combinations with other programs,
14
   and to distribute those combinations without any restriction coming
15
   from the use of this file.  (The General Public License restrictions
16
   do apply in other respects; for example, they cover modification of
17
   the file, and distribution when not linked into a combined
18
   executable.)
19
 
20
   GCC is distributed in the hope that it will be useful, but WITHOUT
21
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
23
   License for more details.
24
 
25
   You should have received a copy of the GNU General Public License
26
   along with GCC; see the file COPYING.  If not, write to the Free
27
   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
28
   02110-1301, USA.  */
29
 
30
/* This is derived from the C++ ABI for IA-64.  Where we diverge
31
   for cross-architecture compatibility are noted with "@@@".
32
   This file is included from unwind-dw2.c or unwind-ia64.c.  */
33
 
34
/* Subroutine of _Unwind_RaiseException also invoked from _Unwind_Resume.
35
 
36
   Unwind the stack calling the personality routine to find both the
37
   exception handler and intermediary cleanup code.  We'll only locate
38
   the first such frame here.  Cleanup code will call back into
39
   _Unwind_Resume and we'll continue Phase 2 there.  */
40
 
41
static _Unwind_Reason_Code
42
_Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc,
43
                              struct _Unwind_Context *context)
44
{
45
  _Unwind_Reason_Code code;
46
 
47
  while (1)
48
    {
49
      _Unwind_FrameState fs;
50
      int match_handler;
51
 
52
      code = uw_frame_state_for (context, &fs);
53
 
54
      /* Identify when we've reached the designated handler context.  */
55
      match_handler = (uw_identify_context (context) == exc->private_2
56
                       ? _UA_HANDLER_FRAME : 0);
57
 
58
      if (code != _URC_NO_REASON)
59
        /* Some error encountered.  Usually the unwinder doesn't
60
           diagnose these and merely crashes.  */
61
        return _URC_FATAL_PHASE2_ERROR;
62
 
63
      /* Unwind successful.  Run the personality routine, if any.  */
64
      if (fs.personality)
65
        {
66
          code = (*fs.personality) (1, _UA_CLEANUP_PHASE | match_handler,
67
                                    exc->exception_class, exc, context);
68
          if (code == _URC_INSTALL_CONTEXT)
69
            break;
70
          if (code != _URC_CONTINUE_UNWIND)
71
            return _URC_FATAL_PHASE2_ERROR;
72
        }
73
 
74
      /* Don't let us unwind past the handler context.  */
75
      gcc_assert (!match_handler);
76
 
77
      uw_update_context (context, &fs);
78
    }
79
 
80
  return code;
81
}
82
 
83
/* Raise an exception, passing along the given exception object.  */
84
 
85
_Unwind_Reason_Code
86
_Unwind_RaiseException(struct _Unwind_Exception *exc)
87
{
88
  struct _Unwind_Context this_context, cur_context;
89
  _Unwind_Reason_Code code;
90
 
91
  /* Set up this_context to describe the current stack frame.  */
92
  uw_init_context (&this_context);
93
  cur_context = this_context;
94
 
95
  /* Phase 1: Search.  Unwind the stack, calling the personality routine
96
     with the _UA_SEARCH_PHASE flag set.  Do not modify the stack yet.  */
97
  while (1)
98
    {
99
      _Unwind_FrameState fs;
100
 
101
      /* Set up fs to describe the FDE for the caller of cur_context.  The
102
         first time through the loop, that means __cxa_throw.  */
103
      code = uw_frame_state_for (&cur_context, &fs);
104
 
105
      if (code == _URC_END_OF_STACK)
106
        /* Hit end of stack with no handler found.  */
107
        return _URC_END_OF_STACK;
108
 
109
      if (code != _URC_NO_REASON)
110
        /* Some error encountered.  Ususally the unwinder doesn't
111
           diagnose these and merely crashes.  */
112
        return _URC_FATAL_PHASE1_ERROR;
113
 
114
      /* Unwind successful.  Run the personality routine, if any.  */
115
      if (fs.personality)
116
        {
117
          code = (*fs.personality) (1, _UA_SEARCH_PHASE, exc->exception_class,
118
                                    exc, &cur_context);
119
          if (code == _URC_HANDLER_FOUND)
120
            break;
121
          else if (code != _URC_CONTINUE_UNWIND)
122
            return _URC_FATAL_PHASE1_ERROR;
123
        }
124
 
125
      /* Update cur_context to describe the same frame as fs.  */
126
      uw_update_context (&cur_context, &fs);
127
    }
128
 
129
  /* Indicate to _Unwind_Resume and associated subroutines that this
130
     is not a forced unwind.  Further, note where we found a handler.  */
131
  exc->private_1 = 0;
132
  exc->private_2 = uw_identify_context (&cur_context);
133
 
134
  cur_context = this_context;
135
  code = _Unwind_RaiseException_Phase2 (exc, &cur_context);
136
  if (code != _URC_INSTALL_CONTEXT)
137
    return code;
138
 
139
  uw_install_context (&this_context, &cur_context);
140
}
141
 
142
 
143
/* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume.  */
144
 
145
static _Unwind_Reason_Code
146
_Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc,
147
                             struct _Unwind_Context *context)
148
{
149
  _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1;
150
  void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2;
151
  _Unwind_Reason_Code code, stop_code;
152
 
153
  while (1)
154
    {
155
      _Unwind_FrameState fs;
156
      int action;
157
 
158
      /* Set up fs to describe the FDE for the caller of cur_context.  */
159
      code = uw_frame_state_for (context, &fs);
160
      if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
161
        return _URC_FATAL_PHASE2_ERROR;
162
 
163
      /* Unwind successful.  */
164
      action = _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE;
165
      if (code == _URC_END_OF_STACK)
166
        action |= _UA_END_OF_STACK;
167
      stop_code = (*stop) (1, action, exc->exception_class, exc,
168
                           context, stop_argument);
169
      if (stop_code != _URC_NO_REASON)
170
        return _URC_FATAL_PHASE2_ERROR;
171
 
172
      /* Stop didn't want to do anything.  Invoke the personality
173
         handler, if applicable, to run cleanups.  */
174
      if (code == _URC_END_OF_STACK)
175
        break;
176
 
177
      if (fs.personality)
178
        {
179
          code = (*fs.personality) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE,
180
                                    exc->exception_class, exc, context);
181
          if (code == _URC_INSTALL_CONTEXT)
182
            break;
183
          if (code != _URC_CONTINUE_UNWIND)
184
            return _URC_FATAL_PHASE2_ERROR;
185
        }
186
 
187
      /* Update cur_context to describe the same frame as fs, and discard
188
         the previous context if necessary.  */
189
      uw_advance_context (context, &fs);
190
    }
191
 
192
  return code;
193
}
194
 
195
 
196
/* Raise an exception for forced unwinding.  */
197
 
198
_Unwind_Reason_Code
199
_Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
200
                      _Unwind_Stop_Fn stop, void * stop_argument)
201
{
202
  struct _Unwind_Context this_context, cur_context;
203
  _Unwind_Reason_Code code;
204
 
205
  uw_init_context (&this_context);
206
  cur_context = this_context;
207
 
208
  exc->private_1 = (_Unwind_Ptr) stop;
209
  exc->private_2 = (_Unwind_Ptr) stop_argument;
210
 
211
  code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
212
  if (code != _URC_INSTALL_CONTEXT)
213
    return code;
214
 
215
  uw_install_context (&this_context, &cur_context);
216
}
217
 
218
 
219
/* Resume propagation of an existing exception.  This is used after
220
   e.g. executing cleanup code, and not to implement rethrowing.  */
221
 
222
void
223
_Unwind_Resume (struct _Unwind_Exception *exc)
224
{
225
  struct _Unwind_Context this_context, cur_context;
226
  _Unwind_Reason_Code code;
227
 
228
  uw_init_context (&this_context);
229
  cur_context = this_context;
230
 
231
  /* Choose between continuing to process _Unwind_RaiseException
232
     or _Unwind_ForcedUnwind.  */
233
  if (exc->private_1 == 0)
234
    code = _Unwind_RaiseException_Phase2 (exc, &cur_context);
235
  else
236
    code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
237
 
238
  gcc_assert (code == _URC_INSTALL_CONTEXT);
239
 
240
  uw_install_context (&this_context, &cur_context);
241
}
242
 
243
 
244
/* Resume propagation of an FORCE_UNWIND exception, or to rethrow
245
   a normal exception that was handled.  */
246
 
247
_Unwind_Reason_Code
248
_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
249
{
250
  struct _Unwind_Context this_context, cur_context;
251
  _Unwind_Reason_Code code;
252
 
253
  /* Choose between continuing to process _Unwind_RaiseException
254
     or _Unwind_ForcedUnwind.  */
255
  if (exc->private_1 == 0)
256
    return _Unwind_RaiseException (exc);
257
 
258
  uw_init_context (&this_context);
259
  cur_context = this_context;
260
 
261
  code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
262
 
263
  gcc_assert (code == _URC_INSTALL_CONTEXT);
264
 
265
  uw_install_context (&this_context, &cur_context);
266
}
267
 
268
 
269
/* A convenience function that calls the exception_cleanup field.  */
270
 
271
void
272
_Unwind_DeleteException (struct _Unwind_Exception *exc)
273
{
274
  if (exc->exception_cleanup)
275
    (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
276
}
277
 
278
 
279
/* Perform stack backtrace through unwind data.  */
280
 
281
_Unwind_Reason_Code
282
_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument)
283
{
284
  struct _Unwind_Context context;
285
  _Unwind_Reason_Code code;
286
 
287
  uw_init_context (&context);
288
 
289
  while (1)
290
    {
291
      _Unwind_FrameState fs;
292
 
293
      /* Set up fs to describe the FDE for the caller of context.  */
294
      code = uw_frame_state_for (&context, &fs);
295
      if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
296
        return _URC_FATAL_PHASE1_ERROR;
297
 
298
      /* Call trace function.  */
299
      if ((*trace) (&context, trace_argument) != _URC_NO_REASON)
300
        return _URC_FATAL_PHASE1_ERROR;
301
 
302
      /* We're done at end of stack.  */
303
      if (code == _URC_END_OF_STACK)
304
        break;
305
 
306
      /* Update context to describe the same frame as fs.  */
307
      uw_update_context (&context, &fs);
308
    }
309
 
310
  return code;
311
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.