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 "ctype_ops.h"
65
#include "exp_ops.h"
66
#include "id_ops.h"
67
#include "member_ops.h"
68
#include "nat_ops.h"
69
#include "nspace_ops.h"
70
#include "off_ops.h"
71
#include "type_ops.h"
72
#include "error.h"
73
#include "tdf.h"
74
#include "allocate.h"
75
#include "basetype.h"
76
#include "capsule.h"
77
#include "check.h"
78
#include "chktype.h"
79
#include "compile.h"
80
#include "constant.h"
81
#include "copy.h"
82
#include "destroy.h"
83
#include "diag.h"
84
#include "encode.h"
85
#include "exp.h"
86
#include "init.h"
87
#include "initialise.h"
88
#include "member.h"
89
#include "shape.h"
90
#include "statement.h"
91
#include "stmt.h"
92
#include "struct.h"
93
#include "syntax.h"
94
#include "throw.h"
95
#include "tok.h"
96
#if TDF_OUTPUT
97
 
98
 
99
/*
100
    INITIALISER FLAGS
101
 
102
    The flag in_static_init is set to true when encoding a static
103
    initialiser.  The flag in_dynamic_init is set to true when encoding
104
    a dynamic initialiser.
105
*/
106
 
6 7u83 107
int in_static_init = 0;
108
int in_dynamic_init = 0;
2 7u83 109
 
110
 
111
/*
112
    ENCODE AN AGGREGATE ARRAY INITIALISER
113
 
114
    This routine adds the aggregate initialiser for an array of type t,
115
    given by the aggregate expression e followed by n zeros, to the
116
    bitstream bs.  n may be null to indicate the absence of padding.
117
*/
118
 
6 7u83 119
BITSTREAM *
120
enc_init_array(BITSTREAM *bs, EXP e, NAT n, TYPE t)
2 7u83 121
{
6 7u83 122
	LIST(EXP)p = DEREF_list(exp_aggregate_args(e));
123
	TYPE s = DEREF_type(type_array_sub(t));
124
	unsigned tag = TAG_type(s);
125
	if (tag == type_integer_tag || tag == type_enumerate_tag) {
126
		unsigned mask = 0;
127
		unsigned long len = 0;
128
		LIST(EXP)q = p;
129
		LIST(unsigned)vs = NULL_list(unsigned);
130
		while (!IS_NULL_list(q)) {
131
			/* Check for arrays of integers */
132
			unsigned v = 0;
133
			EXP a = DEREF_exp(HEAD_list(q));
134
			if (!IS_NULL_exp(a)) {
135
				NAT m;
136
				unsigned tm;
137
				if (!IS_exp_int_lit(a)) {
138
					break;
139
				}
140
				m = DEREF_nat(exp_int_lit_nat(a));
141
				tm = TAG_nat(m);
142
				if (tm == nat_calc_tag) {
143
					/* Allow for character literals */
144
					a = eval_exp(a, 1);
145
					if (!IS_exp_int_lit(a)) {
146
						break;
147
					}
148
					m = DEREF_nat(exp_int_lit_nat(a));
149
					tm = TAG_nat(m);
150
				}
151
				if (tm != nat_small_tag) {
152
					break;
153
				}
154
				v = DEREF_unsigned(nat_small_value(m));
155
			}
156
			CONS_unsigned(v, vs, vs);
157
			mask |= v;
158
			len++;
159
			q = TAIL_list(q);
2 7u83 160
		}
6 7u83 161
		if (IS_NULL_list(q)) {
162
			/* Array of small integers */
163
			if (mask == 0) {
164
				/* All zeros */
165
				bs = enc_null_exp(bs, t);
166
			} else {
167
				/* Encode as a string */
168
				LIST(unsigned)us;
169
				unsigned bits = no_bits(mask);
170
				if (!IS_NULL_nat(n)) {
171
					/* Check for padding */
172
					unsigned long pad = get_nat_value(n);
173
					if (pad <= STRING_PADDING) {
174
						len += pad;
175
						n = NULL_nat;
176
					} else {
177
						ENC_concat_nof(bs);
178
					}
179
				}
180
				ENC_make_nof_int(bs);
181
				bs = enc_variety(bs, s);
182
				ENC_make_string(bs);
183
				ENC_INT(bs, bits);
184
				ENC_INT(bs, len);
185
				vs = REVERSE_list(vs);
186
				us = vs;
187
				while (!IS_NULL_list(us)) {
188
					/* Encode each element */
189
					unsigned v =
190
					    DEREF_unsigned(HEAD_list(us));
191
					ENC_BITS(bs, bits, v);
192
					len--;
193
					us = TAIL_list(us);
194
				}
195
				while (len) {
196
					/* Encode explicit padding */
197
					ENC_BITS(bs, bits, 0);
198
					len--;
199
				}
200
				if (!IS_NULL_nat(n)) {
201
					/* Encode remaining padding */
202
					ENC_n_copies(bs);
203
					bs = enc_nat(bs, n, 1);
204
					bs = enc_null_exp(bs, s);
205
				}
206
			}
207
			DESTROY_list(vs, SIZE_unsigned);
208
			return (bs);
2 7u83 209
		}
6 7u83 210
		DESTROY_list(vs, SIZE_unsigned);
2 7u83 211
	}
212
 
6 7u83 213
	/* Simple list */
214
	if (!IS_NULL_nat(n)) {
215
		ENC_concat_nof(bs);
216
	}
217
	ENC_make_nof(bs);
218
	bs = enc_exp_list(bs, p);
219
	if (!IS_NULL_nat(n)) {
220
		ENC_n_copies(bs);
221
		bs = enc_nat(bs, n, 1);
222
		bs = enc_null_exp(bs, s);
223
	}
224
	return (bs);
2 7u83 225
}
226
 
227
 
228
/*
229
    ENCODE AN AGGREGATE CLASS INITIALISER
230
 
231
    This routine adds the aggregate initialiser for an object of class
232
    type t given by the aggregate expression p to the bitstream bs.  Note
233
    that t cannot have any base classes.
234
*/
235
 
6 7u83 236
BITSTREAM *
237
enc_init_class(BITSTREAM *bs, EXP e, CLASS_TYPE ct)
2 7u83 238
{
6 7u83 239
	LIST(EXP)p = DEREF_list(exp_aggregate_args(e));
240
	LIST(OFFSET)q = DEREF_list(exp_aggregate_offs(e));
241
	unsigned m = LENGTH_list(p);
242
	IGNORE compile_class(ct);
243
	if (m == 0) {
244
		/* Deal with empty classes */
245
		ENC_make_value(bs);
246
		bs = enc_ctype(bs, ct);
247
	} else {
248
		ENC_make_compound(bs);
249
		ENC_shape_offset(bs);
250
		bs = enc_ctype(bs, ct);
251
		ENC_LIST(bs, m + m);
252
		while (!IS_NULL_list(p)) {
253
			/* Scan aggregate initialiser */
254
			EXP a = DEREF_exp(HEAD_list(p));
255
			OFFSET off = DEREF_off(HEAD_list(q));
256
			bs = enc_offset(bs, off);
257
			bs = enc_exp(bs, a);
258
			q = TAIL_list(q);
259
			p = TAIL_list(p);
260
		}
2 7u83 261
	}
6 7u83 262
	return (bs);
2 7u83 263
}
264
 
265
 
266
/*
267
    ALLOCATION LOOP COUNTER
268
 
269
    This variable is used to hold the tag of the loop counter variable
270
    which is used in new-initialiser expressions.
271
*/
272
 
6 7u83 273
static ulong alloc_counter = LINK_NONE;
2 7u83 274
 
275
 
276
/*
277
    DECLARE A LOOP COUNTER
278
 
279
    This routine declares the pointer to s variable n to be the pointer
280
    variable m plus the offset off and the offset of the type t.
281
*/
282
 
6 7u83 283
static BITSTREAM *
284
enc_loop_decl(BITSTREAM *bs, ulong n, ulong m, TYPE s, int cnt, OFFSET off,
285
	      TYPE t)
2 7u83 286
{
6 7u83 287
	DECL_SPEC ds = dspec_none;
288
	if (n == alloc_counter) {
289
		ds = dspec_mutable;
290
	}
291
	if (cnt) {
292
		cnt = 2;
293
	}
294
	ENC_variable(bs);
295
	bs = enc_access(bs, ds);
296
	ENC_make_tag(bs, n);
297
	if (IS_NULL_type(t)) {
298
		bs = enc_dummy_exp(bs, s, m, off, cnt, 0);
299
	} else {
300
		ENC_add_to_ptr(bs);
301
		bs = enc_dummy_exp(bs, s, m, off, cnt, 0);
302
		bs = enc_shape_offset(bs, t);
303
	}
304
	return (bs);
2 7u83 305
}
306
 
307
 
308
/*
309
    TEST A LOOP COUNTER
310
 
311
    This routine compares the pointer to t variables n and m using test
312
    tst, jumping to label lab if appropriate.
313
*/
314
 
