Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
6 7u83 2
 * Copyright (c) 2002-2006 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
6 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
6 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
6 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#include "version.h"
63
#include "c_types.h"
64
#include "exp_ops.h"
65
#include "type_ops.h"
66
#include "error.h"
67
#include "tdf.h"
68
#include "allocate.h"
69
#include "basetype.h"
70
#include "capsule.h"
71
#include "chktype.h"
72
#include "compile.h"
73
#include "destroy.h"
74
#include "diag.h"
75
#include "encode.h"
76
#include "exception.h"
77
#include "exp.h"
78
#include "init.h"
79
#include "inttype.h"
80
#include "shape.h"
81
#include "statement.h"
82
#include "stmt.h"
83
#include "struct.h"
84
#include "syntax.h"
85
#include "throw.h"
86
#include "tok.h"
87
#include "typeid.h"
88
#include "ustring.h"
89
#if TDF_OUTPUT
90
 
91
 
92
/*
93
    ENCODE THE ADDRESS OF A DESTRUCTOR
94
 
95
    This routine adds the address of the destructor function corresponding
96
    to d to the bitstream bs.
97
*/
98
 
6 7u83 99
BITSTREAM *
100
enc_destr_func(BITSTREAM *bs, EXP d)
2 7u83 101
{
6 7u83 102
	if (!IS_NULL_exp(d)) {
103
		EXP f;
104
		while (IS_exp_nof(d)) {
105
			d = DEREF_exp(exp_nof_pad(d));
106
		}
107
		f = DEREF_exp(exp_destr_call(d));
108
		if (IS_exp_func_id(f)) {
109
			ulong n;
110
			IDENTIFIER fn = DEREF_id(exp_func_id_id(f));
111
			IGNORE capsule_id(fn, VAR_tag);
112
			n = unit_no(bs, fn, VAR_tag, 0);
113
			ENC_obtain_tag(bs);
114
			ENC_make_tag(bs, n);
115
			return (bs);
116
		}
2 7u83 117
	}
6 7u83 118
	ENC_make_null_proc(bs);
119
	return (bs);
2 7u83 120
}
121
 
122
 
123
/*
124
    EXCEPTION HANDLING ROUTINES
125
 
126
    The exception handling routines are only included in the C++ producer.
127
*/
128
 
129
#if LANGUAGE_CPP
130
 
131
 
132
/*
133
    ENCODE A CATCH STATEMENT
134
 
135
    This routine adds the start of a catch statement to the bitstream bs.
136
    It checks whether the type t can handle the current exception.  If
137
    the label lab is given then catching the exception causes a jump to
138
    lab.  Otherwise the handler body, consisting of seq statements,
139
    followed by the code if the exception is not caught, needs to be
140
    added later.
141
*/
142
 
6 7u83 143
static BITSTREAM *
144
enc_catch(BITSTREAM *bs, TYPE t, ulong lab, unsigned seq)
2 7u83 145
{
6 7u83 146
	BITSTREAM *ts;
147
	NTEST tst = ntest_eq;
148
	if (lab == LINK_NONE) {
149
		/* Create label if necessary */
150
		lab = unit_no(bs, NULL_id, VAR_label, 1);
151
		ENC_conditional(bs);
152
		ENC_make_label(bs, lab);
153
		ENC_SEQUENCE(bs, seq);
154
		tst = ntest_not_eq;
155
	}
156
	ENC_integer_test(bs);
157
	ENC_OFF(bs);
158
	bs = enc_ntest(bs, tst);
159
	ENC_make_label(bs, lab);
160
	bs = enc_special(bs, TOK_except_catch);
161
	ts = start_bitstream(NIL(FILE), bs->link);
162
	ts = enc_rtti_type(ts, t, lex_typeid);
163
	bs = enc_bitstream(bs, ts);
164
	bs = enc_make_int(bs, type_sint, 0);
165
	return (bs);
2 7u83 166
}
167
 
168
 
169
/*
170
    ENCODE THE START OF A TRY BLOCK
171
 
172
    This routine adds the start of a try block to the bitstream bs.  seq
173
    gives the number of statements to follow.
174
*/
175
 
