Added package with the documentation and the examples
[lwc.git] / except.c
blob87090e289fd166fd5bee7f700b4dd969247e1ec3
1 #include "global.h"
3 static Token longjmp_stack_t, unwind_t, longjmp_base;
4 static Token longjmp_ctx_top;
5 static Token longjmp_ctx;
7 void init_except ()
9 longjmp_stack_t = new_symbol ("longjmp_StaCk");
10 unwind_t = new_symbol ("AuToDt_t");
11 longjmp_ctx_top = new_symbol ("longjmp_StaCkTop");
12 longjmp_ctx = new_symbol ("longjmp_CoNtExT");
13 longjmp_base = new_symbol ("longjmp_iNiTObjFaKe");
16 static char _lwcbuiltin_estack [] =
17 "static inline void *__lwcbuiltin_get_estack ()\n"
18 "{\n"
19 " return longjmp_StaCkTop;\n"
20 "}\n"
21 "static inline void __lwcbuiltin_set_estack (void *v)\n"
22 "{\n"
23 " longjmp_StaCkTop = v;\n"
24 "}\n";
26 static char _Unwind_gcc [] =
27 " /*"COLS"*** gcc unwind internals ***"COLE"*/\n"
28 " static _Unwind_Reason_Code"
29 " ThRoW_sToP ( )"
30 " {"
31 " return _URC_NO_REASON ;"
32 " }"
34 " void __lwc_unwind (void*) __attribute__ ((noreturn, noinline));"
35 " void __lwc_unwind ( void *i )"
36 " {"
37 " struct _Unwind_Exception * exc = malloc ( sizeof * exc ) ;"
38 " exc -> exception_class = 0 ;"
39 " exc -> exception_cleanup = 0 ;"
40 " longjmp_StaCkTop -> X = i ;"
41 " longjmp_StaCkTop -> i = exc ;"
42 #ifndef __USING_SJLJ_EXCEPTIONS__
43 " _Unwind_ForcedUnwind ( exc , ThRoW_sToP, 0 ) ;"
44 #else
45 " _Unwind_SjLj_ForcedUnwind ( exc , ThRoW_sToP , 0 ) ;"
46 #endif
47 " \n/* did you forget -fexceptions ? */ * ( int * ) 0 = 0 ;"
48 " __lwc_unwind (i);"
49 "} \n"
50 " void __lwc_landingpad ( int * i ) "
51 " {"
52 " if ( ! * i ) "
53 " longjmp ( * longjmp_StaCkTop -> x , 1 ) ;"
54 " }";
56 #define IFEH if (EHUnwind) {
57 #define IFNEH if (!EHUnwind) {
58 #define ELSE } else {
59 #define ENDIF }
61 void decl_except_data ()
63 outprintf (INCLUDE, include_sys_header_s ("setjmp.h"), -1);
64 IFEH // include <unwind.h>
65 outprintf (INCLUDE, include_sys_header_s ("unwind.h"), -1);
66 ENDIF
68 IFNEH // declare manual unwind accounting
69 outprintf (STRUCTS,
70 RESERVED_struct, unwind_t, '{',
71 RESERVED_const, RESERVED_struct, unwind_t, '*', RESERVED_X, ';',
72 RESERVED_void, '*', RESERVED_x, ';',
73 RESERVED_void, '*', '(', '*' , RESERVED_y, ')', '(', RESERVED_void, '*', ')', ';',
74 '}', ';', -1);
75 ENDIF
77 outprintf (STRUCTS,
78 RESERVED_struct, longjmp_stack_t, '{',
79 RESERVED_jmp_buf, '*', RESERVED_x, ';',
80 RESERVED_struct, longjmp_stack_t, '*', RESERVED_y, ';',
81 RESERVED_void, '*', RESERVED_X, ';', -1);
82 IFEH // cleanup eh mess
83 outprintf (STRUCTS, RESERVED_void, '*', RESERVED_i, ';', -1);
84 ELSE // accounting member
85 outprintf (STRUCTS, RESERVED_const, RESERVED_struct, unwind_t, '*', RESERVED_i, ';', -1);
86 ENDIF
87 outprintf (STRUCTS, '}', ';', -1);
89 if (MainModule)
90 outprintf (GVARS, Reentrant ? RESERVED___thread : BLANKT,
91 RESERVED_struct, longjmp_stack_t, longjmp_base, ',', '*',
92 RESERVED___restrict, longjmp_ctx_top, '=', '&', longjmp_base, ';', -1);
93 else
94 outprintf (GVARS, RESERVED_extern,
95 Reentrant ? RESERVED___thread : BLANKT,
96 RESERVED_struct, longjmp_stack_t, '*', longjmp_ctx_top, ';', -1);
98 #define EHTOP longjmp_ctx_top, POINTSAT
99 #define ADTOP EHTOP, RESERVED_i
100 if (!MainModule) {
101 outprintf (GVARS, RESERVED_extern, RESERVED_void, RESERVED___lwc_unwind,
102 '(', RESERVED_void, '*', ')', -1);
103 #ifdef HAVE_GNUC_ATTR_NORETURN
104 outprintf (GVARS, RESERVED___attribute__, '(', '(',RESERVED_noreturn,')', ')', -1);
105 #endif
106 output_itoken (GVARS, ';');
107 IFEH // landing pad prototype
108 outprintf (GVARS, RESERVED_extern, RESERVED_void, RESERVED___lwc_landingpad,
109 '(', RESERVED_int, '*', ')', ';', -1);
110 ENDIF
111 } else
112 if (!EHUnwind)
113 outprintf (GVARS, RESERVED_void, RESERVED___lwc_unwind, '(', RESERVED_void, '*',')',
114 RESERVED___attribute__, '(', '(', RESERVED_noreturn, ')', ')', ';',
115 RESERVED_void, RESERVED___lwc_unwind, '(', RESERVED_void, '*',
116 RESERVED_X, ')', '{',
117 EHTOP, RESERVED_X, '=', RESERVED_X, ';',
118 RESERVED_while, '(', ADTOP, ')', '{',
119 ADTOP, POINTSAT, RESERVED_y, '(', ADTOP, POINTSAT, RESERVED_x, ')', ';',
120 ADTOP, '=', ADTOP, POINTSAT, RESERVED_X, ';', '}',
121 RESERVED_longjmp, '(', '*',
122 EHTOP, RESERVED_x, ',', RESERVED_1, ')', ';', '}', -1);
123 else output_itoken (GVARS, new_symbol (_Unwind_gcc));
124 if (!EHUnwind)
125 outprintf (GVARS, new_symbol (_lwcbuiltin_estack), -1);
129 /* member 'r' is normally a recID, but if a symbol, it's
130 the name of the custom dtor function. Useful for arrdtor */
131 #define DTOR_OF(x) ISSYMBOL(x) ? x : dtor_name (x)
133 bool did_unwind;
135 void push_unwind (OUTSTREAM o, recID r, Token arg)
137 if (EHUnwind) return;
138 did_unwind = true;
139 #define NOWARNONTYPE '(', RESERVED___typeof__, '(', u, '.', RESERVED_y, ')', ')'
140 Token u = name_unwind_var (arg);
141 outprintf (o, UWMARK, RESERVED_const, RESERVED_struct, unwind_t, u, '=', '{',
142 '.', RESERVED_X, '=', ADTOP, ',',
143 '.', RESERVED_x, '=', '&', arg, ',',
144 '.', RESERVED_y, '=', NOWARNONTYPE, DTOR_OF (r), ',',
145 '}', ';', ADTOP, '=', '&', u, ';', UWMARK, -1);
148 void pop_unwind (OUTSTREAM o)
150 if (EHUnwind) return;
151 outprintf (o, UWMARK, ADTOP, '=', ADTOP, POINTSAT, RESERVED_X, ';', UWMARK, -1);
154 void remove_unwind_stuff (Token *str)
156 int i, j, k;
157 for (i = 0; str [i] != -1;)
158 if (str [i] == UWMARK) {
159 for (j = i + 1; str [j] != UWMARK; j++);
160 for (k = i, j += 1;;)
161 if ((str [k++] = str [j++]) == -1)
162 break;
163 } else i++;
166 void leave_escope (OUTSTREAM o)
168 IFEH
169 outprintf (o, internal_identifier3 (), '=', RESERVED_1, ';', -1);
170 ENDIF
171 outprintf (o, longjmp_ctx_top, '=', longjmp_ctx_top, POINTSAT, RESERVED_y, ';', -1);
174 NormPtr throw_statement (OUTSTREAM o, NormPtr p)
176 may_throw = true;
178 outprintf (o, RESERVED___lwc_unwind, '(', -1);
180 if (CODE [p] == ';')
181 output_itoken (o, RESERVED_0);
182 else {
183 exprret E;
184 p = parse_expression_retconv (p, &E, typeID_voidP, NORMAL_EXPR);
185 if (!E.ok) return p + 1;
186 outprintf (o, ISTR (E.newExpr), -1);
188 free (E.newExpr);
189 if (CODE [p] != ';')
190 parse_error (p, "excepted ';' after throw expression");
193 outprintf (o, ')', ';', -1);
195 return p + 1;
198 NormPtr try_statement (OUTSTREAM o, NormPtr p)
200 Token x = RESERVED_x;
201 Token y = RESERVED_y;
202 Token X = RESERVED_X;
203 Token i = RESERVED_i;
204 Token ii = internal_identifier2 ();
205 Token i3 = internal_identifier3 ();
206 Token retcode = 0;
207 bool have_retcode;
209 outprintf (o, '{', RESERVED_struct, longjmp_stack_t, longjmp_ctx, ';', -1);
211 if (have_retcode = CODE [p] == '(') {
212 NormPtr p2;
213 p = skip_parenthesis (p2 = p + 1) - 1;
214 CODE [p] = ';';
215 open_local_scope ();
216 local_declaration (o, p2);
217 CODE [p++] = ')';
218 retcode = recent_obj ();
221 outprintf (o, RESERVED_jmp_buf, ii, ';', longjmp_ctx, '.', x, '=', '&', ii, ';',
222 longjmp_ctx, '.', y, '=', longjmp_ctx_top, ';', longjmp_ctx_top,
223 '=', '&', longjmp_ctx, ';', longjmp_ctx, '.', X, '=', RESERVED_0, ';', -1);
225 IFNEH // init manual accounting
226 outprintf (o, longjmp_ctx, '.', RESERVED_i, '=', RESERVED_0, ';', -1);
227 ENDIF
228 outprintf (o,
229 RESERVED_if, '(', '!', '(', RESERVED_setjmp, '(', ii, ')', ')',
230 ')', '{', -1);
232 IFEH // cleanup with landing pad
233 outprintf (o, RESERVED_int, i3, cleanup_func (RESERVED___lwc_landingpad),
234 '=', RESERVED_0, ';', -1);
235 ENDIF
237 SAVE_VAR (may_throw, may_throw);
238 int pos = get_stream_pos (o);
239 p = statement (o, p);
240 nowipeout_unwind (o, pos);
241 RESTOR_VAR (may_throw);
243 IFEH // mark landing pad normal termination
244 outprintf (o, i3, '=', RESERVED_1, ';', -1);
245 ENDIF
246 outprintf (o, longjmp_ctx_top, '=', longjmp_ctx, '.', y, ';', '}', -1);
248 outprintf (o, RESERVED_else, '{', -1);
249 if (have_retcode)
250 outprintf (o, retcode, '=', longjmp_ctx, '.', RESERVED_X, ';', -1);
251 IFEH // cleanup eh mess
252 outprintf (o, RESERVED_free, '(', longjmp_ctx, '.', i, ')', ';', -1);
253 ENDIF
254 outprintf (o, longjmp_ctx_top, '=', longjmp_ctx, '.', y, ';', -1);
255 if (CODE [p] == RESERVED_else)
256 p = statement (o, p + 1);
257 output_itoken (o, '}');
259 output_itoken (o, '}');
261 if (have_retcode) close_local_scope ();
263 return p;
266 NormPtr on_throw_statement (OUTSTREAM o, NormPtr p)
268 Token x = RESERVED_x;
269 Token y = RESERVED_y;
270 Token X = RESERVED_X;
271 Token ii = internal_identifier2 ();
272 Token i3 = internal_identifier3 ();
273 Token retcode = 0;
274 bool have_retcode;
276 // the exception handler is removed when the scope closes
277 add_auto_destruction (LEAVE_ESCOPE, -1, 0);
279 outprintf (o, RESERVED_struct, longjmp_stack_t, longjmp_ctx, ';', -1);
281 if (have_retcode = CODE [p] == '(') {
282 NormPtr p2;
283 p = skip_parenthesis (p2 = p + 1) - 1;
284 CODE [p] = ';';
285 open_local_scope ();
286 local_declaration (o, p2);
287 CODE [p++] = ')';
288 retcode = recent_obj ();
291 outprintf (o, RESERVED_jmp_buf, ii, ';', longjmp_ctx, '.', x, '=', '&', ii, ';',
292 longjmp_ctx, '.', y, '=', longjmp_ctx_top, ';', longjmp_ctx_top,
293 '=', '&', longjmp_ctx, ';', longjmp_ctx, '.', X, '=', RESERVED_0, ';', -1);
295 IFNEH // init manual accounting
296 outprintf (o, longjmp_ctx, '.', RESERVED_i, '=', RESERVED_0, ';', -1);
297 ELSE // install landing pad
298 outprintf (o, RESERVED_int, i3, cleanup_func (RESERVED___lwc_landingpad),
299 '=', RESERVED_0, ';', -1);
300 ENDIF
302 outprintf (o,
303 RESERVED_if, '(', '(', RESERVED_setjmp, '(', ii, ')', ')', ')', '{', -1);
304 IFNEH // init manual accounting
305 outprintf (o, longjmp_ctx, '.', RESERVED_i, '=', RESERVED_0, ';', -1);
306 ENDIF
307 if (have_retcode)
308 outprintf (o, retcode, '=', longjmp_ctx, '.', RESERVED_X, ';', -1);
310 p = statement (o, p);
311 output_itoken (o, '}');
312 if (have_retcode) close_local_scope ();
314 return p;