6 7u83 315
static BITSTREAM *
316
enc_loop_test(BITSTREAM *bs, ulong n, ulong m, TYPE t, ulong lab, NTEST tst)
2 7u83 317
{
6 7u83 318
	ENC_pointer_test(bs);
319
	ENC_OFF(bs);
320
	bs = enc_ntest(bs, tst);
321
	ENC_make_label(bs, lab);
322
	ENC_contents(bs);
323
	ENC_pointer(bs);
324
	bs = enc_alignment(bs, t);
325
	ENC_obtain_tag(bs);
326
	ENC_make_tag(bs, n);
327
	if (m == LINK_NONE) {
328
		ENC_make_null_ptr(bs);
329
		bs = enc_alignment(bs, t);
330
	} else {
331
		ENC_contents(bs);
332
		ENC_pointer(bs);
333
		bs = enc_alignment(bs, t);
334
		ENC_obtain_tag(bs);
335
		ENC_make_tag(bs, m);
336
	}
337
	return (bs);
2 7u83 338
}
339
 
340
 
341
/*
342
    TEST A BOOLEAN FLAG
343
 
344
    This routine tests the flag given by the tag n, and-ed with a if this
345
    is not zero, against zero.  A further s expressions to be evaluated
346
    if tst is true must be added together with the terminating expression
347
    of the conditional.
348
*/
349
 
6 7u83 350
BITSTREAM *
351
enc_flag_test(BITSTREAM *bs, ulong n, unsigned s, int a, NTEST tst)
2 7u83 352
{
6 7u83 353
	ulong lab = unit_no(bs, NULL_id, VAR_label, 1);
354
	ENC_conditional(bs);
355
	ENC_make_label(bs, lab);
356
	if (s) {
357
		ENC_SEQUENCE(bs, s);
358
	}
359
	ENC_integer_test(bs);
360
	ENC_OFF(bs);
361
	bs = enc_ntest(bs, tst);
362
	ENC_make_label(bs, lab);
363
	if (a) {
364
		ENC_and(bs);
365
	}
366
	ENC_contents(bs);
367
	bs = enc_shape(bs, type_sint);
368
	ENC_obtain_tag(bs);
369
	ENC_make_tag(bs, n);
370
	if (a) {
371
		bs = enc_make_int(bs, type_sint, a);
372
	}
373
	bs = enc_make_int(bs, type_sint, 0);
374
	return (bs);
2 7u83 375
}
376
 
377
 
378
/*
379
    INCREMENT A LOOP COUNTER
380
 
381
    This routine increments (or decrements if neg is true) the pointer
382
    variable n by the offset of the type t.
383
*/
384
 
6 7u83 385
static BITSTREAM *
386
enc_loop_incr(BITSTREAM *bs, ulong n, TYPE t, int neg)
2 7u83 387
{
6 7u83 388
	ENC_assign(bs);
389
	ENC_obtain_tag(bs);
390
	ENC_make_tag(bs, n);
391
	ENC_add_to_ptr(bs);
392
	ENC_contents(bs);
393
	ENC_pointer(bs);
394
	bs = enc_alignment(bs, t);
395
	ENC_obtain_tag(bs);
396
	ENC_make_tag(bs, n);
397
	if (neg) {
398
		ENC_offset_negate(bs);
399
	}
400
	bs = enc_shape_offset(bs, t);
401
	return (bs);
2 7u83 402
}
403
 
404
 
405
/*
406
    FIND A TERMINATOR TYPE
407
 
408
    This routine returns the type for a terminator for a value of type t.
409
*/
410
 
6 7u83 411
static TYPE
412
find_count_type(TYPE t)
2 7u83 413
{
6 7u83 414
	if (!IS_NULL_type(t)) {
415
		if (IS_type_array(t)) {
416
			/* Handle arrays */
417
			NAT n = DEREF_nat(type_array_size(t));
418
			TYPE s = DEREF_type(type_array_sub(t));
419
			s = find_count_type(s);
420
			MAKE_type_array(cv_none, s, n, t);
421
		} else {
422
			t = dummy_count;
423
		}
2 7u83 424
	}
6 7u83 425
	return (t);
2 7u83 426
}
427
 
428
 
429
/*
430
    DECLARE A TERMINATOR COUNT VARIABLE
431
 
432
    This routine introduces a local variable for the terminator count
433
    variable given by d.
434
*/
435
 
6 7u83 436
static BITSTREAM *
437
enc_count_decl(BITSTREAM *bs, EXP d, TYPE s, ulong *pm)
2 7u83 438
{
6 7u83 439
	if (IS_exp_destr(d)) {
440
		EXP c = DEREF_exp(exp_destr_count(d));
441
		if (!IS_NULL_exp(c)) {
442
			int cnt = DEREF_int(exp_dummy_cont(c));
443
			if (cnt == 0) {
444
				/* Variable not yet introduced */
445
				TYPE t = dummy_count;
446
				ulong n = unit_no(bs, NULL_id, VAR_tag, 1);
447
				ulong m = DEREF_ulong(exp_dummy_no(c));
448
				s = find_count_type(s);
449
				bs = enc_loop_decl(bs, n, m, t, 0, NULL_off, s);
450
				COPY_int(exp_dummy_cont(c), 2);
451
				COPY_ulong(exp_dummy_no(c), n);
452
				*pm = m;
453
			}
454
		}
2 7u83 455
	}
6 7u83 456
	return (bs);
2 7u83 457
}
458
 
459
 
460
/*
461
    END A TERMINATOR COUNT VARIABLE
462
 
463
    This routine ends the terminator count given by d.
464
*/
465
 
6 7u83 466
static void
467
enc_count_end(EXP d, ulong m)
2 7u83 468
{
6 7u83 469
	if (IS_exp_destr(d)) {
470
		EXP c = DEREF_exp(exp_destr_count(d));
471
		if (!IS_NULL_exp(c) && m != LINK_NONE) {
472
			COPY_int(exp_dummy_cont(c), 0);
473
			COPY_ulong(exp_dummy_no(c), m);
474
		}
2 7u83 475
	}
6 7u83 476
	return;
2 7u83 477
}
478
 
479
 
480
/*
481
    INCREMENT A TERMINATOR COUNT VARIABLE
482
 
483
    This routine increments the terminator count variable given by d.
484
    Note that this is only done at the innermost level, i.e. when the
485
    associated type t is not an array.
486
*/
487
 
6 7u83 488
static BITSTREAM *
489
enc_count_incr(BITSTREAM *bs, EXP d, int neg, TYPE t)
2 7u83 490
{
6 7u83 491
	if (IS_exp_destr(d) && !IS_type_array(t)) {
492
		EXP c = DEREF_exp(exp_destr_count(d));
493
		if (!IS_NULL_exp(c)) {
494
			ulong n = DEREF_ulong(exp_dummy_no(c));
495
			bs = enc_loop_incr(bs, n, dummy_count, neg);
496
			return (bs);
497
		}
2 7u83 498
	}
6 7u83 499
	ENC_make_top(bs);
500
	return (bs);
2 7u83 501
}
502
 
503
 
504
/*
505
    ENCODE A TERMINATOR TYPE
506
 
507
    This routine adds the type of the terminator object corresponding to
508
    type t to the bitstream bs.
509
*/
510
 
6 7u83 511
BITSTREAM *
512
enc_term_type(BITSTREAM *bs, TYPE t)
2 7u83 513
{
6 7u83 514
	while (IS_type_array(t)) {
515
		/* Allow for arrays */
516
		NAT n = DEREF_nat(type_array_size(t));
517
		ENC_nof(bs);
518
		bs = enc_nat(bs, n, 1);
519
		t = DEREF_type(type_array_sub(t));
520
	}
521
	bs = enc_special(bs, TOK_destr_type);
522
	return (bs);
2 7u83 523
}
524
 
525
 
526
/*
527
    DEFINE A GLOBAL TERMINATOR OBJECT
528
 
529
    This routine defines a global terminator object corresponding to an
530
    object of type t and destructor pd.
531
*/
532
 
6 7u83 533
void
534
make_term_global(TYPE t, EXP *pd)
2 7u83 535
{
6 7u83 536
	EXP d = *pd;
537
	if (!IS_NULL_exp(d)) {
538
		EXP a;
539
		while (IS_exp_nof(d)) {
540
			d = DEREF_exp(exp_nof_pad(d));
541
		}
542
		a = DEREF_exp(exp_destr_count(d));
543
		if (IS_NULL_exp(a)) {
544
			/* Not already defined */
545
			TYPE s = dummy_count;
546
			ulong n = capsule_no(NULL_string, VAR_tag);
547
			BITSTREAM *bs = enc_tagdec_start(NULL_id, n, t, 1);
548
			bs = enc_term_type(bs, t);
549
			enc_tagdec_end(bs);
550
			bs = enc_tagdef_start(NULL_id, n, t, 1);
551
			while (IS_type_array(t)) {
552
				NAT m = DEREF_nat(type_array_size(t));
553
				ENC_n_copies(bs);
554
				bs = enc_nat(bs, m, 1);
555
				t = DEREF_type(type_array_sub(t));
556
			}
557
			bs = enc_special(bs, TOK_destr_null);
558
			enc_tagdef_end(bs);
559
			MAKE_exp_dummy(s, NULL_exp, n, NULL_off, 0, a);
560
			COPY_exp(exp_destr_count(d), a);
561
		}
562
		*pd = d;
2 7u83 563
	}
6 7u83 564
	return;
2 7u83 565
}
566
 