6 7u83 176
BITSTREAM *
177
enc_try_start(BITSTREAM *bs, ulong *pn, unsigned seq)
2 7u83 178
{
6 7u83 179
	ulong n;
180
	ulong lab;
181
	BITSTREAM *ts;
2 7u83 182
 
6 7u83 183
	/* Must be in a function definition */
184
	if (in_dynamic_init) {
185
		output_init = 1;
186
	}
2 7u83 187
 
6 7u83 188
	/* Encode the try block jump buffer */
189
	n = unit_no(bs, NULL_id, VAR_tag, 1);
190
	ENC_variable(bs);
191
	bs = enc_access(bs, crt_func_access);
192
	ENC_make_tag(bs, n);
193
	ENC_make_value(bs);
194
	bs = enc_special(bs, TOK_try_type);
195
	*pn = n;
2 7u83 196
 
6 7u83 197
	/* Encode the try block label */
198
	lab = unit_no(bs, NULL_id, VAR_label, 1);
199
	ENC_conditional(bs);
200
	ENC_make_label(bs, lab);
2 7u83 201
 
6 7u83 202
	/* Encode the try block body */
203
	ENC_SEQUENCE(bs, seq);
204
	bs = enc_special(bs, TOK_try_begin);
205
	ts = start_bitstream(NIL(FILE), bs->link);
206
	ENC_obtain_tag(ts);
207
	ENC_make_tag(ts, n);
208
	ENC_current_env(ts);
209
	ENC_make_local_lv(ts);
210
	ENC_make_label(ts, lab);
211
	bs = enc_bitstream(bs, ts);
212
	return (bs);
2 7u83 213
}
214
 
215
 
216
/*
217
    ENCODE THE END OF A TRY BLOCK
218
 
219
    This routine adds the end of the current try block to the bitstream bs.
220
*/
221
 
6 7u83 222
BITSTREAM *
223
enc_try_end(BITSTREAM *bs, ulong n)
2 7u83 224
{
6 7u83 225
	BITSTREAM *ts;
226
	bs = enc_special(bs, TOK_try_end);
227
	ts = start_bitstream(NIL(FILE), bs->link);
228
	ENC_obtain_tag(ts);
229
	ENC_make_tag(ts, n);
230
	bs = enc_bitstream(bs, ts);
231
	return (bs);
2 7u83 232
}
233
 
234
 
235
/*
236
    ENCODE A TRY BLOCK
237
 
238
    This routine adds the try block e to the bitstream bs.
239
*/
240
 
6 7u83 241
BITSTREAM *
242
enc_try(BITSTREAM *bs, EXP e)
2 7u83 243
{
6 7u83 244
	int uc;
245
	ulong ex;
246
	unsigned seq;
247
	EXP a = DEREF_exp(exp_try_block_body(e));
248
	LIST(EXP)p = DEREF_list(exp_try_block_handlers(e));
249
	LIST(TYPE)q = DEREF_list(exp_try_block_htypes(e));
250
	EXP c = DEREF_exp(exp_try_block_ellipsis(e));
2 7u83 251
 
6 7u83 252
	/* Ignore handlers if exception handling disabled */
253
	if (!output_except) {
254
		bs = enc_stmt(bs, a);
255
		return (bs);
256
	}
2 7u83 257
 
6 7u83 258
	/* Encode the try block */
259
	no_destructors++;
260
	if (output_new_diag) {
261
		seq = 2;
262
	} else {
263
		seq = stmt_length(a) + 1;
264
	}
265
	bs = enc_try_start(bs, &ex, seq);
266
	COPY_ulong(exp_try_block_no(e), ex);
267
	if (output_new_diag) {
268
		BITSTREAM *ts = enc_diag_begin(&bs);
269
		ts = enc_stmt(ts, a);
270
		bs = enc_diag_end(bs, ts, e, 1);
271
	} else {
272
		bs = enc_compound_stmt(bs, a);
273
	}
274
	bs = enc_try_end(bs, ex);
275
	uc = unreached_code;
2 7u83 276
 
6 7u83 277
	/* Encode the handlers */
278
	while (!IS_NULL_list(p)) {
279
		EXP b = DEREF_exp(HEAD_list(p));
280
		TYPE t = DEREF_type(HEAD_list(q));
281
		unreached_code = 0;
282
		if (!output_new_diag) {
283
			b = DEREF_exp(exp_handler_body(b));
284
		}
285
		seq = stmt_length(b) + 1;
286
		bs = enc_catch(bs, t, LINK_NONE, seq);
287
		bs = enc_compound_stmt(bs, b);
288
		bs = enc_special(bs, TOK_except_end);
289
		if (!unreached_code) {
290
			uc = 0;
291
		}
292
		q = TAIL_list(q);
293
		p = TAIL_list(p);
2 7u83 294
	}
295
 
6 7u83 296
	/* Encode the default handler */
297
	unreached_code = 0;
298
	if (IS_exp_handler(c)) {
299
		if (!output_new_diag) {
300
			c = DEREF_exp(exp_handler_body(c));
301
		}
302
		seq = stmt_length(c);
303
		if (seq) {
304
			ENC_SEQUENCE(bs, seq);
305
			bs = enc_compound_stmt(bs, c);
306
		}
307
		bs = enc_special(bs, TOK_except_end);
308
	} else {
309
		/* Re-throw current exception */
310
		bs = enc_exp(bs, c);
2 7u83 311
	}
6 7u83 312
	if (!unreached_code) {
313
		uc = 0;
2 7u83 314
	}
6 7u83 315
	unreached_code = uc;
316
	no_destructors--;
317
	return (bs);
2 7u83 318
}
319
 
