Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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