567
 
568
/*
569
    DEFINE A LOCAL TERMINATOR OBJECT
570
 
571
    This routine defines a local terminator object corresponding to an
572
    object of type t and destructor pd.
573
*/
574
 
6 7u83 575
BITSTREAM *
576
make_term_local(BITSTREAM *bs, TYPE t, EXP *pd, int var)
2 7u83 577
{
6 7u83 578
	EXP d = *pd;
579
	if (!IS_NULL_exp(d)) {
580
		EXP a;
581
		TYPE s = dummy_count;
582
		ulong n = unit_no(bs, NULL_id, VAR_tag, 1);
583
		ENC_variable(bs);
584
		bs = enc_access(bs, dspec_none);
585
		ENC_make_tag(bs, n);
586
		if (var == 4) {
587
			/* Initialise to zero for temporaries */
588
			while (IS_type_array(t)) {
589
				NAT m = DEREF_nat(type_array_size(t));
590
				ENC_n_copies(bs);
591
				bs = enc_nat(bs, m, 1);
592
				t = DEREF_type(type_array_sub(t));
593
			}
594
			bs = enc_special(bs, TOK_destr_null);
595
		} else {
596
			ENC_make_value(bs);
597
			bs = enc_term_type(bs, t);
598
		}
599
		while (IS_exp_nof(d)) {
600
			d = DEREF_exp(exp_nof_pad(d));
601
		}
602
		MAKE_exp_dummy(s, NULL_exp, n, NULL_off, 0, a);
603
		COPY_exp(exp_destr_count(d), a);
604
		*pd = d;
2 7u83 605
	}
6 7u83 606
	return (bs);
2 7u83 607
}
608
 
609
 
610
/*
611
    DECREASE A PARTIAL DESTRUCTOR COUNT
612
 
613
    This routine decreases the partial destructor count by the value given
614
    in t and n.
615
*/
616
 
6 7u83 617
BITSTREAM *
618
enc_destr_count(BITSTREAM *bs, TYPE t, int n)
2 7u83 619
{
6 7u83 620
	TYPE s = type_sint;
621
	ulong m = last_params[DUMMY_count];
622
	ENC_assign(bs);
623
	ENC_obtain_tag(bs);
624
	ENC_make_tag(bs, m);
625
	ENC_minus(bs);
626
	bs = enc_error_treatment(bs, s);
627
	ENC_contents(bs);
628
	bs = enc_shape(bs, s);
629
	ENC_obtain_tag(bs);
630
	ENC_make_tag(bs, m);
631
	if (!IS_NULL_type(t) && IS_type_array(t)) {
632
		EXP a = sizeof_array(&t, s);
633
		bs = enc_exp(bs, a);
634
		free_exp(a, 1);
635
	} else {
636
		bs = enc_make_int(bs, s, n);
637
	}
638
	return (bs);
2 7u83 639
}
640
 
641
 
642
/*
643
    ENCODE THE TERMINATOR FOR A TAG
644
 
645
    This routine adds a terminator expression for the destructor d to the
646
    bitstream bs.  The other arguments are as in enc_init_tag.  The effect
647
    of the terminator expression is to add the destructor call to a list
648
    of destructors to be called at a later stage.
649
*/
650
 
6 7u83 651
static BITSTREAM *
652
enc_term_start(BITSTREAM *bs, ulong n, OFFSET off, int cnt, TYPE t, EXP d,
653
	       int context)
2 7u83 654
{
6 7u83 655
	int tok = TOK_destr_local;
656
	switch (context) {
657
	case 1:
658
destr_lab: {
659
		   /* Destroy local variable */
660
		   BITSTREAM *ts, *us;
661
		   EXP c = DEREF_exp(exp_destr_count(d));
662
		   ASSERT(!IS_NULL_exp(c));
663
		   bs = enc_special(bs, tok);
664
		   ts = start_bitstream(NIL(FILE), bs->link);
665
		   ts = enc_exp(ts, c);
666
		   ts = enc_special(ts, TOK_destr_cast);
667
		   us = start_bitstream(NIL(FILE), ts->link);
668
		   us = enc_alignment(us, t);
669
		   us = enc_dummy_exp(us, t, n, off, 2 * cnt, 0);
670
		   ts = enc_bitstream(ts, us);
671
		   ts = enc_destr_func(ts, d);
672
		   bs = enc_bitstream(bs, ts);
673
		   break;
674
	   }
675
	case 2: {
676
		/* Destroy global variable */
677
		tok = TOK_destr_global;
678
		goto destr_lab;
2 7u83 679
	}
6 7u83 680
	case 5: {
681
		/* Partial constructor count */
682
		bs = enc_destr_count(bs, t, 1);
683
		break;
2 7u83 684
	}
6 7u83 685
	default: {
686
		ENC_make_top(bs);
687
		break;
2 7u83 688
	}
689
	}
6 7u83 690
	return (bs);
2 7u83 691
}
692
 
693
 
694
/*
695
    ENCODE AN ASSIGNMENT TO A TAG
696
 
697
    This routine adds an assignment of the value e to the tag n plus offset
698
    off of type t (or the contents of tag n plus offset off if cnt is true)
699
    to the bitstream bs.  context is 2 for the initialisation of a global
700
    variable, 1 for the initialisation of a local variable and 0 otherwise.
701
    If the destructor expression d is not null then the terminator
702
    expressions for tag n are also initialised.  In this the case the
703
    output comprises two TDF expressions, otherwise it is a single
704
    expression.
705
*/
706
 
6 7u83 707
BITSTREAM *
708
enc_init_tag(BITSTREAM *bs, ulong n, OFFSET off, int cnt, TYPE t, EXP e, EXP d,
709
	     int context)