320
 
321
/*
322
    RETHROW THE CURRENT EXCEPTION
323
 
324
    This routine adds the expression 'throw' to the bitstream bs.
325
*/
326
 
6 7u83 327
BITSTREAM *
328
enc_rethrow(BITSTREAM *bs)
2 7u83 329
{
6 7u83 330
	if (output_except) {
331
		bs = enc_special(bs, TOK_except_rethrow);
332
	} else {
333
		BITSTREAM *ts;
334
		bs = enc_special(bs, TOK_except_bad);
335
		ts = start_bitstream(NIL(FILE), bs->link);
336
		ts = enc_make_snat(ts, 0);
337
		bs = enc_bitstream(bs, ts);
338
	}
339
	unreached_code = 1;
340
	return (bs);
2 7u83 341
}
342
 
343
 
344
/*
345
    ENCODE A THROW EXPRESSION
346
 
347
    This routine adds the expression 'throw a' to the bitstream bs.  If
348
    a is the null expression then the current exception is rethrown.  b
349
    and d give the size and destructor for the exception type.
350
*/
351
 
6 7u83 352
BITSTREAM *
353
enc_throw(BITSTREAM *bs, EXP a, EXP b, EXP d)
2 7u83 354
{
6 7u83 355
	if (!IS_NULL_exp(a) && output_except) {
356
		/* Set up variable */
357
		EXP c;
358
		BITSTREAM *ts, *us;
359
		TYPE t = DEREF_type(exp_type(a));
360
		ulong n = unit_no(bs, NULL_id, VAR_tag, 1);
361
		ENC_variable(bs);
362
		bs = enc_access(bs, dspec_none);
363
		ENC_make_tag(bs, n);
364
		MAKE_exp_dummy(t, NULL_exp, n, NULL_off, 2, c);
2 7u83 365
 
6 7u83 366
		/* Allocate space for exception value */
367
		bs = enc_special(bs, TOK_from_ptr_void);
368
		ts = start_bitstream(NIL(FILE), bs->link);
369
		ts = enc_alignment(ts, t);
370
		ts = enc_special(ts, TOK_except_alloc);
371
		us = start_bitstream(NIL(FILE), ts->link);
372
		us = enc_exp(us, b);
373
		ts = enc_bitstream(ts, us);
374
		bs = enc_bitstream(bs, ts);
2 7u83 375
 
6 7u83 376
		/* Assign exception value */
377
		ENC_SEQ_SMALL(bs, 1);
378
		bs = enc_init_tag(bs, n, NULL_off, 1, t, a, NULL_exp, 0);
2 7u83 379
 
6 7u83 380
		/* Throw the exception */
381
		bs = enc_special(bs, TOK_except_throw);
382
		ts = start_bitstream(NIL(FILE), bs->link);
383
		ts = enc_special(ts, TOK_to_ptr_void);
384
		us = start_bitstream(NIL(FILE), ts->link);
385
		us = enc_alignment(us, t);
386
		us = enc_exp(us, c);
387
		ts = enc_bitstream(ts, us);
388
		ts = enc_rtti_type(ts, t, lex_typeid);
389
		ts = enc_destr_func(ts, d);
390
		bs = enc_bitstream(bs, ts);
391
		unreached_code = 1;
392
		free_exp(c, 1);
2 7u83 393
 
6 7u83 394
	} else {
395
		/* Rethrow the current exception */
396
		bs = enc_rethrow(bs);
397
	}
398
	return (bs);
2 7u83 399
}
400
 
401
 
402
/*
403
    ENCODE A CAUGHT EXPRESSION
404
 
405
    This routine adds the initialiser for an exception handler variable
406
    of type t to the bitstream bs.  This is obtained by casting the
407
    current exception value to a pointer to t.
408
*/
409
 
6 7u83 410
BITSTREAM *
411
enc_thrown(BITSTREAM *bs, TYPE t)
2 7u83 412
{
6 7u83 413
	BITSTREAM *ts = start_bitstream(NIL(FILE), bs->link);
414
	bs = enc_special(bs, TOK_from_ptr_void);
415
	ts = enc_alignment(ts, t);
416
	ts = enc_special(ts, TOK_except_value);
417
	bs = enc_bitstream(bs, ts);
418
	return (bs);
2 7u83 419
}
420
 
421
 
422
/*
423
    EXCEPTION SPECIFICATION FLAG
424
 
425
    This flag is set to true if the current function has an exception
426
    specification.
427
*/
428
 