2 7u83 710
{
6 7u83 711
	/* Step over parenthesised expressions */
712
	int paren;
713
	unsigned tag;
714
	int temp = 0;
715
	int array = 0;
716
	int constant = 1;
717
	do {
718
		tag = TAG_exp(e);
719
		paren = 0;
720
		switch (tag) {
721
		case exp_dynamic_tag: {
722
			e = DEREF_exp(exp_dynamic_arg(e));
723
			constant = 0;
724
			paren = 1;
725
			break;
726
		}
727
		case exp_paren_tag:
728
		case exp_copy_tag: {
729
			e = DEREF_exp(exp_paren_etc_arg(e));
730
			paren = 1;
731
			break;
732
		}
733
		}
734
	} while (paren);
2 7u83 735
 
6 7u83 736
	/* Encode initialiser */
737
	switch (tag) {
2 7u83 738
 
6 7u83 739
	case exp_constr_tag: {
740
		/* Constructor calls */
741
		EXP a = DEREF_exp(exp_constr_obj(e));
742
		EXP b = DEREF_exp(exp_constr_alt(e));
743
		COPY_ulong(exp_dummy_no(a), n);
744
		COPY_off(exp_dummy_off(a), off);
745
		COPY_off(exp_dummy_off(b), off);
746
		COPY_int(exp_dummy_cont(a), 2 * cnt);
747
		e = DEREF_exp(exp_constr_call(e));
748
		bs = enc_exp(bs, e);
749
		COPY_off(exp_dummy_off(b), NULL_off);
750
		COPY_off(exp_dummy_off(a), NULL_off);
751
		break;
2 7u83 752
	}
753
 
6 7u83 754
	case exp_aggregate_tag: {
755
		/* Aggregate initialisers */
756
		unsigned tt = TAG_type(t);
757
		LIST(EXP)p = DEREF_list(exp_aggregate_args(e));
758
		LIST(OFFSET)q = DEREF_list(exp_aggregate_offs(e));
759
		unsigned i, m = LENGTH_list(p);
760
		if (tt == type_array_tag) {
761
			/* Array initialisers */
762
			OFFSET off1;
763
			ulong dn = LINK_NONE;
764
			TYPE s1 = DEREF_type(type_array_sub(t));
765
			if (constant) {
766
				/* Perform constant initialisation */
767
				if (IS_NULL_exp(d) && is_const_exp(e, -1)) {
768
					goto default_lab;
769
				}
770
			}
771
			if (!IS_NULL_exp(d)) {
772
				/* Declare terminator count */
773
				bs = enc_count_decl(bs, d, NULL_type, &dn);
774
				ENC_SEQUENCE(bs, 3 * m - 1);
775
			} else {
776
				if (m > 1)ENC_SEQUENCE(bs, m - 1);
777
			}
778
			MAKE_off_array(s1, 0, off1);
779
			MAKE_off_plus(off, off1, off);
780
			for (i = 0; i < m; i++) {
781
				/* Scan through elements */
782
				EXP a = DEREF_exp(HEAD_list(p));
783
				COPY_unsigned(off_array_arg(off1), i);
784
				bs = enc_init_tag(bs, n, off, cnt, s1, a, d,
785
						  context);
786
				if (!IS_NULL_exp(d)) {
787
					/* Increase terminator count */
788
					bs = enc_count_incr(bs, d, 0, s1);
789
				}
790
				p = TAIL_list(p);
791
			}
792
			DESTROY_off_plus(destroy, off, off1, off);
793
			DESTROY_off_array(destroy, s1, i, off1);
794
			UNUSED(s1);
795
			UNUSED(i);
796
			array = 1;
2 7u83 797
 
6 7u83 798
		} else if (tt == type_compound_tag) {
799
			/* Class initialisers */
800
			OFFSET off1 = NULL_off;
801
			CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
802
			IGNORE compile_class(ct);
803
			if (m == 0) {
804
				goto default_lab;
805
			}
806
			if (constant && m >= SMALL_COMPOUND_INIT) {
807
				if (is_const_exp(e, -1)) {
808
					/* Perform constant initialisation */
809
					temp = 1;
810
					goto default_lab;
811
				}
812
			}
813
			MAKE_off_plus(off, off1, off);
814
			if (m > 1) {
815
				ENC_SEQUENCE(bs, m - 1);
816
			}
817
			for (i = 0; i < m; i++) {
818
				/* Scan through data members */
819
				EXP a = DEREF_exp(HEAD_list(p));
820
				TYPE s = DEREF_type(exp_type(a));
821
				off1 = DEREF_off(HEAD_list(q));
822
				COPY_off(off_plus_arg2(off), off1);
823
				bs = enc_init_tag(bs, n, off, cnt, s, a,
824
						  NULL_exp, 0);
825
				p = TAIL_list(p);
826
				q = TAIL_list(q);
827
			}
828
			DESTROY_off_plus(destroy, off, off1, off);
829
			UNUSED(off1);
2 7u83 830
		}
6 7u83 831
		break;
2 7u83 832
	}
833
 
6 7u83 834
	case exp_nof_tag: {
835
		/* Array initialisers */
836
		OFFSET off1 = off;
837
		EXP a = DEREF_exp(exp_nof_start(e));
838
		EXP b = DEREF_exp(exp_nof_pad(e));
839
		NAT m = DEREF_nat(exp_nof_size(e));
840
		if (constant) {
841
			/* Perform constant initialisation */
842
			if (IS_NULL_exp(d) && is_const_exp(e, -1)) {
843
				goto default_lab;
844
			}
2 7u83 845
		}
846
 
6 7u83 847
		/* Allow for zero sized arrays */
848
		if (is_zero_nat(m)) {
849
			b = NULL_exp;
850
		} else {
851
			if (context == 2 && is_null_exp(b)) {
852
				/* Global already default initialised */
853
				if (IS_NULL_exp(d)) {
854
					b = NULL_exp;
855
				} else {
856
					MAKE_exp_value(t, b);
857
				}
858
			}
2 7u83 859
		}
860
 
6 7u83 861
		/* Encode initial component */
862
		if (IS_NULL_exp(a)) {
863
			if (IS_NULL_exp(b)) {
864
				/* Both components empty */
865
				ENC_make_top(bs);
866
			}
867
		} else {
868
			TYPE s = DEREF_type(exp_type(a));
869
			if (!IS_NULL_exp(b)) {
870
				unsigned seq = 1;
871
				if (!IS_NULL_exp(d))seq = 2;
872
				ENC_SEQ_SMALL(bs, seq);
873
				MAKE_off_type(s, off1);
874
				MAKE_off_plus(off, off1, off1);
875
			}
876
			bs = enc_init_tag(bs, n, off, cnt, s, a, d, context);
2 7u83 877
		}
878
 
6 7u83 879
		/* Encode padding component */
880
		if (!IS_NULL_exp(b)) {
881
			ulong ptr, end;
882
			unsigned seq = 2;
883
			ulong dn = LINK_NONE;
884
			int c = last_conts[DUMMY_copy];
885
			ulong s = last_params[DUMMY_copy];
886
			ulong cpy = s;
2 7u83 887
 
6 7u83 888
			TYPE r1 = DEREF_type(exp_type(b));
889
			ulong lab = unit_no(bs, NULL_id, VAR_label, 1);
890
			ptr = alloc_counter;
891
			if (ptr == LINK_NONE) {
892
				TYPE t0 = NULL_type;
893
				ptr = unit_no(bs, NULL_id, VAR_tag, 1);
894
				bs = enc_loop_decl(bs, ptr, n, r1, cnt, off1,
895
						   t0);
896
			}
897
			end = unit_no(bs, NULL_id, VAR_tag, 1);
898
			bs = enc_loop_decl(bs, end, n, r1, cnt, off, t);
899
			if (s != LINK_NONE) {
900
				/* Allow for copy constructors */
901
				cpy = unit_no(bs, NULL_id, VAR_tag, 1);
902
				bs = enc_loop_decl(bs, cpy, s, r1, c, off1,
903
						   NULL_type);
904
				last_params[DUMMY_copy] = cpy;
905
				last_conts[DUMMY_copy] = 2;
906
				seq++;
907
			}
908
			if (IS_nat_calc(m)) {
909
				/* Check for calculated bounds */
910
				ulong lab2 = unit_no(bs, NULL_id, VAR_label, 1);
911
				ENC_conditional(bs);
912
				ENC_make_label(bs, lab2);
913
				ENC_SEQ_SMALL(bs, 1);
914
				bs = enc_loop_test(bs, ptr, end, r1, lab2,
915
						   ntest_less);
916
			}
917
			if (!IS_NULL_exp(d)) {
918
				/* Declare terminator count */
919
				bs = enc_count_decl(bs, d, NULL_type, &dn);
920
				seq += 2;
921
			}
922
			ENC_repeat(bs);
923
			ENC_make_label(bs, lab);
924
			ENC_make_top(bs);
925
			ENC_SEQUENCE(bs, seq);
926
			bs = enc_init_tag(bs, ptr, NULL_off, 1, r1, b, d,
927
					  context);
928
			if (!IS_NULL_exp(d)) {
929
				/* Increase terminator count */
930
				bs = enc_count_incr(bs, d, 0, r1);
931
			}
932
			if (cpy != LINK_NONE) {
933
				bs = enc_loop_incr(bs, cpy, r1, 0);
934
			}
935
			bs = enc_loop_incr(bs, ptr, r1, 0);
936
			bs = enc_loop_test(bs, ptr, end, r1, lab, ntest_eq);
937
			if (IS_nat_calc(m)) {
938
				/* End check for calculated bounds */
939
				ENC_make_top(bs);
940
			}
941
			if (!IS_NULL_exp(d)) {
942
				enc_count_end(d, dn);
943
			}
944
			last_params[DUMMY_copy] = s;
945
			last_conts[DUMMY_copy] = c;
946
			if (!EQ_off(off1, off)) {
947
				DESTROY_off_plus(destroy, off, off1, off1);
948
				DESTROY_off_type(destroy, r1, off1);
949
				UNUSED(r1);
950
			}
2 7u83 951
		}
6 7u83 952
		/* NOT YET IMPLEMENTED - end component */
953
		array = 1;
954
		break;
2 7u83 955
	}
956
 
6 7u83 957
	case exp_preinc_tag: {
958
		/* Array initialisers */
959
		int op = DEREF_int(exp_preinc_becomes(e));
960
		if (op == lex_array) {
961
			int c = last_conts[DUMMY_copy];
962
			ulong s = last_params[DUMMY_copy];
963
			EXP a = DEREF_exp(exp_preinc_ref(e));
964
			EXP a1 = DEREF_exp(exp_dummy_value(a));
965
			ulong m = unit_no(bs, NULL_id, VAR_tag, 1);
966
			ENC_variable(bs);
967
			bs = enc_access(bs, dspec_none);
968
			ENC_make_tag(bs, m);
969
			bs = enc_exp(bs, a1);
970
			last_params[DUMMY_copy] = m;
971
			last_conts[DUMMY_copy] = 2;
972
			COPY_exp(exp_dummy_value(a), NULL_exp);
973
			e = DEREF_exp(exp_preinc_op(e));
974
			if (!IS_NULL_exp(d)) {
975
				ENC_SEQ_SMALL(bs, 1);
976
			}
977
			bs = enc_init_tag(bs, n, off, cnt, t, e, d, context);
978
			COPY_exp(exp_dummy_value(a), a1);
979
			last_params[DUMMY_copy] = s;
980
			last_conts[DUMMY_copy] = c;
981
			array = 1;
982
			break;
983
		}
984
		goto default_lab;
2 7u83 985
	}
986
 
6 7u83 987
	case exp_int_lit_tag:
988
	case exp_float_lit_tag:
989
	case exp_null_tag:
990
	case exp_zero_tag: {
991
		/* Null expressions */
992
		if (context == 2 && is_null_exp(e)) {
993
			/* Global already default initialised */
994
			ENC_make_top(bs);
995
			break;
996
		}
997
		goto default_lab;
2 7u83 998
	}
999
 
6 7u83 1000
	case exp_value_tag: {
1001
		/* Undefined expressions */
1002
		ENC_make_top(bs);
1003
		break;
2 7u83 1004
	}
1005
 
6 7u83 1006
	default:
1007
default_lab: {
1008
		     /* Simple assignments */
1009
		     int bf = 0;
1010
		     if (cnt) {
1011
			     cnt = 2;
1012
		     }
1013
		     bs = enc_assign_op(bs, t, &bf);
1014
		     if (bf) {
1015
			     /* Bitfield assignment */
1016
			     OFFSET off1 = off;
1017
			     OFFSET off2 = decons_bitf_off(&off1);
1018
			     bs = enc_dummy_exp(bs, t, n, off1, cnt, 0);
1019
			     bs = enc_offset(bs, off2);
1020
		     } else {
1021
			     /* Non-bitfield assignment */
1022
			     bs = enc_dummy_exp(bs, t, n, off, cnt, 0);
1023
		     }
1024
		     if (temp) {
1025
			     /* Introduce temporary variable */
1026
			     ulong m = make_tagdef(NULL_id, t, e, NULL_exp, 1);
1027
			     bs = enc_dummy_exp(bs, t, m, NULL_off, 1, 0);
1028
		     } else {
1029
			     bs = enc_exp(bs, e);
1030
		     }
1031
		     break;
1032
	     }
2 7u83 1033
	}
1034
 
6 7u83 1035
	/* Encode terminator expression */
1036
	if (!IS_NULL_exp(d)) {
1037
		if (array) {
1038
			/* Array elements already handled */
1039
			ENC_make_top(bs);
1040
		} else {
1041
			bs = enc_term_start(bs, n, off, cnt, t, d, context);
1042
		}
2 7u83 1043
	}
6 7u83 1044
	return (bs);
2 7u83 1045
}
1046
 
1047
 
1048
/*
1049
    CREATE A DUMMY INITIALISER EXPRESSION
1050
 
1051
    This routine creates a dummy initialiser expression of type t.
1052
*/
1053
 
6 7u83 1054
EXP
1055
make_dummy_init(TYPE t)
2 7u83 1056
{
6 7u83 1057
	EXP a;
1058
	if (IS_type_array(t)) {
1059
		NAT n = DEREF_nat(type_array_size(t));
1060
		TYPE s = DEREF_type(type_array_sub(t));
1061
		EXP b = make_dummy_init(s);
1062
		MAKE_exp_nof(t, NULL_exp, n, b, NULL_exp, a);
1063
		return (a);
1064
	}
1065
	MAKE_exp_value(t, a);
1066
	return (a);
2 7u83 1067
}
1068
 
1069
 
1070
/*
1071
    ENCODE A GLOBAL INITIALISER EXPRESSION
1072
 
1073
    This routine adds the initialiser expression e for the global variable
1074
    with capsule tag number n and type t to the bitstream bs.  If d is
1075
    not the null expression then the terminator expressions for tag n
1076
    are also initialised.
1077
*/
1078
 
6 7u83 1079
BITSTREAM *
1080
enc_init_global(BITSTREAM *bs, EXP e, EXP d, ulong n, TYPE t)
2 7u83 1081
{
6 7u83 1082
	int i = in_static_init;
1083
	int j = in_dynamic_init;
1084
	int uc = unreached_code;
1085
	unreached_code = 0;
1086
	in_static_init = 1;
1087
	if (IS_exp_dynamic(e) && n != LINK_NONE) {
1088
		/* Dynamic initialisers */
1089
		BITSTREAM *ts;
1090
		EXP a = DEREF_exp(exp_dynamic_arg(e));
1091
		bs = enc_null_exp(bs, t);
1092
		in_static_init = 0;
1093
		in_dynamic_init = 1;
1094
		ts = start_bitstream(NIL(FILE), init_func->link);
1095
		n = link_no(ts, n, VAR_tag);
1096
		ts = enc_init_tag(ts, n, NULL_off, 0, t, a, d, 2);
1097
		init_func = join_bitstreams(init_func, ts);
1098
		if (!IS_NULL_exp(d)) {
1099
			init_no++;
1100
		}
1101
		init_no++;
1102
	} else {
1103
		/* Static initialisers */
1104
		bs = enc_exp(bs, e);
1105
		if (!IS_NULL_exp(d) && n != LINK_NONE) {
1106
			/* Dynamic destructors */
1107
			BITSTREAM *ts;
1108
			EXP a = make_dummy_init(t);
1109
			in_static_init = 0;
1110
			in_dynamic_init = 1;
1111
			ts = start_bitstream(NIL(FILE), init_func->link);
1112
			n = link_no(ts, n, VAR_tag);
1113
			ts = enc_init_tag(ts, n, NULL_off, 0, t, a, d, 2);
1114
			init_func = join_bitstreams(init_func, ts);
1115
			init_no += 2;
1116
			free_exp(a, 1);
1117
		}
2 7u83 1118
	}
6 7u83 1119
	unreached_code = uc;
1120
	in_dynamic_init = j;
1121
	in_static_init = i;
1122
	return (bs);
2 7u83 1123
}
1124
 
1125
 
1126
/*
1127
    ENCODE A LOCAL ASSIGNMENT EXPRESSION
1128
 
1129
    This routine is similar to enc_init_local, but handles assignment
1130
    rather than initialisation.
1131
*/
1132
 
6 7u83 1133
BITSTREAM *
1134
enc_assign_local(BITSTREAM *bs, EXP a, EXP d, ulong n, TYPE t, EXP e)
2 7u83 1135
{
6 7u83 1136
	if (!IS_NULL_exp(e)) {
1137
		BITSTREAM *ts;
1138
		ENC_SEQ_SMALL(bs, 1);
1139
		ts = enc_diag_begin(&bs);
1140
		if (!IS_NULL_exp(d)) {
1141
			ENC_SEQ_SMALL(ts, 1);
1142
		}
1143
		ts = enc_init_tag(ts, n, NULL_off, 0, t, a, d, 1);
1144
		bs = enc_diag_end(bs, ts, e, 1);
1145
	} else {
1146
		unsigned seq = 1;
1147
		if (!IS_NULL_exp(d)) {
1148
			seq++;
1149
		}
1150
		ENC_SEQ_SMALL(bs, seq);
1151
		bs = enc_init_tag(bs, n, NULL_off, 0, t, a, d, 1);
1152
	}
1153
	return (bs);
2 7u83 1154
}
1155
 
1156
 
1157
/*
1158
    ENCODE A LOCAL INITIALISER EXPRESSION
1159
 
1160
    This routine adds the initialiser expression a for the local
1161
    variable with tag number n (in the current unit) and type t to the
1162
    bitstream bs.  e gives the corresponding declaration statement for
1163
    use with diagnostics.
1164
*/
1165
 
6 7u83 1166
BITSTREAM *
1167
enc_init_local(BITSTREAM *bs, EXP a, EXP d, ulong n, TYPE t, EXP e)
2 7u83 1168
{
6 7u83 1169
	if (n != LINK_NONE) {
1170
		switch (TAG_exp(a)) {
1171
		case exp_constr_tag:
1172
		case exp_dynamic_tag:
1173
dynamic_label: {
1174
		       /* Explicit initialisation */
1175
		       ENC_make_value(bs);
1176
		       bs = enc_shape(bs, t);
1177
		       bs = enc_assign_local(bs, a, d, n, t, e);
1178
		       return (bs);
1179
	       }
1180
		case exp_aggregate_tag:
1181
		case exp_nof_tag: {
1182
			/* Explicitly initialise in non-constant cases */
1183
			if (!is_const_exp(a, -1)) {
1184
				goto dynamic_label;
1185
			}
1186
			break;
1187
		}
1188
		case exp_paren_tag:
1189
		case exp_copy_tag: {
1190
			/* Parenthesised expressions */
1191
			a = DEREF_exp(exp_paren_etc_arg(a));
1192
			bs = enc_init_local(bs, a, d, n, t, e);
1193
			return (bs);
1194
		}
1195
		default : {
1196
			if (!IS_NULL_exp(d)) {
1197
				goto dynamic_label;
1198
			}
1199
			break;
1200
		}
1201
		}
2 7u83 1202
	}
6 7u83 1203
	if (!IS_NULL_exp(e)) {
1204
		BITSTREAM *ts = enc_diag_begin(&bs);
1205
		ts = enc_exp(ts, a);
1206
		bs = enc_diag_end(bs, ts, e, 1);
1207
	} else {
1208
		bs = enc_exp(bs, a);
1209
	}
1210
	return (bs);
2 7u83 1211
}
1212
 