6 7u83 429
int in_exception_spec = 0;
2 7u83 430
 
431
 
432
/*
433
    ENCODE THE START OF A FUNCTION EXCEPTION HANDLER
434
 
435
    This routine is called at the start of a function definition declared
436
    with a non-trivial exception specification.  It sets up a try block
437
    enclosing the complete function body.
438
*/
439
 
6 7u83 440
BITSTREAM *
441
enc_try_func(BITSTREAM *bs, EXP a)
2 7u83 442
{
6 7u83 443
	if (!IS_NULL_exp(a)) {
444
		/* Declare counter variable */
445
		EXP b = sizeof_init(a, type_sint);
446
		ulong n = unit_no(bs, NULL_id, VAR_tag, 1);
447
		ENC_variable(bs);
448
		bs = enc_access(bs, crt_func_access);
449
		ENC_make_tag(bs, n);
450
		bs = enc_exp(bs, b);
451
		free_exp(b, 1);
452
		last_params[DUMMY_count] = n;
453
	}
454
	no_destructors++;
455
	in_exception_spec++;
456
	ENC_SEQ_SMALL(bs, 1);
457
	bs = enc_try_start(bs, last_params + DUMMY_catch,(unsigned)1);
458
	return (bs);
2 7u83 459
}
460
 
461
 
462
/*
463
    BAD EXCEPTION TYPE
464
 
465
    This type represents the standard class 'std::bad_exception' which has
466
    a special meaning within exception specifications.
467
*/
468
 
6 7u83 469
static TYPE bad_except = NULL_type;
2 7u83 470
 
471
 
472
/*
473
    ENCODE THE END OF A FUNCTION EXCEPTION HANDLER
474
 
475
    This routine is called at the end of a function definition declared
476
    with the set of exceptions p.  It sets up a list of exception handlers
477
    for each element of p which re-throw the current exception.  If the
478
    exception remains uncaught then the bad exception token is called
479
    (which calls unexpected).
480
*/
481
 
6 7u83 482
BITSTREAM *
483
enc_catch_func(BITSTREAM *bs, LIST(TYPE)p, EXP a)
2 7u83 484
{
6 7u83 485
	int rethrow = 0;
486
	bs = enc_try_end(bs, last_params[DUMMY_catch]);
487
	if (!IS_NULL_exp(a)) {
488
		ENC_SEQ_SMALL(bs, 1);
489
		bs = enc_exp(bs, a);
490
	}
491
	if (EQ_list(p, univ_type_set)) {
492
		/* Can throw any exception */
493
		rethrow = 1;
494
	} else {
495
		BITSTREAM *ts;
496
		int have_bad = 0;
497
		if (!IS_NULL_list(p)) {
498
			/* Check list of exceptions */
499
			unsigned n = 0;
500
			LIST(TYPE)q = p;
501
			while (!IS_NULL_list(q)) {
502
				TYPE t = DEREF_type(HEAD_list(q));
503
				if (!IS_NULL_type(t)) {
504
					n++;
505
				}
506
				q = TAIL_list(q);
507
			}
508
			if (n) {
509
				ulong lab;
510
				TYPE s = bad_except;
511
				if (IS_NULL_type(s)) {
512
					s = find_std_type("bad_exception", 1,
513
							  0);
514
					s = exception_type(s, 0);
515
					bad_except = s;
516
				}
517
				lab = unit_no(bs, NULL_id, VAR_label, 1);
518
				ENC_conditional(bs);
519
				ENC_make_label(bs, lab);
520
				ENC_SEQUENCE(bs, n);
521
				while (!IS_NULL_list(p)) {
522
					TYPE t = DEREF_type(HEAD_list(p));
523
					if (!IS_NULL_type(t)) {
524
						t = exception_type(t, 0);
525
						if (eq_type(t, s)) {
526
							have_bad = 1;
527
						}
528
						bs = enc_catch(bs, t,
529
							       lab,(unsigned)0);
530
					}
531
					p = TAIL_list(p);
532
				}
533
				rethrow = 1;
534
			}
2 7u83 535
		}
6 7u83 536
		bs = enc_special(bs, TOK_except_bad);
537
		ts = start_bitstream(NIL(FILE), bs->link);
538
		ts = enc_make_snat(ts, have_bad);
539
		bs = enc_bitstream(bs, ts);
2 7u83 540
	}
6 7u83 541
	if (rethrow) {
542
		/* Re-throw the current exception */
543
		bs = enc_special(bs, TOK_except_rethrow);
544
		unreached_code = 1;
545
	}
546
	in_exception_spec--;
547
	no_destructors--;
548
	UNUSED(a);
549
	return (bs);
2 7u83 550
}
551
 
552
 
553
#endif /* LANGUAGE_CPP */
554
#endif /* TDF_OUTPUT */