1213
 
1214
/*
1215
    IS AN EXPRESSION A COMPLEX ASSIGNEE?
1216
 
1217
    This routine checks whether the expression a, which forms the right hand
1218
    side of an assignment, requires the use of enc_init_tag rather than a
1219
    simple assignment operation.
1220
*/
1221
 
6 7u83 1222
int
1223
is_init_complex(EXP a)
2 7u83 1224
{
6 7u83 1225
	switch (TAG_exp(a)) {
1226
	case exp_constr_tag:
1227
	case exp_dynamic_tag:
1228
	case exp_aggregate_tag:
1229
	case exp_string_lit_tag:
1230
	case exp_nof_tag: {
1231
		/* These are the complex cases */
1232
		return (1);
2 7u83 1233
	}
6 7u83 1234
	case exp_paren_tag:
1235
	case exp_copy_tag: {
1236
		a = DEREF_exp(exp_paren_etc_arg(a));
1237
		return (is_init_complex(a));
2 7u83 1238
	}
6 7u83 1239
	}
1240
	return (0);
2 7u83 1241
}
1242
 
1243
 
1244
/*
1245
    ENCODE A GLOBAL TERMINATOR EXPRESSION
1246
 
1247
    This routine adds a termination expression e for the object with
1248
    capsule tag number n and type t to the termination function ts.  If m
1249
    is not LINK_NONE then it is the capsule tag number of a flag which
1250
    needs to be checked before the termination expression is called.
1251
    Note that the terminations are done in the reverse order to the
1252
    initialisations.
1253
*/
1254
 
6 7u83 1255
BITSTREAM *
1256
enc_term_global(BITSTREAM *ts, ulong n, TYPE t, EXP e, ulong m)
2 7u83 1257
{
6 7u83 1258
	if (!IS_NULL_exp(e)) {
1259
		BITSTREAM *bs;
1260
		int uc = unreached_code;
1261
		unreached_code = 0;
1262
		bs = start_bitstream(NIL(FILE), ts->link);
1263
		n = link_no(bs, n, VAR_tag);
1264
		if (m == LINK_NONE) {
1265
			/* Simple case */
1266
			bs = enc_term_local(bs, n, NULL_off, 0, t, e, 2);
1267
		} else {
1268
			/* Check flag before call */
1269
			m = link_no(bs, m, VAR_tag);
1270
			bs = enc_flag_test(bs, m,(unsigned)1, 0, ntest_not_eq);
1271
			bs = enc_term_local(bs, n, NULL_off, 0, t, e, 2);
1272
			ENC_make_top(bs);
1273
		}
1274
		ts = join_bitstreams(bs, ts);
1275
		unreached_code = uc;
2 7u83 1276
	}
6 7u83 1277
	return (ts);
2 7u83 1278
}
1279
 
1280
 
1281
/*
1282
    ENCODE A LOCAL TERMINATOR EXPRESSION
1283
 
1284
    This routine adds a termination expression e for the object with local
1285
    tag number n and type t to the bitstream bs.  context is 2 for global
1286
    variables, 1, 3 or 4 for local variables, and 0 in destructors and
1287
    deallocation expressions.  For local variables the result consists
1288
    of two TDF expressions (including terminator variable adjustment).
1289
    Otherwise the result is a single expression.
1290
*/
1291
 
6 7u83 1292
BITSTREAM *
1293
enc_term_local(BITSTREAM *bs, ulong n, OFFSET off, int cnt, TYPE t, EXP e,
1294
	       int context)
2 7u83 1295
{
6 7u83 1296
	/* Allow for parenthesised expressions */
1297
	EXP a = NULL_exp;
1298
	EXP c = NULL_exp;
1299
	unsigned tops = 0;
1300
	while (IS_exp_paren_etc(e)) {
1301
		e = DEREF_exp(exp_paren_etc_arg(e));
1302
	}
2 7u83 1303
 
6 7u83 1304
	/* Check for array destructors */
1305
	if (IS_type_array(t)) {
1306
		TYPE r = t;
1307
		EXP d = sizeof_array(&r, type_sint);
1308
		switch (context) {
1309
		case 1:
1310
		case 3:
1311
		case 4: {
1312
			/* Local variables */
1313
			tops = 1;
1314
			break;
1315
		}
1316
		}
1317
		if (IS_NULL_exp(d) || is_zero_exp(d)) {
1318
			/* Zero sized arrays */
1319
			tops++;
1320
		} else {
1321
			/* Non-trivial arrays */
1322
			int calc = 1;
1323
			ulong dn = LINK_NONE;
1324
			unsigned seq = tops + 2;
1325
			ulong ptr = unit_no(bs, NULL_id, VAR_tag, 1);
1326
			ulong end = unit_no(bs, NULL_id, VAR_tag, 1);
1327
			ulong lab = unit_no(bs, NULL_id, VAR_label, 1);
1328
			bs = enc_loop_decl(bs, ptr, n, r, cnt, off, t);
1329
			bs = enc_loop_decl(bs, end, n, r, cnt, off, NULL_type);
1330
			while (IS_exp_nof(e)) {
1331
				/* Step over array destructors */
1332
				e = DEREF_exp(exp_nof_pad(e));
1333
			}
1334
			if (context != 2) {
1335
				/* Declare counter */
1336
				bs = enc_count_decl(bs, e, t, &dn);
1337
				seq++;
1338
			}
1339
			if (IS_exp_int_lit(d)) {
1340
				/* Check whether dimensions are constant */
1341
				NAT m = DEREF_nat(exp_int_lit_nat(d));
1342
				if (!IS_nat_calc(m)) {
1343
					calc = 0;
1344
				}
1345
			}
1346
			if (calc) {
1347
				/* Check for calculated bounds */
1348
				ulong lab2 = unit_no(bs, NULL_id, VAR_label, 1);
1349
				ENC_conditional(bs);
1350
				ENC_make_label(bs, lab2);
1351
				ENC_SEQ_SMALL(bs, 1);
1352
				bs = enc_loop_test(bs, ptr, end, r, lab2,
1353
						   ntest_greater);
1354
				tops++;
1355
			}
1356
			ENC_repeat(bs);
1357
			ENC_make_label(bs, lab);
1358
			ENC_make_top(bs);
1359
			ENC_SEQ_SMALL(bs, seq);
1360
			bs = enc_loop_incr(bs, ptr, r, 1);
1361
			if (context != 2) {
1362
				/* Decrease counter */
1363
				bs = enc_count_incr(bs, e, 1, r);
1364
			}
1365
			bs = enc_term_local(bs, ptr, NULL_off, 1, r, e,
1366
					    context);
1367
			bs = enc_loop_test(bs, ptr, end, r, lab, ntest_eq);
1368
			enc_count_end(e, dn);
1369
		}
1370
		while (tops) {
1371
			ENC_make_top(bs);
1372
			tops--;
1373
		}
1374
		return (bs);
2 7u83 1375
	}
6 7u83 1376
 
1377
	/* Simple destructor calls */
1378
	if (IS_exp_destr(e)) {
1379
		a = DEREF_exp(exp_destr_obj(e));
1380
		COPY_ulong(exp_dummy_no(a), n);
1381
		COPY_off(exp_dummy_off(a), off);
1382
		COPY_int(exp_dummy_cont(a), 2 * cnt);
1383
		c = DEREF_exp(exp_destr_count(e));
1384
		e = DEREF_exp(exp_destr_call(e));
2 7u83 1385
	}
6 7u83 1386
	switch (context) {
1387
	case 1:
1388
	case 3: {
1389
		/* Local variable */
1390
		if (!IS_NULL_exp(c)) {
1391
			BITSTREAM *ts;
1392
			bs = enc_special(bs, TOK_destr_end);
1393
			ts = start_bitstream(NIL(FILE), bs->link);
1394
			ts = enc_exp(ts, c);
1395
			bs = enc_bitstream(bs, ts);
1396
		} else {
1397
			tops = 1;
1398
		}
1399
		break;
2 7u83 1400
	}
6 7u83 1401
	case 4: {
1402
		/* Explicitly initialised local variable */
1403
		if (!IS_NULL_exp(c)) {
1404
			/* Check for initialisation */
1405
			BITSTREAM *ts;
1406
			ulong lab = unit_no(bs, NULL_id, VAR_label, 1);
1407
			ENC_conditional(bs);
1408
			ENC_make_label(bs, lab);
1409
			ENC_SEQ_SMALL(bs, 2);
1410
			bs = enc_special(bs, TOK_destr_test);
1411
			ts = start_bitstream(NIL(FILE), bs->link);
1412
			ts = enc_exp(ts, c);
1413
			ENC_make_label(ts, lab);
1414
			bs = enc_bitstream(bs, ts);
1415
			bs = enc_special(bs, TOK_destr_end);
1416
			ts = start_bitstream(NIL(FILE), bs->link);
1417
			ts = enc_exp(ts, c);
1418
			bs = enc_bitstream(bs, ts);
1419
			tops = 2;
1420
		} else {
1421
			tops = 1;
1422
		}
1423
		break;
2 7u83 1424
	}
6 7u83 1425
	case 5: {
1426
		/* Partial destructor count */
1427
		ulong m = last_params[DUMMY_count];
1428
		bs = enc_flag_test(bs, m,(unsigned)1, 0, ntest_not_eq);
1429
		bs = enc_destr_count(bs, t, 1);
1430
		break;
2 7u83 1431
	}
1432
	}
6 7u83 1433
	bs = enc_exp(bs, e);
1434
	if (!IS_NULL_exp(a)) {
1435
		/* Reset dummy expression */
1436
		COPY_off(exp_dummy_off(a), NULL_off);
1437
	}
1438
	while (tops) {
1439
		/* End any conditionals */
1440
		ENC_make_top(bs);
1441
		tops--;
1442
	}
1443
	return (bs);
2 7u83 1444
}
1445
 
1446
 
1447
/*
1448
    ALLOCATION ROUTINES
1449
 
1450
    The memory allocation routines are only included in the C++ producer.
1451
*/
1452
 
1453
#if LANGUAGE_CPP
1454
 
1455
 
1456
/*
1457
    ENCODE A NEW-INITIALISER EXPRESSION
1458
 
1459
    This routine adds the initialisation of the tag n, obtained from a
1460
    call to an allocation function, with the expression a to the bitstream
1461
    bs.  If d is not the null expression then any exceptions thrown by a
1462
    must be caught and the allocated memory freed using d.
1463
*/
1464
 
6 7u83 1465
static BITSTREAM *
1466
enc_init_new(BITSTREAM *bs, ulong n, EXP a, EXP d)
2 7u83 1467
{
6 7u83 1468
	EXP a0 = new_try_body(a);
1469
	EXP a1 = DEREF_exp(exp_assign_ref(a0));
1470
	EXP a2 = DEREF_exp(exp_assign_arg(a0));
1471
	COPY_ulong(exp_dummy_no(a1), n);
1472
	if (IS_NULL_exp(d)) {
1473
		/* Simple initialisation */
1474
		a = DEREF_exp(exp_try_block_body(a));
1475
		bs = enc_stmt(bs, a);
2 7u83 1476
	} else {
6 7u83 1477
		/* Initialisation with deletion */
1478
		int uc;
1479
		ulong ex;
1480
		TYPE s = NULL_type;
1481
		ulong ptr = LINK_NONE;
1482
		ulong prev = alloc_counter;
1483
		TYPE t = DEREF_type(exp_type(a2));
1484
		EXP b = DEREF_exp(exp_dealloc_term(d));
1485
		if (IS_exp_nof(a2) && !IS_NULL_exp(b)) {
1486
			/* Declare array initialisation counter */
1487
			s = DEREF_type(type_array_sub(t));
1488
			ptr = unit_no(bs, NULL_id, VAR_tag, 1);
1489
			alloc_counter = ptr;
1490
			bs = enc_loop_decl(bs, ptr, n, s, 1, NULL_off,
1491
					   NULL_type);
1492
		} else {
1493
			alloc_counter = LINK_NONE;
1494
		}
1495
		bs = enc_try_start(bs, &ex,(unsigned)2);
1496
		COPY_ulong(exp_try_block_no(a), ex);
1497
		a = DEREF_exp(exp_try_block_body(a));
1498
		bs = enc_stmt(bs, a);
1499
		bs = enc_try_end(bs, ex);
1500
		uc = unreached_code;
1501
		if (ptr == LINK_NONE) {
1502
			ENC_SEQ_SMALL(bs, 1);
1503
		} else {
1504
			/* Destroy a partially constructed array */
1505
			EXP b1 = b;
1506
			ulong lab1 = unit_no(bs, NULL_id, VAR_label, 1);
1507
			ulong lab2 = unit_no(bs, NULL_id, VAR_label, 1);
1508
			ENC_SEQ_SMALL(bs, 2);
1509
			ENC_conditional(bs);
1510
			ENC_make_label(bs, lab1);
1511
			ENC_SEQ_SMALL(bs, 1);
1512
			bs = enc_loop_test(bs, ptr, n, s, lab1, ntest_not_eq);
1513
			ENC_repeat(bs);
1514
			ENC_make_label(bs, lab2);
1515
			ENC_make_top(bs);
1516
			ENC_SEQ_SMALL(bs, 2);
1517
			bs = enc_loop_incr(bs, ptr, s, 1);
1518
			if (IS_exp_nof(b1)) {
1519
				b1 = DEREF_exp(exp_nof_pad(b1));
1520
			}
1521
			bs = enc_term_local(bs, ptr, NULL_off, 1, s, b1, 0);
1522
			bs = enc_loop_test(bs, ptr, n, s, lab2, ntest_eq);
1523
			ENC_make_top(bs);
1524
		}
1525
		COPY_exp(exp_dealloc_term(d), NULL_exp);
1526
		bs = enc_dealloc(bs, d, n);
1527
		COPY_exp(exp_dealloc_term(d), b);
1528
		bs = enc_rethrow(bs);
1529
		alloc_counter = prev;
1530
		unreached_code = uc;
2 7u83 1531
	}
6 7u83 1532
	return (bs);
2 7u83 1533
}
1534
 
1535
 
1536
/*
1537
    ENCODE AN ALLOCATION EXPRESSION
1538
 
1539
    This routine adds the allocation expression e to the bitstream bs.
1540
*/
1541
 
6 7u83 1542
BITSTREAM *
1543
enc_alloc(BITSTREAM *bs, EXP e)
2 7u83 1544
{
6 7u83 1545
	EXP a = DEREF_exp(exp_alloc_call(e));
1546
	EXP b = DEREF_exp(exp_alloc_init(e));
1547
	EXP c = DEREF_exp(exp_alloc_size(e));
1548
	EXP d = DEREF_exp(exp_alloc_garbage(e));
1549
	if (IS_NULL_exp(b) && IS_NULL_exp(c)) {
1550
		/* Simple case */
1551
		bs = enc_exp(bs, a);
1552
	} else {
1553
		/* Complex case */
1554
		ulong n;
1555
		ulong lab;
1556
		int bf = 0;
1557
		unsigned seq = 0;
1558
		EXP c1 = NULL_exp;
1559
		DECL_SPEC ds = dspec_none;
1560
		TYPE t = DEREF_type(exp_type(a));
1561
		TYPE s = DEREF_type(type_ptr_sub(t));
1562
		LIST(TYPE)throws = NULL_list(TYPE);
2 7u83 1563
 
6 7u83 1564
		/* Check exception deallocator */
1565
		if (!IS_NULL_exp(b)) {
1566
			throws = DEREF_list(exp_try_block_ttypes(b));
1567
			seq = 1;
2 7u83 1568
		}
6 7u83 1569
		if (!IS_NULL_exp(d)) {
1570
			EXP d1 = DEREF_exp(exp_dealloc_call(d));
1571
			EXP d2 = DEREF_exp(exp_dealloc_size(d));
1572
			if (IS_NULL_exp(d1) && IS_NULL_exp(d2)) {
1573
				d = NULL_exp;
1574
			} else if (output_except && output_partial) {
1575
				if (!IS_NULL_list(throws)) {
1576
					ds = dspec_mutable;
1577
				} else {
1578
					d = NULL_exp;
1579
				}
1580
			} else {
1581
				d = NULL_exp;
1582
			}
1583
		}
2 7u83 1584
 
6 7u83 1585
		/* Introduce identity for non-constant array size */
1586
		if (!IS_NULL_exp(c)) {
1587
			c1 = DEREF_exp(exp_dummy_value(c));
1588
			if (!IS_exp_int_lit(c1)) {
1589
				n = unit_no(bs, NULL_id, VAR_tag, 1);
1590
				COPY_exp(exp_dummy_value(c), NULL_exp);
1591
				COPY_ulong(exp_dummy_no(c), n);
1592
				ENC_identify(bs);
1593
				bs = enc_access(bs, dspec_none);
1594
				ENC_make_tag(bs, n);
1595
				bs = enc_exp(bs, c1);
1596
			}
1597
			seq += 2;
1598
		}
2 7u83 1599
 
6 7u83 1600
		/* Introduce variable for call to allocation function */
1601
		n = unit_no(bs, NULL_id, VAR_tag, 1);
1602
		ENC_variable(bs);
1603
		bs = enc_access(bs, ds);
1604
		ENC_make_tag(bs, n);
1605
		bs = enc_exp(bs, a);
1606
		ENC_SEQ_SMALL(bs, 1);
2 7u83 1607
 
6 7u83 1608
		/* Check for null pointers */
1609
		lab = unit_no(bs, NULL_id, VAR_label, 1);
1610
		ENC_conditional(bs);
1611
		ENC_make_label(bs, lab);
1612
		if (seq) {
1613
			ENC_SEQUENCE(bs, seq);
1614
		}
1615
		bs = enc_loop_test(bs, n, LINK_NONE, s, lab, ntest_not_eq);
2 7u83 1616
 
6 7u83 1617
		/* Deal with array dimensions */
1618
		if (!IS_NULL_exp(c)) {
1619
			/* Assign array size */
1620
			BITSTREAM *ts;
1621
			TYPE tz = type_size_t;
1622
			TYPE tc = DEREF_type(exp_type(c));
1623
			ENC_assign(bs);
1624
			bs = enc_special(bs, TOK_ptr_to_ptr);
1625
			ts = start_bitstream(NIL(FILE), bs->link);
1626
			ts = enc_alignment(ts, s);
1627
			ts = enc_alignment(ts, tz);
1628
			ts = enc_cont_op(ts, t, &bf);
1629
			ts = enc_shape(ts, t);
1630
			ENC_obtain_tag(ts);
1631
			ENC_make_tag(ts, n);
1632
			bs = enc_bitstream(bs, ts);
1633
			if (!eq_type_rep(tc, tz, 0)) {
1634
				/* Cast array size to size_t */
1635
				ENC_change_variety(bs);
1636
				bs = enc_error_treatment(bs, tz);
1637
				bs = enc_variety(bs, tz);
1638
			}
1639
			bs = enc_exp(bs, c);
2 7u83 1640
 
6 7u83 1641
			/* Increase pointer */
1642
			bs = enc_assign_op(bs, t, &bf);
1643
			ENC_obtain_tag(bs);
1644
			ENC_make_tag(bs, n);
1645
			ENC_add_to_ptr(bs);
1646
			bs = enc_cont_op(bs, t, &bf);
1647
			bs = enc_shape(bs, t);
1648
			ENC_obtain_tag(bs);
1649
			ENC_make_tag(bs, n);
1650
			bs = enc_extra_offset(bs, s, off_size_t, 1);
1651
		}
2 7u83 1652
 
6 7u83 1653
		/* Call initialiser */
1654
		if (!IS_NULL_exp(b)) {
1655
			bs = enc_init_new(bs, n, b, d);
1656
		}
1657
		ENC_make_top(bs);
2 7u83 1658
 
6 7u83 1659
		/* Evaluate result */
1660
		bs = enc_cont_op(bs, t, &bf);
1661
		bs = enc_shape(bs, t);
1662
		ENC_obtain_tag(bs);
1663
		ENC_make_tag(bs, n);
1664
		if (!IS_NULL_exp(c1)) {
1665
			/* Restore size value */
1666
			COPY_exp(exp_dummy_value(c), c1);
1667
		}
1668
		ASSERT(bf == 0);
2 7u83 1669
	}
6 7u83 1670
	return (bs);
2 7u83 1671
}
1672
 
1673
 
1674
/*
1675
    ENCODE A DEALLOCATION EXPRESSION
1676
 
1677
    This routine adds the deallocation expression e to the bitstream bs.
1678
    If the argument is already stored in a tag then this is given by n.
1679
*/
1680
 
6 7u83 1681
BITSTREAM *
1682
enc_dealloc(BITSTREAM *bs, EXP e, ulong n)
2 7u83 1683
{
6 7u83 1684
	EXP a = DEREF_exp(exp_dealloc_call(e));
1685
	EXP b = DEREF_exp(exp_dealloc_term(e));
1686
	EXP c = DEREF_exp(exp_dealloc_size(e));
1687
	EXP d = DEREF_exp(exp_dealloc_arg(e));
1688
	EXP d1 = DEREF_exp(exp_dummy_value(d));
2 7u83 1689
 
6 7u83 1690
	/* Use given tag if necessary */
1691
	int var = 1;
1692
	if (n != LINK_NONE) {
1693
		COPY_exp(exp_dummy_value(d), NULL_exp);
1694
		COPY_ulong(exp_dummy_no(d), n);
1695
		var = 0;
1696
	}
2 7u83 1697
 
6 7u83 1698
	if (IS_NULL_exp(b) && IS_NULL_exp(c)) {
1699
		/* Simple case */
1700
		bs = enc_exp(bs, a);
2 7u83 1701
 
6 7u83 1702
	} else {
1703
		/* Complex case */
1704
		NAT i;
1705
		TYPE t = DEREF_type(exp_type(d));
1706
		TYPE s = DEREF_type(type_ptr_sub(t));
2 7u83 1707
 
6 7u83 1708
		/* Check for virtual deallocators (see make_delete_exp) */
1709
		if (!IS_NULL_exp(a) && IS_exp_paren(a)) {
1710
			if (!IS_NULL_exp(b)) {
1711
				a = NULL_exp;
1712
			}
1713
		}
2 7u83 1714
 
6 7u83 1715
		/* Introduce variable for deallocation argument */
1716
		if (var) {
1717
			unsigned seq = 2;
1718
			ulong lab = unit_no(bs, NULL_id, VAR_label, 1);
1719
			n = unit_no(bs, NULL_id, VAR_tag, 1);
1720
			COPY_exp(exp_dummy_value(d), NULL_exp);
1721
			COPY_ulong(exp_dummy_no(d), n);
1722
			ENC_variable(bs);
1723
			bs = enc_access(bs, dspec_none);
1724
			ENC_make_tag(bs, n);
1725
			bs = enc_exp(bs, d1);
2 7u83 1726
 
6 7u83 1727
			/* Check for null pointers */
1728
			if (!IS_NULL_exp(c)) {
1729
				seq = 1;
1730
			}
1731
			ENC_conditional(bs);
1732
			ENC_make_label(bs, lab);
1733
			ENC_SEQ_SMALL(bs, seq);
1734
			bs = enc_loop_test(bs, n, LINK_NONE, s, lab,
1735
					   ntest_not_eq);
1736
		} else {
1737
			if (IS_NULL_exp(c))ENC_SEQ_SMALL(bs, 1);
1738
		}
2 7u83 1739
 
6 7u83 1740
		/* Introduce identity for array size */
1741
		if (!IS_NULL_exp(c)) {
1742
			if (IS_exp_dummy(c)) {
1743
				int bf = 0;
1744
				BITSTREAM *ts;
1745
				TYPE tz = type_size_t;
1746
				ulong m = unit_no(bs, NULL_id, VAR_tag, 1);
1747
				COPY_ulong(exp_dummy_no(c), m);
2 7u83 1748
 
6 7u83 1749
				/* Find array size */
1750
				ENC_identify(bs);
1751
				bs = enc_access(bs, dspec_none);
1752
				ENC_make_tag(bs, m);
1753
				ENC_contents(bs);
1754
				bs = enc_shape(bs, tz);
1755
				bs = enc_special(bs, TOK_ptr_to_ptr);
1756
				ts = start_bitstream(NIL(FILE), bs->link);
1757
				ts = enc_alignment(ts, s);
1758
				ts = enc_alignment(ts, tz);
1759
				ENC_add_to_ptr(ts);
1760
				ts = enc_cont_op(ts, t, &bf);
1761
				ts = enc_shape(ts, t);
1762
				ENC_obtain_tag(ts);
1763
				ENC_make_tag(ts, n);
1764
				ts = enc_extra_offset(ts, s, off_size_t, -1);
1765
				bs = enc_bitstream(bs, ts);
1766
				ASSERT(bf == 0);
1767
			}
2 7u83 1768
 
6 7u83 1769
			/* Construct dummy array type */
1770
			if (!IS_NULL_exp(b)) {
1771
				MAKE_nat_calc(c, i);
1772
				MAKE_type_array(cv_none, s, i, s);
1773
				ENC_SEQ_SMALL(bs, 1);
1774
			}
1775
		}
2 7u83 1776
 
6 7u83 1777
		/* Encode destructors */
1778
		if (!IS_NULL_exp(b)) {
1779
			bs = enc_term_local(bs, n, NULL_off, 1, s, b, 0);
1780
			if (!IS_NULL_exp(c)) {
1781
				/* Destroy dummy array type */
1782
				ulong tok;
1783
				CV_SPEC cv;
1784
				IDENTIFIER tid;
1785
				DESTROY_type_array(destroy, cv, tid, s, i, s);
1786
				DESTROY_nat_calc(destroy, c, tok, i);
1787
				UNUSED(tok);
1788
				UNUSED(tid);
1789
				UNUSED(cv);
1790
				UNUSED(c);
1791
				UNUSED(s);
1792
			}
1793
		}
2 7u83 1794
 
6 7u83 1795
		/* Encode deallocation function call */
1796
		bs = enc_exp(bs, a);
1797
		if (var) {
1798
			/* End conditional */
1799
			ENC_make_top(bs);
1800
		}
2 7u83 1801
	}
6 7u83 1802
	COPY_exp(exp_dummy_value(d), d1);
1803
	return (bs);
2 7u83 1804
}
1805
 
1806
 
1807
#endif /* LANGUAGE_CPP */
1808
#endif /* TDF_OUTPUT */