Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997, 1998
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 "graph_ops.h"
37
#include "hashid_ops.h"
38
#include "id_ops.h"
39
#include "itype_ops.h"
40
#include "member_ops.h"
41
#include "nspace_ops.h"
42
#include "off_ops.h"
43
#include "type_ops.h"
44
#include "virt_ops.h"
45
#include "error.h"
46
#include "tdf.h"
47
#include "allocate.h"
48
#include "basetype.h"
49
#include "buffer.h"
50
#include "capsule.h"
51
#include "check.h"
52
#include "chktype.h"
53
#include "class.h"
54
#include "compile.h"
55
#include "constant.h"
56
#include "construct.h"
57
#include "derive.h"
58
#include "destroy.h"
59
#include "encode.h"
60
#include "exp.h"
61
#include "function.h"
62
#include "hash.h"
63
#include "init.h"
64
#include "initialise.h"
65
#include "interface.h"
66
#include "mangle.h"
67
#include "member.h"
68
#include "namespace.h"
69
#include "print.h"
70
#include "shape.h"
71
#include "struct.h"
72
#include "syntax.h"
73
#include "tok.h"
74
#include "token.h"
75
#include "virtual.h"
76
#if TDF_OUTPUT
77
 
78
 
79
/*
80
    CLASS AND GRAPH TOKEN NUMBERS
81
 
82
    Each node of a base class graph has three associated token numbers.
83
    The use of these numbers varies depending on whether the node is
84
    the top node of a graph, a virtual base class, or a non-virtual base
85
    class.  These macros give mnemonic values for these uses.  Names are
86
    also given to the various class type token numbers.
87
*/
88
 
89
#define ctype_shape( A )	ctype_tok1 ( ( A ) )
90
#define ctype_null_exp( A )	ctype_tok2 ( ( A ) )
91
#define graph_al_tag( A )	graph_tok1 ( ( A ) )
92
#define graph_core_off( A )	graph_tok2 ( ( A ) )
93
#define graph_base_off( A )	graph_tok1 ( ( A ) )
94
#define graph_real_off( A )	graph_tok2 ( ( A ) )
95
 
96
 
97
/*
98
    DUMMY CLASS TYPE
99
 
100
    These types are dummies used in the class layout routines.
101
*/
102
 
103
TYPE dummy_class = NULL_type ;
104
TYPE dummy_vtab = NULL_type ;
105
TYPE dummy_count = NULL_type ;
106
TYPE ptr_dummy_class = NULL_type ;
107
TYPE ptr_dummy_vtab = NULL_type ;
108
TYPE dummy_func = NULL_type ;
109
ulong size_dummy_vtab = 0 ;
110
OFFSET off_size_t = NULL_off ;
111
IDENTIFIER dummy_type_name = NULL_id ;
112
 
113
 
114
/*
115
    ENCODE AN EXPRESSION TOKEN APPLICATION
116
 
117
    This routine adds an application of the simple expression token n to
118
    the bitstream bs.
119
*/
120
 
121
static BITSTREAM *enc_exp_token
122
    PROTO_N ( ( bs, n ) )
123
    PROTO_T ( BITSTREAM *bs X ulong n )
124
{
125
    ulong m = link_no ( bs, n, VAR_token ) ;
126
    ENC_exp_apply_token ( bs ) ;
127
    ENC_make_tok ( bs, m ) ;
128
    ENC_LEN_SMALL ( bs, 0 ) ;
129
    return ( bs ) ;
130
}
131
 
132
 
133
/*
134
    ENCODE A SHAPE TOKEN APPLICATION
135
 
136
    This routine adds an application of the simple shape token n to the
137
    bitstream bs.
138
*/
139
 
140
static BITSTREAM *enc_shape_token
141
    PROTO_N ( ( bs, n ) )
142
    PROTO_T ( BITSTREAM *bs X ulong n )
143
{
144
    ulong m = link_no ( bs, n, VAR_token ) ;
145
    ENC_shape_apply_token ( bs ) ;
146
    ENC_make_tok ( bs, m ) ;
147
    ENC_LEN_SMALL ( bs, 0 ) ;
148
    return ( bs ) ;
149
}
150
 
151
 
152
/*
153
    VIRTUAL FUNCTION TABLE ROUTINES
154
 
155
    The virtual function table and run-time type information routines are
156
    only included in the C++ producer.
157
*/
158
 
159
#if LANGUAGE_CPP
160
 
161
 
162
/*
163
    ENCODE A BUFFER AS A STRING LITERAL
164
 
165
    This routine adds the contents of the buffer bf to the bitstream bs
166
    as a string literal.
167
*/
168
 
169
static BITSTREAM *enc_buffer
170
    PROTO_N ( ( bs, bf ) )
171
    PROTO_T ( BITSTREAM *bs X BUFFER *bf )
172
{
173
    string s = bf->start ;
174
    unsigned long n = ( unsigned long ) ( bf->posn - s ) ;
175
 
176
    /* Declare the string literal */
177
    ulong m = capsule_no ( NULL_string, VAR_tag ) ;
178
    BITSTREAM *ts = enc_tagdec_start ( NULL_id, m, NULL_type, 1 ) ;
179
    ENC_nof ( ts ) ;
180
    ENC_make_nat ( ts ) ;
181
    ENC_INT ( ts, n ) ;
182
    ts = enc_shape ( ts, type_char ) ;
183
    enc_tagdec_end ( ts ) ;
184
 
185
    /* Define the string literal */
186
    ts = enc_tagdef_start ( NULL_id, m, NULL_type, 1 ) ;
187
    ENC_make_nof_int ( ts ) ;
188
    ts = enc_variety ( ts, type_char ) ;
189
    ENC_make_string ( ts ) ;
190
    ts = enc_tdfstring ( ts, n, s ) ;
191
    enc_tagdef_end ( ts ) ;
192
 
193
    /* Encode the result */
194
    m = link_no ( bs, m, VAR_tag ) ;
195
    ENC_obtain_tag ( bs ) ;
196
    ENC_make_tag ( bs, m ) ;
197
    return ( bs ) ;
198
}
199
 
200
 
201
/*
202
    ENCODE RUN-TIME BASE CLASS INFORMATION
203
 
204
    This routine defines the run-time base class information for the base
205
    classes br or the sub-types pt and adds the address of the first base
206
    to bs.
207
*/
208
 
209
static BITSTREAM *enc_rtti_bases
210
    PROTO_N ( ( bs, br, pt, sz ) )
211
    PROTO_T ( BITSTREAM *bs X LIST ( GRAPH ) br X LIST ( TYPE ) pt X NAT sz )
212
{
213
    TYPE t ;
214
    ulong n, m ;
215
    BITSTREAM *ts, *us ;
216
    int a = INFO_public ;
217
 
218
    if ( !IS_NULL_list ( br ) ) {
219
	/* Get base class information */
220
	VIRTUAL vt ;
221
	CLASS_TYPE ct ;
222
	GRAPH gr = DEREF_graph ( HEAD_list ( br ) ) ;
223
	DECL_SPEC acc = DEREF_dspec ( graph_access ( gr ) ) ;
224
	br = TAIL_list ( br ) ;
225
 
226
	/* Find base class information */
227
	ct = DEREF_ctype ( graph_head ( gr ) ) ;
228
	t = make_class_type ( ct ) ;
229
	vt = DEREF_virt ( ctype_virt ( ct ) ) ;
230
	if ( !IS_NULL_virt ( vt ) ) {
231
	    /* Make sure base class is declared */
232
	    int used = DEREF_int ( virt_table_rtti_used ( vt ) ) ;
233
	    if ( !used ) {
234
		IDENTIFIER cid = DEREF_id ( ctype_name ( ct ) ) ;
235
		COPY_int ( virt_table_rtti_used ( vt ), 1 ) ;
236
		compile_virtual ( ct, !has_linkage ( cid ) ) ;
237
	    }
238
	}
239
	if ( acc & dspec_virtual ) sz = small_nat [1] ;
240
	acc &= dspec_access ;
241
	if ( acc == dspec_protected ) {
242
	    a = INFO_protected ;
243
	} else if ( acc == dspec_private ) {
244
	    a = INFO_private ;
245
	}
246
	m = DEREF_ulong ( graph_base_off ( gr ) ) ;
247
 
248
    } else if ( !IS_NULL_list ( pt ) ) {
249
	/* Get sub-type information */
250
	t = DEREF_type ( HEAD_list ( pt ) ) ;
251
	pt = TAIL_list ( pt ) ;
252
	if ( !IS_NULL_type ( t ) ) {
253
	    CV_SPEC cv = DEREF_cv ( type_qual ( t ) ) ;
254
	    if ( IS_type_func ( t ) ) {
255
		/* Allow for function qualifiers */
256
		cv = DEREF_cv ( type_func_mqual ( t ) ) ;
257
	    }
258
	    if ( cv ) {
259
		if ( cv & cv_const ) a |= INFO_const ;
260
		if ( cv & cv_volatile ) a |= INFO_volatile ;
261
		t = qualify_type ( t, cv_none, 0 ) ;
262
	    }
263
	}
264
	m = LINK_NONE ;
265
 
266
    } else {
267
	/* Output end of list */
268
	ENC_make_null_ptr ( bs ) ;
269
	ENC_alignment ( bs ) ;
270
	bs = enc_special ( bs, TOK_baseid_type ) ;
271
	return ( bs ) ;
272
    }
273
 
274
    /* Declare base structure */
275
    n = capsule_no ( NULL_string, VAR_tag ) ;
276
    ts = enc_tagdec_start ( NULL_id, n, NULL_type, 1 ) ;
277
    ts = enc_special ( ts, TOK_baseid_type ) ;
278
    enc_tagdec_end ( ts ) ;
279
 
280
    /* Define base structure */
281
    ts = enc_tagdef_start ( NULL_id, n, NULL_type, 1 ) ;
282
    ts = enc_special ( ts, TOK_baseid_make ) ;
283
    us = start_bitstream ( NIL ( FILE ), ts->link ) ;
284
    us = enc_rtti_type ( us, t, lex_typeid ) ;
285
    if ( m == LINK_NONE ) {
286
	ENC_offset_zero ( us ) ;
287
	us = enc_alignment ( us, type_sint ) ;
288
    } else {
289
	us = enc_exp_token ( us, m ) ;
290
    }
291
    us = enc_rtti_bases ( us, br, pt, NULL_nat ) ;
292
    us = enc_make_snat ( us, a ) ;
293
    us = enc_snat ( us, sz, 0, 0 ) ;
294
    ts = enc_bitstream ( ts, us ) ;
295
    enc_tagdef_end ( ts ) ;
296
 
297
    /* Encode the result */
298
    n = link_no ( bs, n, VAR_tag ) ;
299
    ENC_obtain_tag ( bs ) ;
300
    ENC_make_tag ( bs, n ) ;
301
    return ( bs ) ;
302
}
303
 
304
 
305
/*
306
    ENCODE A RUN-TIME TYPE INFORMATION STRUCTURE
307
 
308
    This routine defines the tag n to be the run-time type information
309
    structure for the type t.  If def is false then only the declaration
310
    is output.
311
*/
312
 
313
static void enc_rtti_struct
314
    PROTO_N ( ( t, n, def ) )
315
    PROTO_T ( TYPE t X ulong n X int def )
316
{
317
    unsigned acc = find_usage ( n, VAR_tag ) ;
318
    if ( !( acc & USAGE_DECL ) ) {
319
	BITSTREAM *bs = enc_tagdec_start ( NULL_id, n, NULL_type, 1 ) ;
320
	bs = enc_special ( bs, TOK_typeid_type ) ;
321
	enc_tagdec_end ( bs ) ;
322
    }
323
    if ( def && !( acc & USAGE_DEFN ) ) {
324
	int c = RTTI_void ;
325
	NAT sz = NULL_nat ;
326
	BITSTREAM *bs, *ts ;
327
	LIST ( TYPE ) p = NULL_list ( TYPE ) ;
328
	LIST ( GRAPH ) br = NULL_list ( GRAPH ) ;
329
	BUFFER *bf = clear_buffer ( &print_buff, NIL ( FILE ) ) ;
330
	print_uniq_anon++ ;
331
	IGNORE print_type ( t, bf, 0 ) ;
332
	print_uniq_anon-- ;
333
	bfputc ( bf, 0 ) ;
334
	switch ( TAG_type ( t ) ) {
335
	    case type_integer_tag : {
336
		/* Integral types */
337
		c = RTTI_integer ;
338
		break ;
339
	    }
340
	    case type_floating_tag : {
341
		/* Floating-point types */
342
		c = RTTI_float ;
343
		break ;
344
	    }
345
	    case type_ptr_tag : {
346
		/* Pointer types */
347
		TYPE s = DEREF_type ( type_ptr_sub ( t ) ) ;
348
		CONS_type ( s, p, p ) ;
349
		c = RTTI_ptr ;
350
		break ;
351
	    }
352
	    case type_ref_tag : {
353
		/* Reference types */
354
		TYPE s = DEREF_type ( type_ref_sub ( t ) ) ;
355
		CONS_type ( s, p, p ) ;
356
		c = RTTI_ref ;
357
		break ;
358
	    }
359
	    case type_ptr_mem_tag : {
360
		/* Pointer to member types */
361
		TYPE s = DEREF_type ( type_ptr_mem_sub ( t ) ) ;
362
		CLASS_TYPE cs = DEREF_ctype ( type_ptr_mem_of ( t ) ) ;
363
		CONS_type ( s, p, p ) ;
364
		s = make_class_type ( cs ) ;
365
		CONS_type ( s, p, p ) ;
366
		c = RTTI_ptr_mem ;
367
		break ;
368
	    }
369
	    case type_func_tag : {
370
		/* Function types */
371
		TYPE s = DEREF_type ( type_func_ret ( t ) ) ;
372
		CV_SPEC mq = DEREF_cv ( type_func_mqual ( t ) ) ;
373
		int ell = DEREF_int ( type_func_ellipsis ( t ) ) ;
374
		LIST ( TYPE ) q = DEREF_list ( type_func_ptypes ( t ) ) ;
375
		CONS_type ( s, p, p ) ;
376
		while ( !IS_NULL_list ( q ) ) {
377
		    s = DEREF_type ( HEAD_list ( q ) ) ;
378
		    CONS_type ( s, p, p ) ;
379
		    q = TAIL_list ( q ) ;
380
		}
381
		if ( ell & FUNC_ELLIPSIS ) {
382
		    CONS_type ( type_any, p, p ) ;
383
		}
384
		p = REVERSE_list ( p ) ;
385
		if ( mq & cv_c ) {
386
		    c = RTTI_c_func ;
387
		} else {
388
		    c = RTTI_func ;
389
		}
390
		break ;
391
	    }
392
	    case type_array_tag : {
393
		/* Array types */
394
		TYPE s = DEREF_type ( type_array_sub ( t ) ) ;
395
		CONS_type ( s, p, p ) ;
396
		sz = DEREF_nat ( type_array_size ( t ) ) ;
397
		c = RTTI_array ;
398
		break ;
399
	    }
400
	    case type_bitfield_tag : {
401
		/* Bitfield types */
402
		INT_TYPE it = DEREF_itype ( type_bitfield_defn ( t ) ) ;
403
		TYPE s = DEREF_type ( itype_bitfield_sub ( it ) ) ;
404
		CONS_type ( s, p, p ) ;
405
		sz = DEREF_nat ( itype_bitfield_size ( it ) ) ;
406
		c = RTTI_bitfield ;
407
		break ;
408
	    }
409
	    case type_compound_tag : {
410
		/* Class types */
411
		CLASS_TYPE ct = DEREF_ctype ( type_compound_defn ( t ) ) ;
412
		CLASS_INFO ci = DEREF_cinfo ( ctype_info ( ct ) ) ;
413
		GRAPH gr = DEREF_graph ( ctype_base ( ct ) ) ;
414
		br = DEREF_list ( graph_tails ( gr ) ) ;
415
		if ( ci & cinfo_union ) {
416
		    c = RTTI_union ;
417
		} else {
418
		    c = RTTI_class ;
419
		}
420
		break ;
421
	    }
422
	    case type_enumerate_tag : {
423
		/* Enumeration types */
424
		c = RTTI_enum ;
425
		break ;
426
	    }
427
	}
428
	bs = enc_tagdef_start ( NULL_id, n, NULL_type, 1 ) ;
429
	bs = enc_special ( bs, TOK_typeid_make ) ;
430
	ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
431
	ts = enc_make_snat ( ts, c ) ;
432
	ts = enc_buffer ( ts, bf ) ;
433
	ts = enc_rtti_bases ( ts, br, p, sz ) ;
434
	DESTROY_list ( p, SIZE_type ) ;
435
	bs = enc_bitstream ( bs, ts ) ;
436
	enc_tagdef_end ( bs ) ;
437
    }
438
    return ;
439
}
440
 
441
 
442
/*
443
    LIST OF RUN-TIME TYPE INFORMATION STRUCTURES
444
 
445
    These lists gives the tag numbers for the various type information
446
    structures output.  Polymorphic classes, which form the most common
447
    such types, are dealt with separately as part of the virtual function
448
    table.
449
*/
450
 
451
static LIST ( TYPE ) rtti_types = NULL_list ( TYPE ) ;
452
static LIST ( ulong ) rtti_tags = NULL_list ( ulong ) ;
453
 
454
 
455
/*
456
    ENCODE THE RUN-TIME TYPE INFORMATION FOR A TYPE
457
 
458
    This routine adds a reference to the run-time type information
459
    structure for the type t to the bitstream bs, defining this if
460
    necessary.
461
*/
462
 
463
BITSTREAM *enc_rtti_type
464
    PROTO_N ( ( bs, t, op ) )
465
    PROTO_T ( BITSTREAM *bs X TYPE t X int op )
466
{
467
    ulong n = LINK_NONE ;
468
    if ( IS_NULL_type ( t ) ) {
469
	/* Map null type to null pointer */
470
	ENC_make_null_ptr ( bs ) ;
471
	ENC_alignment ( bs ) ;
472
	bs = enc_special ( bs, TOK_typeid_type ) ;
473
	return ( bs ) ;
474
    }
475
    if ( op == lex_typeid && !output_rtti ) {
476
	/* Use dummy type if RTTI suppressed */
477
	t = type_error ;
478
    }
479
    switch ( TAG_type ( t ) ) {
480
	case type_top_tag :
481
	case type_bottom_tag :
482
	case type_integer_tag :
483
	case type_floating_tag :
484
	case type_pre_tag :
485
	case type_error_tag : {
486
	    /* Built-in types */
487
	    BITSTREAM *ts ;
488
	    bs = enc_special ( bs, TOK_typeid_basic ) ;
489
	    ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
490
	    ts = enc_arith ( ts, t, 1 ) ;
491
	    bs = enc_bitstream ( bs, ts ) ;
492
	    return ( bs ) ;
493
	}
494
	case type_compound_tag : {
495
	    /* Class types */
496
	    CLASS_TYPE ct = DEREF_ctype ( type_compound_defn ( t ) ) ;
497
	    CLASS_INFO ci = DEREF_cinfo ( ctype_info ( ct ) ) ;
498
	    if ( ci & cinfo_polymorphic ) {
499
		/* Polymorphic class types */
500
		int used ;
501
		VIRTUAL vt = DEREF_virt ( ctype_virt ( ct ) ) ;
502
		n = DEREF_ulong ( virt_table_rtti ( vt ) ) ;
503
		if ( n == LINK_NONE ) {
504
		    IGNORE compile_class ( ct ) ;
505
		    n = DEREF_ulong ( virt_table_rtti ( vt ) ) ;
506
		}
507
		used = DEREF_int ( virt_table_rtti_used ( vt ) ) ;
508
		if ( !used ) {
509
		    IDENTIFIER cid = DEREF_id ( ctype_name ( ct ) ) ;
510
		    COPY_int ( virt_table_rtti_used ( vt ), 1 ) ;
511
		    compile_virtual ( ct, !has_linkage ( cid ) ) ;
512
		}
513
		if ( op == lex_vtable ) {
514
		    /* Deal with virtual function tables */
515
		    /* NOT YET IMPLEMENTED */
516
		    n = DEREF_ulong ( virt_table_tbl ( vt ) ) ;
517
		    n = link_no ( bs, n, VAR_tag ) ;
518
		    ENC_obtain_tag ( bs ) ;
519
		    ENC_make_tag ( bs, n ) ;
520
		    return ( bs ) ;
521
		}
522
	    } else {
523
		IGNORE compile_class ( ct ) ;
524
	    }
525
	    break ;
526
	}
527
    }
528
    if ( n == LINK_NONE ) {
529
	/* Check for previous definition */
530
	LIST ( TYPE ) p = rtti_types ;
531
	LIST ( ulong ) q = rtti_tags ;
532
	while ( !IS_NULL_list ( p ) ) {
533
	    TYPE s = DEREF_type ( HEAD_list ( p ) ) ;
534
	    if ( eq_type ( s, t ) ) {
535
		n = DEREF_ulong ( HEAD_list ( q ) ) ;
536
		break ;
537
	    }
538
	    q = TAIL_list ( q ) ;
539
	    p = TAIL_list ( p ) ;
540
	}
541
	if ( n == LINK_NONE ) {
542
	    /* Define a new structure */
543
	    string s = NULL ;
544
	    if ( output_all ) s = mangle_tname ( "__ti__", t ) ;
545
	    n = capsule_no ( s, VAR_tag ) ;
546
	    CONS_type ( t, rtti_types, rtti_types ) ;
547
	    CONS_ulong ( n, rtti_tags, rtti_tags ) ;
548
	    enc_rtti_struct ( t, n, 1 ) ;
549
	}
550
    }
551
    n = link_no ( bs, n, VAR_tag ) ;
552
    ENC_obtain_tag ( bs ) ;
553
    ENC_make_tag ( bs, n ) ;
554
    return ( bs ) ;
555
}
556
 
557
 
558
/*
559
    ENCODE THE RUN-TIME TYPE INFORMATION FOR AN EXPRESSION
560
 
561
    This routine adds the run-time type information expression e to
562
    the bitstream bs.
563
*/
564
 
565
BITSTREAM *enc_rtti_exp
566
    PROTO_N ( ( bs, e ) )
567
    PROTO_T ( BITSTREAM *bs X EXP e )
568
{
569
    EXP a = DEREF_exp ( exp_rtti_arg ( e ) ) ;
570
    EXP b = DEREF_exp ( exp_rtti_except ( e ) ) ;
571
    int op = DEREF_int ( exp_rtti_op ( e ) ) ;
572
    TYPE t = DEREF_type ( exp_type ( a ) ) ;
573
    if ( IS_type_ptr_etc ( t ) ) {
574
	TYPE s = DEREF_type ( type_ptr_etc_sub ( t ) ) ;
575
	if ( IS_type_compound ( s ) ) {
576
	    CLASS_TYPE ct = DEREF_ctype ( type_compound_defn ( s ) ) ;
577
	    VIRTUAL vt = DEREF_virt ( ctype_virt ( ct ) ) ;
578
	    if ( !IS_NULL_virt ( vt ) ) {
579
		/* Pointer to polymorphic class */
580
		EXP a1 ;
581
		int used ;
582
		OFFSET off ;
583
		ulong n, m ;
584
		BITSTREAM *ts ;
585
		IGNORE compile_class ( ct ) ;
586
		off = DEREF_off ( virt_table_off ( vt ) ) ;
587
		n = DEREF_ulong ( virt_table_tok ( vt ) ) ;
588
 
589
		/* Introduce variable for pointer */
590
		a1 = DEREF_exp ( exp_dummy_value ( a ) ) ;
591
		m = unit_no ( bs, NULL_id, VAR_tag, 1 ) ;
592
		ENC_variable ( bs ) ;
593
		bs = enc_access ( bs, crt_func_access ) ;
594
		ENC_make_tag ( bs, m ) ;
595
		bs = enc_exp ( bs, a ) ;
596
		COPY_ulong ( exp_dummy_no ( a ), m ) ;
597
		COPY_exp ( exp_dummy_value ( a ), NULL_exp ) ;
598
 
599
		/* Check for null pointers */
600
		if ( !IS_NULL_exp ( b ) ) {
601
		    ulong lab = unit_no ( bs, NULL_id, VAR_label, 1 ) ;
602
		    ENC_SEQ_SMALL ( bs, 1 ) ;
603
		    ENC_conditional ( bs ) ;
604
		    ENC_make_label ( bs, lab ) ;
605
		    ENC_SEQ_SMALL ( bs, 1 ) ;
606
		    ENC_pointer_test ( bs ) ;
607
		    ENC_OFF ( bs ) ;
608
		    ENC_equal ( bs ) ;
609
		    ENC_make_label ( bs, lab ) ;
610
		    bs = enc_exp ( bs, a ) ;
611
		    bs = enc_null_exp ( bs, t ) ;
612
		    bs = enc_exp ( bs, b ) ;
613
		    ENC_make_top ( bs ) ;
614
		}
615
 
616
		/* Find the run-time type information */
617
		ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
618
		if ( op == lex_typeid ) {
619
		    bs = enc_special ( bs, TOK_typeid_ref ) ;
620
		} else {
621
		    bs = enc_special ( bs, TOK_vtab_func ) ;
622
		}
623
		ENC_add_to_ptr ( ts ) ;
624
		ts = enc_add_ptr ( ts, a, LINK_NONE, off, 0 ) ;
625
		ts = enc_exp_token ( ts, n ) ;
626
		if ( op != lex_typeid ) {
627
		    ENC_make_signed_nat ( ts ) ;
628
		    ENC_OFF ( ts ) ;
629
		    ENC_INT_SMALL ( ts, 0 ) ;
630
		}
631
		bs = enc_bitstream ( bs, ts ) ;
632
		used = DEREF_int ( virt_table_rtti_used ( vt ) ) ;
633
		if ( !used ) {
634
		    IDENTIFIER cid = DEREF_id ( ctype_name ( ct ) ) ;
635
		    COPY_int ( virt_table_rtti_used ( vt ), 1 ) ;
636
		    compile_virtual ( ct, !has_linkage ( cid ) ) ;
637
		}
638
		COPY_exp ( exp_dummy_value ( a ), a1 ) ;
639
		return ( bs ) ;
640
	    }
641
	}
642
    }
643
    bs = enc_rtti_type ( bs, t, op ) ;
644
    return ( bs ) ;
645
}
646
 
647
 
648
/*
649
    ENCODE A DYNAMIC CAST EXPRESSION
650
 
651
    This routine adds the dynamic cast expression e to the bitstream bs.
652
*/
653
 
654
BITSTREAM *enc_dyn_cast
655
    PROTO_N ( ( bs, e ) )
656
    PROTO_T ( BITSTREAM *bs X EXP e )
657
{
658
    ulong m ;
659
    int used ;
660
    OFFSET off ;
661
    VIRTUAL vt ;
662
    CLASS_TYPE ct ;
663
    BITSTREAM *ts, *us ;
664
    ulong r = LINK_NONE ;
665
    TYPE t = DEREF_type ( exp_type ( e ) ) ;
666
    EXP a = DEREF_exp ( exp_dyn_cast_arg ( e ) ) ;
667
    TYPE s = DEREF_type ( exp_type ( a ) ) ;
668
    EXP a1 = DEREF_exp ( exp_dummy_value ( a ) ) ;
669
    EXP b = DEREF_exp ( exp_dyn_cast_except ( e ) ) ;
670
 
671
    /* Introduce identity for argument */
672
    ulong n = unit_no ( bs, NULL_id, VAR_tag, 1 ) ;
673
    ENC_identify ( bs ) ;
674
    bs = enc_access ( bs, dspec_none ) ;
675
    ENC_make_tag ( bs, n ) ;
676
    bs = enc_exp ( bs, a1 ) ;
677
    COPY_exp ( exp_dummy_value ( a ), NULL_exp ) ;
678
    COPY_ulong ( exp_dummy_no ( a ), n ) ;
679
 
680
    /* Convert to result type */
681
    bs = enc_special ( bs, TOK_from_ptr_void ) ;
682
    ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
683
    t = DEREF_type ( type_ptr_etc_sub ( t ) ) ;
684
    ts = enc_alignment ( ts, t ) ;
685
 
686
    /* Introduce variable in exception case */
687
    if ( !IS_NULL_exp ( b ) ) {
688
	r = unit_no ( ts, NULL_id, VAR_tag, 1 ) ;
689
	ENC_variable ( ts ) ;
690
	ts = enc_access ( ts, crt_func_access ) ;
691
	ENC_make_tag ( ts, r ) ;
692
    }
693
 
694
    /* Encode main token */
695
    ts = enc_special ( ts, TOK_dynam_cast ) ;
696
    us = start_bitstream ( NIL ( FILE ), ts->link ) ;
697
 
698
    /* Encode address of virtual function table */
699
    s = DEREF_type ( type_ptr_etc_sub ( s ) ) ;
700
    ct = DEREF_ctype ( type_compound_defn ( s ) ) ;
701
    IGNORE compile_class ( ct ) ;
702
    vt = DEREF_virt ( ctype_virt ( ct ) ) ;
703
    off = DEREF_off ( virt_table_off ( vt ) ) ;
704
    m = DEREF_ulong ( virt_table_tok ( vt ) ) ;
705
    ENC_add_to_ptr ( us ) ;
706
    us = enc_add_ptr ( us, a, LINK_NONE, off, 0 ) ;
707
    us = enc_exp_token ( us, m ) ;
708
    used = DEREF_int ( virt_table_rtti_used ( vt ) ) ;
709
    if ( !used ) {
710
	IDENTIFIER cid = DEREF_id ( ctype_name ( ct ) ) ;
711
	COPY_int ( virt_table_rtti_used ( vt ), 1 ) ;
712
	compile_virtual ( ct, !has_linkage ( cid ) ) ;
713
    }
714
 
715
    /* Output run-time type information */
716
    us = enc_rtti_type ( us, t, lex_typeid ) ;
717
    ts = enc_bitstream ( ts, us ) ;
718
 
719
    /* Check for exceptions */
720
    if ( !IS_NULL_exp ( b ) ) {
721
	ulong lab = unit_no ( ts, NULL_id, VAR_label, 1 ) ;
722
	ENC_SEQ_SMALL ( ts, 1 ) ;
723
	ENC_conditional ( ts ) ;
724
	ENC_make_label ( ts, lab ) ;
725
	ENC_SEQ_SMALL ( ts, 1 ) ;
726
	ts = enc_special ( ts, TOK_pv_test ) ;
727
	us = start_bitstream ( NIL ( FILE ), ts->link ) ;
728
	ENC_contents ( us ) ;
729
	us = enc_special ( us, TOK_ptr_void ) ;
730
	ENC_obtain_tag ( us ) ;
731
	ENC_make_tag ( us, r ) ;
732
	ENC_make_label ( us, lab ) ;
733
	ENC_equal ( us ) ;
734
	ts = enc_bitstream ( ts, us ) ;
735
	ts = enc_exp ( ts, b ) ;
736
	ENC_make_top ( ts ) ;
737
	ENC_contents ( ts ) ;
738
	ts = enc_special ( ts, TOK_ptr_void ) ;
739
	ENC_obtain_tag ( ts ) ;
740
	ENC_make_tag ( ts, r ) ;
741
    }
742
 
743
    /* End conversion expression */
744
    bs = enc_bitstream ( bs, ts ) ;
745
    COPY_exp ( exp_dummy_value ( a ), a1 ) ;
746
    return ( bs ) ;
747
}
748
 
749
 
750
/*
751
    LIST OF PREVIOUSLY DEFINED THUNKS
752
 
753
    A list of all previously defined thunks is maintained to avoid
754
    unnecessary duplication.
755
*/
756
 
757
static VIRTUAL all_thunks = NULL_virt ;
758
 
759
 
760
/*
761
    CREATE A THUNK FUNCTION
762
 
763
    This routine creates a dummy function of type f which calls fid with
764
    its given arguments and returns its result with the base class conversion
765
    given by ret applied.  The tag number of the dummy function is returned.
766
    This is used for overriding virtual functions in which the return
767
    type differs.
768
*/
769
 
770
static ulong make_thunk
771
    PROTO_N ( ( f, fid, ret ) )
772
    PROTO_T ( TYPE f X IDENTIFIER fid X GRAPH ret )
773
{
774
    ulong n ;
775
    DECL_SPEC acc = DEREF_dspec ( graph_access ( ret ) ) ;
776
    IGNORE capsule_id ( fid, VAR_tag ) ;
777
    if ( acc & dspec_ignore ) {
778
	/* Use fid for trivial conversions */
779
	n = DEREF_ulong ( id_no ( fid ) ) ;
780
 
781
    } else {
782
	EXP e ;
783
	int ell ;
784
	TYPE f2 ;
785
	OFFSET off ;
786
	unsigned np ;
787
	TYPE r1, r2 ;
788
	ulong rn, pn ;
789
	LIST ( TYPE ) p ;
790
	BITSTREAM *bs, *ts ;
791
 
792
	/* Check previously defined thunks */
793
	VIRTUAL vt = all_thunks ;
794
	while ( !IS_NULL_virt ( vt ) ) {
795
	    IDENTIFIER vn = DEREF_id ( virt_func ( vt ) ) ;
796
	    if ( EQ_id ( vn, fid ) ) {
797
		GRAPH gv = DEREF_graph ( virt_base ( vt ) ) ;
798
		if ( EQ_graph ( gv, ret ) ) {
799
		    n = DEREF_ulong ( virt_no ( vt ) ) ;
800
		    return ( n ) ;
801
		}
802
	    }
803
	    vt = DEREF_virt ( virt_next ( vt ) ) ;
804
	}
805
 
806
	/* Find type information */
807
	while ( IS_type_templ ( f ) ) {
808
	    f = DEREF_type ( type_templ_defn ( f ) ) ;
809
	}
810
	r1 = DEREF_type ( type_func_ret ( f ) ) ;
811
	p = DEREF_list ( type_func_mtypes ( f ) ) ;
812
	np = LENGTH_list ( p ) ;
813
	ell = DEREF_int ( type_func_ellipsis ( f ) ) ;
814
	f2 = DEREF_type ( id_function_etc_type ( fid ) ) ;
815
	while ( IS_type_templ ( f2 ) ) {
816
	    f2 = DEREF_type ( type_templ_defn ( f2 ) ) ;
817
	}
818
	r2 = DEREF_type ( type_func_ret ( f2 ) ) ;
819
 
820
	/* Declare the thunk function */
821
	n = capsule_no ( NULL_string, VAR_tag ) ;
822
	enc_tagdec ( NULL_id, n, f, 0 ) ;
823
	bs = enc_tagdef_start ( NULL_id, n, f, 0 ) ;
824
	ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
825
	ENC_make_proc ( bs ) ;
826
	bs = enc_shape ( bs, r1 ) ;
827
	ENC_LIST ( bs, np ) ;
828
	ENC_LIST ( ts, np ) ;
829
	while ( !IS_NULL_list ( p ) ) {
830
	    /* Scan through parameter types */
831
	    TYPE pt = DEREF_type ( HEAD_list ( p ) ) ;
832
	    ulong m = unit_no ( bs, NULL_id, VAR_tag, 1 ) ;
833
	    ENC_contents ( ts ) ;
834
	    if ( pass_complex_type ( pt ) ) {
835
		ENC_pointer ( bs ) ;
836
		bs = enc_alignment ( bs, pt ) ;
837
		ENC_pointer ( ts ) ;
838
		ts = enc_alignment ( ts, pt ) ;
839
	    } else {
840
		bs = enc_shape ( bs, pt ) ;
841
		ts = enc_shape ( ts, pt ) ;
842
	    }
843
	    bs = enc_access ( bs, dspec_none ) ;
844
	    ENC_make_tag ( bs, m ) ;
845
	    ENC_obtain_tag ( ts ) ;
846
	    ENC_make_tag ( ts, m ) ;
847
	    p = TAIL_list ( p ) ;
848
	}
849
	if ( ell & FUNC_ELLIPSIS ) {
850
	    /* Check for ellipsis */
851
	    ulong m = unit_no ( bs, NULL_id, VAR_tag, 1 ) ;
852
	    ENC_ON ( bs ) ;
853
	    ENC_make_tag ( bs, m ) ;
854
	    bs = enc_access ( bs, dspec_none ) ;
855
	    /* NOT YET IMPLEMENTED: use same_callees? */
856
	} else {
857
	    ENC_OFF ( bs ) ;
858
	}
859
	ENC_OFF ( ts ) ;
860
 
861
	/* Output the function body */
862
	rn = unit_no ( bs, NULL_id, VAR_tag, 1 ) ;
863
	MAKE_exp_dummy ( r2, NULL_exp, rn, NULL_off, 1, e ) ;
864
	ENC_variable ( bs ) ;
865
	bs = enc_access ( bs, dspec_none ) ;
866
	ENC_make_tag ( bs, rn ) ;
867
	ENC_apply_proc ( bs ) ;
868
	bs = enc_shape ( bs, r2 ) ;
869
	pn = unit_no ( bs, fid, VAR_tag, 0 ) ;
870
	ENC_obtain_tag ( bs ) ;
871
	ENC_make_tag ( bs, pn ) ;
872
	bs = join_bitstreams ( bs, ts ) ;
873
	if ( IS_type_ptr ( r2 ) ) {
874
	    /* Test for null pointers */
875
	    ulong lab = unit_no ( bs, NULL_id, VAR_label, 1 ) ;
876
	    ENC_conditional ( bs ) ;
877
	    ENC_make_label ( bs, lab ) ;
878
	    ENC_SEQ_SMALL ( bs, 1 ) ;
879
	    bs = enc_compare ( bs, e, NULL_exp, ntest_eq, lab, LINK_NONE ) ;
880
	    ENC_return ( bs ) ;
881
	    bs = enc_null_exp ( bs, r1 ) ;
882
	}
883
	ENC_return ( bs ) ;
884
	off = DEREF_off ( graph_off ( ret ) ) ;
885
	bs = enc_add_ptr ( bs, e, LINK_NONE, off, 1 ) ;
886
	enc_tagdef_end ( bs ) ;
887
	free_exp ( e, 1 ) ;
888
 
889
	/* Add to list of all thunks */
890
	MAKE_virt_simple ( fid, n, ret, vt ) ;
891
	COPY_virt ( virt_next ( vt ), all_thunks ) ;
892
	all_thunks = vt ;
893
    }
894
    return ( n ) ;
895
}
896
 
897
 
898
/*
899
    ENCODE THE SHAPE OF A VIRTUAL FUNCTION TABLE
900
 
901
    This routine adds the shape of a virtual function table containing
902
    n functions to the bitstream bs.
903
*/
904
 
905
BITSTREAM *enc_vtable_shape
906
    PROTO_N ( ( bs, n ) )
907
    PROTO_T ( BITSTREAM *bs X ulong n )
908
{
909
    BITSTREAM *ts ;
910
    bs = enc_special ( bs, TOK_vtab_type ) ;
911
    ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
912
    ENC_make_nat ( ts ) ;
913
    ENC_INT ( ts, n + VIRTUAL_EXTRA ) ;
914
    bs = enc_bitstream ( bs, ts ) ;
915
    return ( bs ) ;
916
}
917
 
918
 
919
/*
920
    ENCODE THE DEFINITION OF A VIRTUAL FUNCTION TABLE
921
 
922
    This routine encodes the definition of the virtual function table vt.
923
    n gives the tag number for the table, gr is the table offset and the
924
    flag inherited is true for secondary tables.  rtti gives the tag
925
    number for the run-time type information.
926
*/
927
 
928
static void enc_vtable_defn
929
    PROTO_N ( ( vt, n, ct, gr, inherited, rtti ) )
930
    PROTO_T ( VIRTUAL vt X ulong n X CLASS_TYPE ct X GRAPH gr X
931
	      int inherited X ulong rtti )
932
{
933
    ulong r ;
934
    BITSTREAM *bs, *ts, *us ;
935
    ulong m = DEREF_ulong ( virt_no ( vt ) ) ;
936
    ulong p = DEREF_ulong ( virt_table_tok ( vt ) ) ;
937
    OFFSET off = DEREF_off ( virt_table_off ( vt ) ) ;
938
    LIST ( VIRTUAL ) pt = DEREF_list ( virt_table_entries ( vt ) ) ;
939
 
940
    /* Output start of table */
941
    bs = enc_tagdef_start ( NULL_id, n, NULL_type, 1 ) ;
942
    bs = enc_special ( bs, TOK_vtab_make ) ;
943
    ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
944
    ENC_obtain_tag ( ts ) ;
945
    r = link_no ( ts, rtti, VAR_tag ) ;
946
    ENC_make_tag ( ts, r ) ;
947
    if ( inherited ) {
948
	/* Add base class offset */
949
	OFFSET off2 = DEREF_off ( graph_off ( gr ) ) ;
950
	if ( !is_zero_offset ( off2 ) ) {
951
	    ENC_offset_add ( ts ) ;
952
	    ts = enc_offset ( ts, off2 ) ;
953
	}
954
    }
955
    if ( !is_zero_offset ( off ) ) {
956
	/* Add inherited table offset */
957
	ENC_offset_add ( ts ) ;
958
	ts = enc_offset ( ts, off ) ;
959
    }
960
    ts = enc_exp_token ( ts, p ) ;
961
    ENC_make_nat ( ts ) ;
962
    ENC_INT ( ts, m + VIRTUAL_EXTRA ) ;
963
 
964
    /* Output virtual functions */
965
    ENC_make_nof ( ts ) ;
966
    ENC_LIST ( ts, m ) ;
967
    while ( !IS_NULL_list ( pt ) ) {
968
	GRAPH gs ;
969
	DECL_SPEC ds ;
970
	IDENTIFIER fid ;
971
	GRAPH ret = NULL_graph ;
972
	IDENTIFIER pid = NULL_id ;
973
	VIRTUAL at = DEREF_virt ( HEAD_list ( pt ) ) ;
974
	while ( IS_virt_link ( at ) ) {
975
	    /* Allow for symbolic links */
976
	    at = DEREF_virt ( DEREF_ptr ( virt_link_to ( at ) ) ) ;
977
	}
978
	if ( inherited ) {
979
	    /* Allow for inherited function tables */
980
	    VIRTUAL as ;
981
	    pid = DEREF_id ( virt_func ( at ) ) ;
982
	    as = find_overrider ( ct, pid, gr, &ret ) ;
983
	    if ( !IS_NULL_virt ( as ) ) at = as ;
984
	}
985
	fid = DEREF_id ( virt_func ( at ) ) ;
986
	ds = DEREF_dspec ( id_storage ( fid ) ) ;
987
	gs = DEREF_graph ( virt_base ( at ) ) ;
988
 
989
	/* Output pointer to member function */
990
	ts = enc_special ( ts, TOK_pmf_make ) ;
991
	us = start_bitstream ( NIL ( FILE ), ts->link ) ;
992
	if ( ds & dspec_pure ) {
993
	    /* Pure virtual function */
994
	    us = enc_special ( us, TOK_vtab_pure ) ;
995
	} else {
996
	    if ( IS_NULL_graph ( ret ) ) {
997
		IGNORE capsule_id ( fid, VAR_tag ) ;
998
		r = unit_no ( us, fid, VAR_tag, 0 ) ;
999
	    } else {
1000
		TYPE f = DEREF_type ( id_function_etc_type ( pid ) ) ;
1001
		r = make_thunk ( f, fid, ret ) ;
1002
		r = link_no ( us, r, VAR_tag ) ;
1003
	    }
1004
	    ENC_obtain_tag ( us ) ;
1005
	    ENC_make_tag ( us, r ) ;
1006
	}
1007
	us = enc_base ( us, gs, 0 ) ;
1008
	us = enc_base ( us, gr, 0 ) ;
1009
	ts = enc_bitstream ( ts, us ) ;
1010
	pt = TAIL_list ( pt ) ;
1011
    }
1012
    bs = enc_bitstream ( bs, ts ) ;
1013
    enc_tagdef_end ( bs ) ;
1014
    return ;
1015
}
1016
 
1017
 
1018
/*
1019
    DEFINE VIRTUAL FUNCTION TABLES
1020
 
1021
    This routine defines or declares the virtual function tables for
1022
    the class ct depending on the value of def.  The tables are given
1023
    external names only if ext is true.
1024
*/
1025
 
1026
void define_vtable
1027
    PROTO_N ( ( ct, def, ext ) )
1028
    PROTO_T ( CLASS_TYPE ct X int def X int ext )
1029
{
1030
    ulong r ;
1031
    int used ;
1032
    int have_main_table = 0 ;
1033
    VIRTUAL vt = DEREF_virt ( ctype_virt ( ct ) ) ;
1034
    if ( IS_NULL_virt ( vt ) ) return ;
1035
    if ( output_all ) ext = 1 ;
1036
    if ( def == 2 ) {
1037
	/* Force definition in this case */
1038
	IGNORE compile_class ( ct ) ;
1039
    } else {
1040
	ulong n = DEREF_ulong ( ctype_shape ( ct ) ) ;
1041
	if ( n == LINK_NONE ) return ;
1042
    }
1043
 
1044
    /* Output run-time type information */
1045
    r = DEREF_ulong ( virt_table_rtti ( vt ) ) ;
1046
    used = DEREF_int ( virt_table_rtti_used ( vt ) ) ;
1047
    if ( used || def ) {
1048
	TYPE t = dummy_class ;
1049
	if ( ext ) {
1050
	    /* Make up external name */
1051
	    string s = mangle_typeid ( "__ti__", ct ) ;
1052
	    r = capsule_name ( r, &s, VAR_tag ) ;
1053
	}
1054
	record_usage ( r, VAR_tag, USAGE_USE ) ;
1055
	COPY_int ( virt_table_rtti_used ( vt ), 1 ) ;
1056
	COPY_ctype ( type_compound_defn ( t ), ct ) ;
1057
	enc_rtti_struct ( t, r, def ) ;
1058
    }
1059
 
1060
    /* Output virtual function tables */
1061
    while ( !IS_NULL_virt ( vt ) ) {
1062
	ulong n ;
1063
	VIRTUAL vs ;
1064
	unsigned acc ;
1065
	CLASS_TYPE cs ;
1066
	int inherited = 1 ;
1067
	GRAPH gr = DEREF_graph ( virt_base ( vt ) ) ;
1068
	DECL_SPEC gacc = DEREF_dspec ( graph_access ( gr ) ) ;
1069
	if ( ( gacc & dspec_ignore ) && !have_main_table ) {
1070
	    /* Main virtual function table */
1071
	    gr = DEREF_graph ( graph_top ( gr ) ) ;
1072
	    have_main_table = 1 ;
1073
	    inherited = 0 ;
1074
	}
1075
	cs = DEREF_ctype ( graph_head ( gr ) ) ;
1076
	vs = DEREF_virt ( ctype_virt ( cs ) ) ;
1077
	n = DEREF_ulong ( virt_table_tbl ( vt ) ) ;
1078
	record_usage ( n, VAR_tag, USAGE_USE ) ;
1079
	acc = find_usage ( n, VAR_tag ) ;
1080
	if ( ext ) {
1081
	    /* Make up external name */
1082
	    string s = mangle_vtable ( "__vt__", gr ) ;
1083
	    n = capsule_name ( n, &s, VAR_tag ) ;
1084
	}
1085
	if ( !( acc & USAGE_DECL ) ) {
1086
	    /* Output table declaration */
1087
	    ulong m = DEREF_ulong ( virt_no ( vs ) ) ;
1088
	    BITSTREAM *ts = enc_tagdec_start ( NULL_id, n, NULL_type, 1 ) ;
1089
	    ts = enc_vtable_shape ( ts, m ) ;
1090
	    enc_tagdec_end ( ts ) ;
1091
	}
1092
	if ( def && !( acc & USAGE_DEFN ) ) {
1093
	    /* Output table definition */
1094
	    enc_vtable_defn ( vs, n, ct, gr, inherited, r ) ;
1095
	}
1096
	vt = DEREF_virt ( virt_next ( vt ) ) ;
1097
    }
1098
    return ;
1099
}
1100
 
1101
 
1102
/*
1103
    ALLOCATE TAG NUMBERS FOR VIRTUAL FUNCTION TABLES
1104
 
1105
    This routine allocates tag and token numbers for the virtual function
1106
    tables of the polymorphic class ct and its base classes.
1107
*/
1108
 
1109
static ulong declare_vtable
1110
    PROTO_N ( ( ct ) )
1111
    PROTO_T ( CLASS_TYPE ct )
1112
{
1113
    ulong n = LINK_NONE ;
1114
    ulong r = LINK_NONE ;
1115
    VIRTUAL vt = DEREF_virt ( ctype_virt ( ct ) ) ;
1116
    while ( !IS_NULL_virt ( vt ) ) {
1117
	ulong t ;
1118
	OFFSET off ;
1119
	ulong m = DEREF_ulong ( virt_table_tok ( vt ) ) ;
1120
	if ( m != LINK_NONE ) {
1121
	    /* Already declared */
1122
	    return ( m ) ;
1123
	}
1124
	off = DEREF_off ( virt_table_off ( vt ) ) ;
1125
	if ( IS_NULL_off ( off ) ) {
1126
	    /* New virtual function table required */
1127
	    m = capsule_no ( NULL_string, VAR_token ) ;
1128
	} else if ( IS_off_base ( off ) ) {
1129
	    /* Use existing virtual function table */
1130
	    GRAPH gs = DEREF_graph ( off_base_graph ( off ) ) ;
1131
	    CLASS_TYPE cs = DEREF_ctype ( graph_head ( gs ) ) ;
1132
	    m = declare_vtable ( cs ) ;
1133
	} else {
1134
	    /* Use existing virtual function table */
1135
	    GRAPH gs = DEREF_graph ( off_deriv_graph ( off ) ) ;
1136
	    CLASS_TYPE cs = DEREF_ctype ( graph_head ( gs ) ) ;
1137
	    m = declare_vtable ( cs ) ;
1138
	}
1139
	if ( n == LINK_NONE ) n = m ;
1140
 
1141
	/* Allocate (but not define) virtual table tags */
1142
	t = capsule_no ( NULL_string, VAR_tag ) ;
1143
	clear_usage ( t, VAR_tag ) ;
1144
	if ( r == LINK_NONE ) {
1145
	    r = capsule_no ( NULL_string, VAR_tag ) ;
1146
	    clear_usage ( r, VAR_tag ) ;
1147
	}
1148
	COPY_ulong ( virt_table_tbl ( vt ), t ) ;
1149
	COPY_ulong ( virt_table_rtti ( vt ), r ) ;
1150
	COPY_ulong ( virt_table_tok ( vt ), m ) ;
1151
	vt = DEREF_virt ( virt_next ( vt ) ) ;
1152
    }
1153
    return ( n ) ;
1154
}
1155
 
1156
 
1157
/*
1158
    END OF RUN-TIME TYPE INFORMATION ROUTINES
1159
 
1160
    The remaining routines are common to both the C and C++ producers.
1161
*/
1162
 
1163
#endif /* LANGUAGE_CPP */
1164
 
1165
 
1166
/*
1167
    FIND THE TABLE OFFSET OF A VIRTUAL FUNCTION
1168
 
1169
    This routine finds the position of the virtual function id in the
1170
    virtual function table vt.
1171
*/
1172
 
1173
ulong virtual_no
1174
    PROTO_N ( ( id, vt ) )
1175
    PROTO_T ( IDENTIFIER id X VIRTUAL vt )
1176
{
1177
    LIST ( VIRTUAL ) pv = DEREF_list ( virt_table_entries ( vt ) ) ;
1178
    while ( !IS_NULL_list ( pv ) ) {
1179
	VIRTUAL vs = DEREF_virt ( HEAD_list ( pv ) ) ;
1180
	IDENTIFIER vid = DEREF_id ( virt_func ( vs ) ) ;
1181
	if ( EQ_id ( vid, id ) ) {
1182
	    ulong m = DEREF_ulong ( virt_no ( vs ) ) ;
1183
	    return ( m + VIRTUAL_EXTRA ) ;
1184
	}
1185
	pv = TAIL_list ( pv ) ;
1186
    }
1187
    return ( VIRTUAL_EXTRA ) ;
1188
}
1189
 
1190
 
1191
/*
1192
    IS A TYPE A ZERO SIZED BITFIELD?
1193
 
1194
    This routine checks whether the type t represents a zero sized
1195
    bitfield.  These force an alignment in a class rather than being
1196
    a proper class member.
1197
*/
1198
 
1199
static int is_zero_bitfield
1200
    PROTO_N ( ( t ) )
1201
    PROTO_T ( TYPE t )
1202
{
1203
    if ( !IS_NULL_type ( t ) && IS_type_bitfield ( t ) ) {
1204
	INT_TYPE bf = DEREF_itype ( type_bitfield_defn ( t ) ) ;
1205
	DECL_SPEC ds = DEREF_dspec ( itype_bitfield_info ( bf ) ) ;
1206
	if ( ds & dspec_pure ) return ( 1 ) ;
1207
    }
1208
    return ( 0 ) ;
1209
}
1210
 
1211
 
1212
/*
1213
    ENCODE A SHAPE OFFSET EXPRESSION
1214
 
1215
    This routine adds the offset of the type t to the bitstream bs,
1216
    unless t is dummy_class, when the offset of the type excluding the
1217
    virtual bases is added.
1218
*/
1219
 
1220
static BITSTREAM *enc_offset_add
1221
    PROTO_N ( ( bs, t ) )
1222
    PROTO_T ( BITSTREAM *bs X TYPE t )
1223
{
1224
    if ( EQ_type ( t, dummy_class ) ) {
1225
	/* Class offset */
1226
	CLASS_TYPE ct = DEREF_ctype ( type_compound_defn ( t ) ) ;
1227
	GRAPH gr = DEREF_graph ( ctype_base ( ct ) ) ;
1228
	ulong m = DEREF_ulong ( graph_core_off ( gr ) ) ;
1229
	if ( m != LINK_NONE ) {
1230
	    bs = enc_exp_token ( bs, m ) ;
1231
	    return ( bs ) ;
1232
	}
1233
    }
1234
    ENC_shape_offset ( bs ) ;
1235
    bs = enc_shape ( bs, t ) ;
1236
    return ( bs ) ;
1237
}
1238
 
1239
 
1240
/*
1241
    ENCODE AN OFFSET PAD EXPRESSION
1242
 
1243
    This routine adds the offset of a structure member of type s
1244
    which follows a member of type t with offset given by the token n
1245
    to the bitstream bs.  Note that bitfield types are awkward.
1246
*/
1247
 
1248
static BITSTREAM *enc_offset_pad
1249
    PROTO_N ( ( bs, n, t, s ) )
1250
    PROTO_T ( BITSTREAM *bs X ulong n X TYPE t X TYPE s )
1251
{
1252
    BITSTREAM *ts ;
1253
    unsigned tag = null_tag ;
1254
    int z = is_zero_bitfield ( t ) ;
1255
    if ( !IS_NULL_type ( s ) ) {
1256
	if ( is_zero_bitfield ( s ) ) {
1257
	    /* Force an alignment */
1258
	    s = find_bitfield_type ( s ) ;
1259
	}
1260
	ENC_offset_pad ( bs ) ;
1261
	bs = enc_alignment ( bs, s ) ;
1262
	tag = TAG_type ( s ) ;
1263
    }
1264
    if ( tag == type_bitfield_tag ) {
1265
	/* Use token for bitfields */
1266
	bs = enc_special ( bs, TOK_pad ) ;
1267
	ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
1268
    } else {
1269
	ts = bs ;
1270
    }
1271
 
1272
    /* Add offset (except for zero sized bitfields) */
1273
    if ( !z ) ENC_offset_add ( ts ) ;
1274
    ts = enc_exp_token ( ts, n ) ;
1275
    if ( !z ) ts = enc_offset_add ( ts, t ) ;
1276
 
1277
    /* Encode extra bitfield arguments */
1278
    if ( tag == type_bitfield_tag ) {
1279
	TYPE r = find_bitfield_type ( s ) ;
1280
	ts = enc_shape ( ts, r ) ;
1281
	ts = enc_shape ( ts, s ) ;
1282
	bs = enc_bitstream ( bs, ts ) ;
1283
    } else {
1284
	bs = ts ;
1285
    }
1286
    return ( bs ) ;
1287
}
1288
 
1289
 
1290
/*
1291
    DEFINE AN ALIGNMENT TAG
1292
 
1293
    This routine defines the alignment tag m to be the token n.  The value
1294
    LINK_NONE for n is used to indicate an incomplete structure.
1295
*/
1296
 
1297
static void enc_al_tagdef
1298
    PROTO_N ( ( m, n ) )
1299
    PROTO_T ( ulong m X ulong n )
1300
{
1301
    unsigned acc = find_usage ( m, VAR_alignment ) ;
1302
    if ( !( acc & USAGE_DEFN ) ) {
1303
	BITSTREAM *bs = aldef_unit ;
1304
	ulong r = link_no ( bs, m, VAR_alignment ) ;
1305
	ENC_make_al_tagdef ( bs ) ;
1306
	ENC_INT ( bs, r ) ;
1307
	if ( n == LINK_NONE ) {
1308
	    bs = enc_special ( bs, TOK_empty_align ) ;
1309
	} else {
1310
	    ENC_alignment ( bs ) ;
1311
	    bs = enc_shape_token ( bs, n ) ;
1312
	}
1313
	record_usage ( m, VAR_alignment, USAGE_DEFN ) ;
1314
	count_item ( bs ) ;
1315
	aldef_unit = bs ;
1316
    }
1317
    return ;
1318
}
1319
 
1320
 
1321
/*
1322
    ENCODE A TDF COMPOUND SHAPE
1323
 
1324
    This routine defines all the shape and offset tokens associated with
1325
    the compound type ct.  It returns the external (capsule) number of
1326
    a token giving the overall shape of the result.
1327
*/
1328
 
1329
ulong compile_class
1330
    PROTO_N ( ( ct ) )
1331
    PROTO_T ( CLASS_TYPE ct )
1332
{
1333
    ulong n = DEREF_ulong ( ctype_shape ( ct ) ) ;
1334
    if ( n == LINK_NONE ) {
1335
	ulong m ;
1336
	HASHID nm ;
1337
	NAMESPACE ns ;
1338
	BITSTREAM *bs ;
1339
	BITSTREAM *ts ;
1340
	LIST ( GRAPH ) br ;
1341
	TYPE pt = NULL_type ;
1342
	int ext = output_all ;
1343
	ulong pm = LINK_NONE ;
1344
	ulong vo = LINK_NONE ;
1345
	unsigned no_mems = 0 ;
1346
	unsigned no_bases = 0 ;
1347
	DECL_SPEC macc = dspec_none ;
1348
	GRAPH gr = DEREF_graph ( ctype_base ( ct ) ) ;
1349
	CLASS_INFO ci = DEREF_cinfo ( ctype_info ( ct ) ) ;
1350
	CLASS_TYPE cd = DEREF_ctype ( type_compound_defn ( dummy_class ) ) ;
1351
#if LANGUAGE_CPP
1352
	VIRTUAL vt = DEREF_virt ( ctype_virt ( ct ) ) ;
1353
#endif
1354
 
1355
	/* Check for tokenised types */
1356
	if ( ci & cinfo_token ) {
1357
	    IDENTIFIER id = DEREF_id ( ctype_name ( ct ) ) ;
1358
	    id = find_token ( id ) ;
1359
	    IGNORE enc_tokdef ( id, 0 ) ;
1360
	    n = DEREF_ulong ( id_no ( id ) ) ;
1361
	    COPY_ulong ( ctype_shape ( ct ), n ) ;
1362
	    return ( n ) ;
1363
	}
1364
 
1365
	/* Assign token number */
1366
	n = capsule_no ( NULL_string, VAR_token ) ;
1367
	COPY_ulong ( ctype_shape ( ct ), n ) ;
1368
 
1369
	/* Allow for recursive types */
1370
	if ( ci & cinfo_recursive ) {
1371
	    m = DEREF_ulong ( graph_al_tag ( gr ) ) ;
1372
	    if ( m == LINK_NONE ) {
1373
		m = capsule_no ( NULL_string, VAR_alignment ) ;
1374
		if ( ext ) {
1375
		    string s = mangle_typeid ( "~cpp.al.", ct ) ;
1376
		    m = capsule_name ( m, &s, VAR_alignment ) ;
1377
		}
1378
		COPY_ulong ( graph_al_tag ( gr ), m ) ;
1379
	    }
1380
	}
1381
 
1382
	/* Assign virtual function tokens */
1383
#if LANGUAGE_CPP
1384
	if ( !IS_NULL_virt ( vt ) ) {
1385
	    OFFSET off = DEREF_off ( virt_table_off ( vt ) ) ;
1386
	    if ( !IS_NULL_off ( off ) ) vt = NULL_virt ;
1387
	    IGNORE declare_vtable ( ct ) ;
1388
	}
1389
#endif
1390
 
1391
	/* Scan through direct base classes */
1392
	br = DEREF_list ( graph_tails ( gr ) ) ;
1393
	while ( !IS_NULL_list ( br ) ) {
1394
	    int virt = 0 ;
1395
	    GRAPH gs = DEREF_graph ( HEAD_list ( br ) ) ;
1396
	    DECL_SPEC acc = DEREF_dspec ( graph_access ( gs ) ) ;
1397
	    CLASS_TYPE cs = DEREF_ctype ( graph_head ( gs ) ) ;
1398
 
1399
	    /* Define offset token */
1400
	    IGNORE compile_class ( cs ) ;
1401
	    m = capsule_no ( NULL_string, VAR_token ) ;
1402
	    if ( ext ) {
1403
		string s = mangle_vtable ( "~cpp.base.", gs ) ;
1404
		m = capsule_name ( m, &s, VAR_token ) ;
1405
	    }
1406
	    COPY_ulong ( graph_base_off ( gs ), m ) ;
1407
	    bs = enc_tokdef_start ( m, "E", NIL ( ulong ), 1 ) ;
1408
	    if ( pm == LINK_NONE ) {
1409
		/* First base class */
1410
		ENC_offset_zero ( bs ) ;
1411
		if ( acc & dspec_virtual ) {
1412
		    ENC_alignment ( bs ) ;
1413
		    ENC_pointer ( bs ) ;
1414
		    ENC_alignment ( bs ) ;
1415
		    ENC_top ( bs ) ;
1416
		    virt = 1 ;
1417
		} else {
1418
		    bs = enc_al_ctype ( bs, cs ) ;
1419
		}
1420
	    } else {
1421
		/* Subsequent base classes */
1422
		ENC_offset_pad ( bs ) ;
1423
		if ( acc & dspec_virtual ) {
1424
		    ENC_alignment ( bs ) ;
1425
		    ENC_pointer ( bs ) ;
1426
		    ENC_alignment ( bs ) ;
1427
		    ENC_top ( bs ) ;
1428
		    virt = 1 ;
1429
		} else {
1430
		    bs = enc_al_ctype ( bs, cs ) ;
1431
		}
1432
		ENC_offset_add ( bs ) ;
1433
		bs = enc_exp_token ( bs, pm ) ;
1434
		bs = enc_offset_add ( bs, pt ) ;
1435
	    }
1436
	    enc_tokdef_end ( m, bs ) ;
1437
 
1438
	    /* Find member type */
1439
	    pt = dummy_class ;
1440
	    COPY_ctype ( type_compound_defn ( pt ), cs ) ;
1441
	    if ( virt ) {
1442
		pt = ptr_dummy_class ;
1443
	    } else {
1444
		no_bases++ ;
1445
	    }
1446
	    pm = m ;
1447
	    br = TAIL_list ( br ) ;
1448
	}
1449
 
1450
	/* Scan through data members */
1451
	ts = start_bitstream ( NIL ( FILE ), tokdef_unit->link ) ;
1452
	ns = DEREF_nspace ( ctype_member ( ct ) ) ;
1453
	if ( output_order ) macc = dspec_public ;
1454
	do {
1455
	    DECL_SPEC nacc = dspec_none ;
1456
	    MEMBER mem = DEREF_member ( nspace_ctype_first ( ns ) ) ;
1457
	    mem = next_data_member ( mem, 1 ) ;
1458
	    while ( !IS_NULL_member ( mem ) ) {
1459
		unsigned real_mem = 1 ;
1460
		IDENTIFIER mid = DEREF_id ( member_id ( mem ) ) ;
1461
		TYPE t = DEREF_type ( id_member_type ( mid ) ) ;
1462
		if ( ci & cinfo_union ) {
1463
		    /* Union types */
1464
		    m = LINK_ZERO ;
1465
		    if ( !IS_NULL_type ( pt ) ) {
1466
			ENC_offset_max ( ts ) ;
1467
			ENC_shape_offset ( ts ) ;
1468
			ts = enc_shape ( ts, pt ) ;
1469
		    }
1470
		    no_mems = 1 ;
1471
		} else {
1472
		    /* Structure types */
1473
		    if ( macc ) {
1474
			/* Check member access */
1475
			DECL_SPEC acc = DEREF_dspec ( id_storage ( mid ) ) ;
1476
			acc &= dspec_access ;
1477
			if ( acc != macc ) {
1478
			    mem = DEREF_member ( member_next ( mem ) ) ;
1479
			    mem = next_data_member ( mem, 1 ) ;
1480
			    if ( acc > macc ) {
1481
				/* Find next access to check */
1482
				if ( acc == dspec_protected ) {
1483
				    nacc = dspec_protected ;
1484
				} else if ( nacc == dspec_none ) {
1485
				    nacc = dspec_private ;
1486
				}
1487
			    }
1488
			    continue ;
1489
			}
1490
		    }
1491
		    m = DEREF_ulong ( id_no ( mid ) ) ;
1492
		    if ( m == LINK_NONE ) {
1493
			m = capsule_no ( NULL_string, VAR_token ) ;
1494
			if ( ext ) {
1495
			    string s = mangle_name ( mid, VAR_token, 0 ) ;
1496
			    m = capsule_name ( m, &s, VAR_token ) ;
1497
			}
1498
			bs = enc_tokdef_start ( m, "E", NIL ( ulong ), 1 ) ;
1499
			if ( pm == LINK_NONE ) {
1500
			    /* First member */
1501
			    if ( IS_type_bitfield ( t ) ) {
1502
				/* Bitfield members */
1503
				TYPE r = find_bitfield_type ( t ) ;
1504
				if ( !is_zero_bitfield ( t ) ) {
1505
				    ENC_offset_pad ( bs ) ;
1506
				    bs = enc_alignment ( bs, t ) ;
1507
				}
1508
				ENC_offset_zero ( bs ) ;
1509
				bs = enc_alignment ( bs, r ) ;
1510
				nm = DEREF_hashid ( id_name ( mid ) ) ;
1511
				if ( IS_hashid_anon ( nm ) ) real_mem = 0 ;
1512
			    } else {
1513
				/* Non-bitfield members */
1514
				ENC_offset_zero ( bs ) ;
1515
				bs = enc_alignment ( bs, t ) ;
1516
			    }
1517
			} else {
1518
			    /* Subsequent members */
1519
			    bs = enc_offset_pad ( bs, pm, pt, t ) ;
1520
			    if ( IS_type_bitfield ( t ) ) {
1521
				nm = DEREF_hashid ( id_name ( mid ) ) ;
1522
				if ( IS_hashid_anon ( nm ) ) real_mem = 0 ;
1523
			    }
1524
			}
1525
			enc_tokdef_end ( m, bs ) ;
1526
		    }
1527
		    no_mems += real_mem ;
1528
		    pm = m ;
1529
		}
1530
		COPY_ulong ( id_no ( mid ), m ) ;
1531
		pt = t ;
1532
		mem = DEREF_member ( member_next ( mem ) ) ;
1533
		mem = next_data_member ( mem, 1 ) ;
1534
	    }
1535
	    macc = nacc ;
1536
	} while ( macc ) ;
1537
 
1538
	/* Allow for virtual function table */
1539
#if LANGUAGE_CPP
1540
	if ( !IS_NULL_virt ( vt ) ) {
1541
	    TYPE t = ptr_dummy_vtab ;
1542
	    m = DEREF_ulong ( virt_table_tok ( vt ) ) ;
1543
	    if ( ext ) {
1544
		string s = mangle_typeid ( "~cpp.vptr.", ct ) ;
1545
		m = capsule_name ( m, &s, VAR_token ) ;
1546
	    }
1547
	    size_dummy_vtab = DEREF_ulong ( virt_no ( vt ) ) ;
1548
	    bs = enc_tokdef_start ( m, "E", NIL ( ulong ), 1 ) ;
1549
	    if ( pm == LINK_NONE ) {
1550
		ENC_offset_zero ( bs ) ;
1551
		bs = enc_alignment ( bs, t ) ;
1552
	    } else {
1553
		bs = enc_offset_pad ( bs, pm, pt, t ) ;
1554
	    }
1555
	    enc_tokdef_end ( m, bs ) ;
1556
	    pt = t ;
1557
	    pm = m ;
1558
	    no_bases++ ;
1559
	}
1560
#endif
1561
 
1562
	/* Scan through virtual bases */
1563
	br = DEREF_list ( ctype_vbase ( ct ) ) ;
1564
	while ( !IS_NULL_list ( br ) ) {
1565
	    GRAPH gs = DEREF_graph ( HEAD_list ( br ) ) ;
1566
	    CLASS_TYPE cs = DEREF_ctype ( graph_head ( gs ) ) ;
1567
 
1568
	    /* Define offset token */
1569
	    IGNORE compile_class ( cs ) ;
1570
	    m = capsule_no ( NULL_string, VAR_token ) ;
1571
	    if ( ext ) {
1572
		string s = mangle_vtable ( "~cpp.virt.", gs ) ;
1573
		m = capsule_name ( m, &s, VAR_token ) ;
1574
	    }
1575
	    bs = enc_tokdef_start ( m, "E", NIL ( ulong ), 1 ) ;
1576
	    ENC_offset_pad ( bs ) ;
1577
	    bs = enc_al_ctype ( bs, cs ) ;
1578
	    ENC_offset_add ( bs ) ;
1579
	    bs = enc_exp_token ( bs, pm ) ;
1580
	    bs = enc_offset_add ( bs, pt ) ;
1581
	    enc_tokdef_end ( m, bs ) ;
1582
	    do {
1583
		/* All copies have the same real offset */
1584
		COPY_ulong ( graph_real_off ( gs ), m ) ;
1585
		gs = DEREF_graph ( graph_equal ( gs ) ) ;
1586
	    } while ( !IS_NULL_graph ( gs ) ) ;
1587
	    if ( vo == LINK_NONE ) vo = m ;
1588
	    pt = dummy_class ;
1589
	    COPY_ctype ( type_compound_defn ( pt ), cs ) ;
1590
	    pm = m ;
1591
	    no_bases++ ;
1592
	    br = TAIL_list ( br ) ;
1593
	}
1594
 
1595
	/* Define the overall shape token */
1596
	no_mems += no_bases ;
1597
	if ( no_mems ) {
1598
	    /* Non-empty structure offset definition */
1599
	    m = capsule_no ( NULL_string, VAR_token ) ;
1600
	    if ( ext ) {
1601
		string s = mangle_typeid ( "~cpp.off.", ct ) ;
1602
		m = capsule_name ( m, &s, VAR_token ) ;
1603
	    }
1604
	    bs = enc_tokdef_start ( m, "E", NIL ( ulong ), 1 ) ;
1605
	    bs = enc_special ( bs, TOK_comp_off ) ;
1606
	    if ( ci & cinfo_union ) {
1607
		/* Complete union definition */
1608
		ENC_shape_offset ( ts ) ;
1609
		ts = enc_shape ( ts, pt ) ;
1610
	    } else {
1611
		/* Complete structure definition */
1612
		ts = enc_offset_pad ( ts, pm, pt, NULL_type ) ;
1613
	    }
1614
	    bs = enc_bitstream ( bs, ts ) ;
1615
	    enc_tokdef_end ( m, bs ) ;
1616
 
1617
	    /* Record offset of non-virtual components */
1618
	    if ( vo == LINK_NONE ) vo = m ;
1619
	    COPY_ulong ( graph_core_off ( gr ), vo ) ;
1620
 
1621
	    /* Non-empty structure shape definition */
1622
	    if ( ext ) {
1623
		string s = mangle_typeid ( "~cpp.sh.", ct ) ;
1624
		n = capsule_name ( n, &s, VAR_token ) ;
1625
	    }
1626
	    bs = enc_tokdef_start ( n, "S", NIL ( ulong ), 1 ) ;
1627
	    ENC_compound ( bs ) ;
1628
	    bs = enc_exp_token ( bs, m ) ;
1629
	    enc_tokdef_end ( n, bs ) ;
1630
	    ci &= ~cinfo_empty ;
1631
 
1632
	} else {
1633
	    /* Empty structure definition */
1634
	    clear_usage ( n, VAR_token ) ;
1635
	    n = special_no ( TOK_empty_shape ) ;
1636
	    COPY_ulong ( ctype_shape ( ct ), n ) ;
1637
	    vo = special_no ( TOK_empty_offset ) ;
1638
	    COPY_ulong ( graph_core_off ( gr ), vo ) ;
1639
	    ci |= cinfo_empty ;
1640
	}
1641
	COPY_cinfo ( ctype_info ( ct ), ci ) ;
1642
 
1643
	/* Define associated alignment tag */
1644
	m = DEREF_ulong ( graph_al_tag ( gr ) ) ;
1645
	if ( m != LINK_NONE ) enc_al_tagdef ( m, n ) ;
1646
	COPY_ctype ( type_compound_defn ( dummy_class ), cd ) ;
1647
    }
1648
    return ( n ) ;
1649
}
1650
 
1651
 
1652
/*
1653
    ENCODE THE SHAPE OF A CLASS TYPE
1654
 
1655
    This routine adds the class type ct to the bitstream bs as a TDF SHAPE.
1656
*/
1657
 
1658
BITSTREAM *enc_ctype
1659
    PROTO_N ( ( bs, ct ) )
1660
    PROTO_T ( BITSTREAM *bs X CLASS_TYPE ct )
1661
{
1662
    ulong n = compile_class ( ct ) ;
1663
    bs = enc_shape_token ( bs, n ) ;
1664
    return ( bs ) ;
1665
}
1666
 
1667
 
1668
/*
1669
    LIST OF INCOMPLETE CLASSES
1670
 
1671
    This list is used to hold all the classes which are used while they
1672
    are incomplete.  An alignment tag is introduced for each such class
1673
    which may be defined later if the class is completed.
1674
*/
1675
 
1676
static LIST ( CLASS_TYPE ) incompl_classes = NULL_list ( CLASS_TYPE ) ;
1677
 
1678
 
1679
/*
1680
    DEFINE INCOMPLETE CLASSES
1681
 
1682
    This routine defines the alignment tags for the incomplete classes
1683
    in this list above.  Note that the class is not compiled if it has
1684
    not already been so.
1685
*/
1686
 
1687
void compile_incompl
1688
    PROTO_Z ()
1689
{
1690
    LIST ( CLASS_TYPE ) p = incompl_classes ;
1691
    while ( !IS_NULL_list ( p ) ) {
1692
	CLASS_TYPE ct = DEREF_ctype ( HEAD_list ( p ) ) ;
1693
	ulong n = DEREF_ulong ( ctype_shape ( ct ) ) ;
1694
	if ( n == LINK_NONE ) {
1695
	    /* Uncompiled or incomplete class */
1696
	    GRAPH gr = DEREF_graph ( ctype_base ( ct ) ) ;
1697
	    ulong m = DEREF_ulong ( graph_al_tag ( gr ) ) ;
1698
	    enc_al_tagdef ( m, n ) ;
1699
	}
1700
	p = TAIL_list ( p ) ;
1701
    }
1702
    DESTROY_list ( incompl_classes, SIZE_ctype ) ;
1703
    incompl_classes = NULL_list ( CLASS_TYPE ) ;
1704
    return ;
1705
}
1706
 
1707
 
1708
/*
1709
    ENCODE THE ALIGNMENT OF A CLASS TYPE
1710
 
1711
    This routine adds the alignment of the class type ct to the bitstream
1712
    bs.  Note that ct is not compiled by this routine.
1713
*/
1714
 
1715
BITSTREAM *enc_al_ctype
1716
    PROTO_N ( ( bs, ct ) )
1717
    PROTO_T ( BITSTREAM *bs X CLASS_TYPE ct )
1718
{
1719
    GRAPH gr = DEREF_graph ( ctype_base ( ct ) ) ;
1720
    ulong m = DEREF_ulong ( graph_al_tag ( gr ) ) ;
1721
    if ( m == LINK_NONE ) {
1722
	string s = NULL ;
1723
	ulong n = DEREF_ulong ( ctype_shape ( ct ) ) ;
1724
	if ( n != LINK_NONE ) {
1725
	    /* Class already compiled */
1726
	    ENC_alignment ( bs ) ;
1727
	    bs = enc_shape_token ( bs, n ) ;
1728
	    return ( bs ) ;
1729
	}
1730
	if ( output_all ) s = mangle_typeid ( "~cpp.al.", ct ) ;
1731
	m = capsule_no ( s, VAR_alignment ) ;
1732
	COPY_ulong ( graph_al_tag ( gr ), m ) ;
1733
	CONS_ctype ( ct, incompl_classes, incompl_classes ) ;
1734
    }
1735
    m = link_no ( bs, m, VAR_alignment ) ;
1736
    ENC_obtain_al_tag ( bs ) ;
1737
    ENC_make_al_tag ( bs, m ) ;
1738
    return ( bs ) ;
1739
}
1740
 
1741
 
1742
/*
1743
    COMPILE A BASE CLASS
1744
 
1745
    This routine compiles the base class graph gr returning a token
1746
    number representing the base class offset.  If gr is a virtual base
1747
    and ptr is true then this is the offset of the pointer to the base,
1748
    otherwise it is the actual base.
1749
*/
1750
 
1751
static ulong compile_base
1752
    PROTO_N ( ( gr, ptr ) )
1753
    PROTO_T ( GRAPH gr X int ptr )
1754
{
1755
    ulong n, m ;
1756
    GRAPH g1, g2 ;
1757
    BITSTREAM *bs ;
1758
    string s = NULL ;
1759
    OFFSET off = DEREF_off ( graph_off ( gr ) ) ;
1760
    DECL_SPEC acc = DEREF_dspec ( graph_access ( gr ) ) ;
1761
    if ( ( acc & dspec_virtual ) && !ptr ) {
1762
	/* Virtual base class */
1763
	n = DEREF_ulong ( graph_real_off ( gr ) ) ;
1764
	return ( n ) ;
1765
    }
1766
    if ( IS_off_base ( off ) ) {
1767
	/* Direct base class */
1768
	n = DEREF_ulong ( graph_base_off ( gr ) ) ;
1769
	return ( n ) ;
1770
    }
1771
 
1772
    /* Check for recorded values */
1773
    if ( ptr ) {
1774
	n = DEREF_ulong ( graph_base_off ( gr ) ) ;
1775
    } else {
1776
	n = DEREF_ulong ( graph_real_off ( gr ) ) ;
1777
    }
1778
    if ( n != LINK_NONE ) return ( n ) ;
1779
    if ( output_all ) {
1780
	CONST char *pre = "~cpp.base." ;
1781
	if ( ( acc & dspec_mutable ) && !ptr ) pre = "~cpp.virt." ;
1782
	s = mangle_vtable ( pre, gr ) ;
1783
    }
1784
    n = capsule_no ( s, VAR_token ) ;
1785
 
1786
    /* Decompose base offset */
1787
    if ( acc & dspec_mutable ) {
1788
	/* Base of virtual base */
1789
	CLASS_TYPE cs ;
1790
	g1 = DEREF_graph ( graph_up ( gr ) ) ;
1791
	cs = DEREF_ctype ( graph_head ( g1 ) ) ;
1792
	g2 = DEREF_graph ( ctype_base ( cs ) ) ;
1793
	g2 = find_subgraph ( g2, g1, gr ) ;
1794
	if ( ptr ) {
1795
	    COPY_ulong ( graph_base_off ( gr ), n ) ;
1796
	} else {
1797
	    COPY_ulong ( graph_real_off ( gr ), n ) ;
1798
	}
1799
    } else {
1800
	/* Indirect base */
1801
	OFFSET off1 = DEREF_off ( off_deriv_direct ( off ) ) ;
1802
	OFFSET off2 = DEREF_off ( off_deriv_indirect ( off ) ) ;
1803
	g1 = DEREF_graph ( off_base_graph ( off1 ) ) ;
1804
	if ( IS_off_base ( off2 ) ) {
1805
	    g2 = DEREF_graph ( off_base_graph ( off2 ) ) ;
1806
	} else {
1807
	    g2 = DEREF_graph ( off_deriv_graph ( off2 ) ) ;
1808
	}
1809
	COPY_ulong ( graph_base_off ( gr ), n ) ;
1810
	COPY_ulong ( graph_real_off ( gr ), n ) ;
1811
    }
1812
 
1813
    /* Define the token */
1814
    bs = enc_tokdef_start ( n, "E", NIL ( ulong ), 1 ) ;
1815
    ENC_offset_add ( bs ) ;
1816
    m = compile_base ( g1, 0 ) ;
1817
    bs = enc_exp_token ( bs, m ) ;
1818
    m = compile_base ( g2, ptr ) ;
1819
    bs = enc_exp_token ( bs, m ) ;
1820
    enc_tokdef_end ( n, bs ) ;
1821
    return ( n ) ;
1822
}
1823
 
1824
 
1825
/*
1826
    ENCODE A BASE CLASS OFFSET
1827
 
1828
    This routine adds an offset representing the base class graph gr
1829
    to the bitstream bs.  For virtual bases this is the offset of the
1830
    pointer to the base if ptr is true and the offset of the actual base
1831
    otherwise.
1832
*/
1833
 
1834
BITSTREAM *enc_base
1835
    PROTO_N ( ( bs, gr, ptr ) )
1836
    PROTO_T ( BITSTREAM *bs X GRAPH gr X int ptr )
1837
{
1838
    GRAPH gt = DEREF_graph ( graph_top ( gr ) ) ;
1839
    CLASS_TYPE ct = DEREF_ctype ( graph_head ( gt ) ) ;
1840
    if ( EQ_graph ( gr, gt ) ) {
1841
	ENC_offset_zero ( bs ) ;
1842
	bs = enc_al_ctype ( bs, ct ) ;
1843
    } else {
1844
	ulong n ;
1845
	IGNORE compile_class ( ct ) ;
1846
	n = compile_base ( gr, ptr ) ;
1847
	bs = enc_exp_token ( bs, n ) ;
1848
    }
1849
    return ( bs ) ;
1850
}
1851
 
1852
 
1853
/*
1854
    ENCODE THE START OF A VIRTUAL BASE CLASS POINTER EXPRESSION
1855
 
1856
    This routine adds the start of a virtual base class pointer expression
1857
    to the bitstream bs.  off1 gives the direct component of the offset
1858
    and off2 gives the indirect component.
1859
*/
1860
 
1861
BITSTREAM *enc_add_base
1862
    PROTO_N ( ( bs, off1, off2 ) )
1863
    PROTO_T ( BITSTREAM *bs X OFFSET off1 X OFFSET off2 )
1864
{
1865
    GRAPH gr = DEREF_graph ( off_base_graph ( off1 ) ) ;
1866
    DECL_SPEC acc = DEREF_dspec ( graph_access ( gr ) ) ;
1867
    if ( !IS_NULL_off ( off2 ) ) {
1868
	if ( IS_off_deriv ( off2 ) ) {
1869
	    OFFSET off3 = DEREF_off ( off_deriv_direct ( off2 ) ) ;
1870
	    OFFSET off4 = DEREF_off ( off_deriv_indirect ( off2 ) ) ;
1871
	    bs = enc_add_base ( bs, off3, off4 ) ;
1872
	} else {
1873
	    bs = enc_add_base ( bs, off2, NULL_off ) ;
1874
	}
1875
    }
1876
    if ( acc & dspec_virtual ) {
1877
	/* Indirection for virtual bases */
1878
	CLASS_TYPE ct = DEREF_ctype ( graph_head ( gr ) ) ;
1879
	ENC_contents ( bs ) ;
1880
	ENC_pointer ( bs ) ;
1881
	bs = enc_al_ctype ( bs, ct ) ;
1882
    }
1883
    if ( !( acc & dspec_ignore ) ) {
1884
	/* Add base class offset */
1885
	ENC_add_to_ptr ( bs ) ;
1886
    }
1887
    return ( bs ) ;
1888
}
1889
 
1890
 
1891
/*
1892
    ENCODE THE END OF A VIRTUAL BASE CLASS POINTER EXPRESSION
1893
 
1894
    This routine adds the end of a virtual base class pointer expression
1895
    to the bitstream bs.  off1 gives the direct component of the offset
1896
    and off2 gives the indirect component.
1897
*/
1898
 
1899
BITSTREAM *enc_end_base
1900
    PROTO_N ( ( bs, off1, off2 ) )
1901
    PROTO_T ( BITSTREAM *bs X OFFSET off1 X OFFSET off2 )
1902
{
1903
    GRAPH gr = DEREF_graph ( off_base_graph ( off1 ) ) ;
1904
    DECL_SPEC acc = DEREF_dspec ( graph_access ( gr ) ) ;
1905
    if ( !( acc & dspec_ignore ) ) {
1906
	/* Output base class offset */
1907
	ulong n = DEREF_ulong ( graph_base_off ( gr ) ) ;
1908
	if ( n == LINK_NONE ) {
1909
	    /* Compile class if necessary */
1910
	    GRAPH gt = DEREF_graph ( graph_top ( gr ) ) ;
1911
	    CLASS_TYPE ct = DEREF_ctype ( graph_head ( gt ) ) ;
1912
	    IGNORE compile_class ( ct ) ;
1913
	    n = DEREF_ulong ( graph_base_off ( gr ) ) ;
1914
	}
1915
	bs = enc_exp_token ( bs, n ) ;
1916
    }
1917
    if ( !IS_NULL_off ( off2 ) ) {
1918
	if ( IS_off_deriv ( off2 ) ) {
1919
	    OFFSET off3 = DEREF_off ( off_deriv_direct ( off2 ) ) ;
1920
	    OFFSET off4 = DEREF_off ( off_deriv_indirect ( off2 ) ) ;
1921
	    bs = enc_end_base ( bs, off3, off4 ) ;
1922
	} else {
1923
	    bs = enc_end_base ( bs, off2, NULL_off ) ;
1924
	}
1925
    }
1926
    return ( bs ) ;
1927
}
1928
 
1929
 
1930
/*
1931
    ENCODE A MEMBER OFFSET
1932
 
1933
    This routine adds the offset of the member id to the bitstream bs.
1934
    If id is a data member this is the offset of the member from the start
1935
    of the structure.
1936
*/
1937
 
1938
BITSTREAM *enc_member
1939
    PROTO_N ( ( bs, id ) )
1940
    PROTO_T ( BITSTREAM *bs X IDENTIFIER id )
1941
{
1942
    ulong tok ;
1943
    unsigned tag = TAG_id ( id ) ;
1944
    if ( tag == id_member_tag ) {
1945
	/* Simple data member */
1946
	OFFSET off = DEREF_off ( id_member_off ( id ) ) ;
1947
	if ( IS_off_member ( off ) ) {
1948
	    tok = DEREF_ulong ( id_no ( id ) ) ;
1949
	    if ( tok == LINK_NONE ) {
1950
		CLASS_TYPE ct = parent_class ( id ) ;
1951
		IGNORE compile_class ( ct ) ;
1952
		tok = DEREF_ulong ( id_no ( id ) ) ;
1953
	    }
1954
	    if ( tok == LINK_ZERO ) {
1955
		/* Union member */
1956
		TYPE t = DEREF_type ( id_member_type ( id ) ) ;
1957
		ENC_offset_zero ( bs ) ;
1958
		bs = enc_alignment ( bs, t ) ;
1959
	    } else {
1960
		/* Structure member */
1961
		bs = enc_exp_token ( bs, tok ) ;
1962
	    }
1963
	} else {
1964
	    bs = enc_offset ( bs, off ) ;
1965
	}
1966
    } else {
1967
	/* Static data members and member functions */
1968
	IGNORE capsule_id ( id, VAR_tag ) ;
1969
	tok = unit_no ( bs, id, VAR_tag, 0 ) ;
1970
	ENC_obtain_tag ( bs ) ;
1971
	ENC_make_tag ( bs, tok ) ;
1972
    }
1973
    return ( bs ) ;
1974
}
1975
 
1976
 
1977
/*
1978
    ENCODE A NULL CLASS OBJECT DEFINITION
1979
 
1980
    This routine adds an expression representing a null value of type
1981
    ct to the bitstream bs.  The virtual base components are only
1982
    included if virt is true.  Note that the order of the components
1983
    is not necessarily the same as that in compile_class, but the
1984
    installers always sort make_compound expressions into the correct
1985
    order.
1986
*/
1987
 
1988
static BITSTREAM *enc_null_class_aux
1989
    PROTO_N ( ( bs, ct, virt ) )
1990
    PROTO_T ( BITSTREAM *bs X CLASS_TYPE ct X int virt )
1991
{
1992
    CLASS_INFO ci = DEREF_cinfo ( ctype_info ( ct ) ) ;
1993
    if ( ci & ( cinfo_empty | cinfo_token ) ) {
1994
	/* Tokenised and empty classes */
1995
	ENC_make_value ( bs ) ;
1996
	bs = enc_ctype ( bs, ct ) ;
1997
    } else {
1998
	/* Non-empty classes */
1999
	MEMBER mem ;
2000
	unsigned no_mems = 0 ;
2001
	GRAPH gr = DEREF_graph ( ctype_base ( ct ) ) ;
2002
	LIST ( GRAPH ) br = DEREF_list ( graph_tails ( gr ) ) ;
2003
	LIST ( GRAPH ) bv = DEREF_list ( ctype_vbase ( ct ) ) ;
2004
	NAMESPACE ns = DEREF_nspace ( ctype_member ( ct ) ) ;
2005
	BITSTREAM *ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
2006
 
2007
	/* Scan through direct base classes */
2008
	while ( !IS_NULL_list ( br ) ) {
2009
	    GRAPH gs = DEREF_graph ( HEAD_list ( br ) ) ;
2010
	    DECL_SPEC acc = DEREF_dspec ( graph_access ( gs ) ) ;
2011
	    CLASS_TYPE cs = DEREF_ctype ( graph_head ( gs ) ) ;
2012
	    ulong m = DEREF_ulong ( graph_base_off ( gs ) ) ;
2013
	    if ( acc & dspec_virtual ) {
2014
		ts = enc_exp_token ( ts, m ) ;
2015
		ENC_make_null_ptr ( ts ) ;
2016
		ts = enc_al_ctype ( ts, cs ) ;
2017
		no_mems++ ;
2018
	    } else {
2019
		CLASS_INFO cj = DEREF_cinfo ( ctype_info ( cs ) ) ;
2020
		if ( !( cj & cinfo_empty ) ) {
2021
		    ts = enc_exp_token ( ts, m ) ;
2022
		    ts = enc_null_class_aux ( ts, cs, 0 ) ;
2023
		    no_mems++ ;
2024
		}
2025
	    }
2026
	    br = TAIL_list ( br ) ;
2027
	}
2028
 
2029
	/* Scan through data members */
2030
	mem = DEREF_member ( nspace_ctype_first ( ns ) ) ;
2031
	mem = next_data_member ( mem, 0 ) ;
2032
	while ( !IS_NULL_member ( mem ) ) {
2033
	    IDENTIFIER mid = DEREF_id ( member_id ( mem ) ) ;
2034
	    TYPE s = DEREF_type ( id_member_type ( mid ) ) ;
2035
	    ts = enc_member ( ts, mid ) ;
2036
	    ts = enc_null_exp ( ts, s ) ;
2037
	    no_mems++ ;
2038
	    if ( ci & cinfo_union ) break ;
2039
	    mem = DEREF_member ( member_next ( mem ) ) ;
2040
	    mem = next_data_member ( mem, 0 ) ;
2041
	}
2042
 
2043
	/* Scan through virtual function tables */
2044
#if LANGUAGE_CPP
2045
	if ( ci & cinfo_polymorphic ) {
2046
	    VIRTUAL vt = DEREF_virt ( ctype_virt ( ct ) ) ;
2047
	    while ( !IS_NULL_virt ( vt ) ) {
2048
		OFFSET off = DEREF_off ( virt_table_off ( vt ) ) ;
2049
		if ( IS_NULL_off ( off ) ) {
2050
		    ulong m = DEREF_ulong ( virt_table_tok ( vt ) ) ;
2051
		    ts = enc_exp_token ( ts, m ) ;
2052
		    size_dummy_vtab = DEREF_ulong ( virt_no ( vt ) ) ;
2053
		    ts = enc_null_exp ( ts, ptr_dummy_vtab ) ;
2054
		    no_mems++ ;
2055
		}
2056
		vt = DEREF_virt ( virt_next ( vt ) ) ;
2057
	    }
2058
	}
2059
#endif
2060
 
2061
	/* Scan through virtual bases */
2062
	if ( virt ) {
2063
	    while ( !IS_NULL_list ( bv ) ) {
2064
		GRAPH gs = DEREF_graph ( HEAD_list ( bv ) ) ;
2065
		CLASS_TYPE cs = DEREF_ctype ( graph_head ( gs ) ) ;
2066
		CLASS_INFO cj = DEREF_cinfo ( ctype_info ( cs ) ) ;
2067
		if ( !( cj & cinfo_empty ) ) {
2068
		    ulong m = DEREF_ulong ( graph_real_off ( gs ) ) ;
2069
		    ts = enc_exp_token ( ts, m ) ;
2070
		    ts = enc_null_class_aux ( ts, cs, 0 ) ;
2071
		    no_mems++ ;
2072
		}
2073
		bv = TAIL_list ( bv ) ;
2074
	    }
2075
	} else {
2076
	    if ( IS_NULL_list ( bv ) ) virt = 1 ;
2077
	}
2078
 
2079
	/* Encode complete construct */
2080
	if ( no_mems ) {
2081
	    ENC_make_compound ( bs ) ;
2082
	    if ( virt ) {
2083
		ENC_shape_offset ( bs ) ;
2084
		bs = enc_ctype ( bs, ct ) ;
2085
	    } else {
2086
		ulong m = DEREF_ulong ( graph_core_off ( gr ) ) ;
2087
		if ( m == LINK_NONE ) {
2088
		    ENC_shape_offset ( bs ) ;
2089
		    bs = enc_ctype ( bs, ct ) ;
2090
		} else {
2091
		    bs = enc_exp_token ( bs, m ) ;
2092
		}
2093
	    }
2094
	    ENC_LIST ( bs, no_mems + no_mems ) ;
2095
	    bs = join_bitstreams ( bs, ts ) ;
2096
	} else {
2097
	    ENC_make_value ( bs ) ;
2098
	    bs = enc_ctype ( bs, ct ) ;
2099
	    end_bitstream ( ts, 0 ) ;
2100
	}
2101
    }
2102
    return ( bs ) ;
2103
}
2104
 
2105
 
2106
/*
2107
    ENCODE A NULL CLASS OBJECT
2108
 
2109
    This routine adds the default null value for the class type ct to the
2110
    bitstream bs.  This is represented by a token which is defined the
2111
    first time the routine is called.
2112
*/
2113
 
2114
BITSTREAM *enc_null_class
2115
    PROTO_N ( ( bs, ct ) )
2116
    PROTO_T ( BITSTREAM *bs X CLASS_TYPE ct )
2117
{
2118
    ulong n = DEREF_ulong ( ctype_null_exp ( ct ) ) ;
2119
    if ( n == LINK_NONE ) {
2120
	/* Define token for null value */
2121
	BITSTREAM *ts ;
2122
	string s = NULL ;
2123
	IGNORE compile_class ( ct ) ;
2124
	if ( output_all ) s = mangle_typeid ( "~cpp.null.", ct ) ;
2125
	n = capsule_no ( s, VAR_token ) ;
2126
	COPY_ulong ( ctype_null_exp ( ct ), n ) ;
2127
	ts = enc_tokdef_start ( n, "E", NIL ( ulong ), 1 ) ;
2128
	ts = enc_null_class_aux ( ts, ct, 1 ) ;
2129
	enc_tokdef_end ( n, ts ) ;
2130
    }
2131
    bs = enc_exp_token ( bs, n ) ;
2132
    return ( bs ) ;
2133
}
2134
 
2135
 
2136
/*
2137
    CONSTRUCTOR INITIALISER ROUTINES
2138
 
2139
    The constructor initialiser routines are only included in the C++
2140
    producer.
2141
*/
2142
 
2143
#if LANGUAGE_CPP
2144
 
2145
 
2146
/*
2147
    ENCODE A CONSTRUCTOR INITIALISER
2148
 
2149
    This routine performs a construct initialisation using a at offset
2150
    off from the tag m.  virt controls how m is accessed.  Note that a
2151
    may be a dummy expression to indicate that m is initialised from
2152
    the corresponding offset from the second argument in a copy
2153
    constructor or assignment operator (see init_empty_base).
2154
*/
2155
 
2156
static BITSTREAM *enc_ctor_exp
2157
    PROTO_N ( ( bs, a, off, m, virt, seq ) )
2158
    PROTO_T ( BITSTREAM *bs X EXP a X OFFSET off X ulong m X
2159
	      int virt X unsigned seq )
2160
{
2161
    if ( !IS_NULL_exp ( a ) ) {
2162
	int context = 0 ;
2163
	EXP d = NULL_exp ;
2164
	TYPE s = DEREF_type ( exp_type ( a ) ) ;
2165
	if ( IS_exp_paren ( a ) ) {
2166
	    /* Used to mark destructors - see destr_init */
2167
	    if ( seq > 1 ) {
2168
		context = 5 ;
2169
		d = a ;
2170
	    }
2171
	    a = DEREF_exp ( exp_paren_arg ( a ) ) ;
2172
	}
2173
	if ( IS_NULL_exp ( a ) ) {
2174
	    /* EMPTY */
2175
	} else if ( IS_exp_value ( a ) ) {
2176
	    /* Copy assignment */
2177
	    int bf = 0 ;
2178
	    TYPE t = DEREF_type ( exp_type ( a ) ) ;
2179
	    bs = enc_assign_op ( bs, t, &bf ) ;
2180
	    if ( bf ) {
2181
		/* Bitfield assignment */
2182
		OFFSET off1 = off ;
2183
		OFFSET off2 = decons_bitf_off ( &off1 ) ;
2184
		bs = enc_dummy_exp ( bs, t, m, off1, 0, virt ) ;
2185
		bs = enc_offset ( bs, off2 ) ;
2186
	    } else {
2187
		/* Non-bitfield assignment */
2188
		bs = enc_dummy_exp ( bs, t, m, off, 0, virt ) ;
2189
	    }
2190
	    last_conts [ DUMMY_copy ] = 1 ;
2191
	    bs = enc_dummy_exp ( bs, t, LINK_NONE, off, DUMMY_copy, 1 ) ;
2192
	    last_conts [ DUMMY_copy ] = 0 ;
2193
	    seq-- ;
2194
	} else {
2195
	    /* Constructor initialiser */
2196
	    bs = enc_init_tag ( bs, m, off, 0, s, a, d, context ) ;
2197
	    if ( !IS_NULL_exp ( d ) ) {
2198
		d = NULL_exp ;
2199
		seq-- ;
2200
	    }
2201
	    seq-- ;
2202
	}
2203
	if ( !IS_NULL_exp ( d ) ) {
2204
	    /* Increase constructor count */
2205
	    bs = enc_destr_count ( bs, s, 1 ) ;
2206
	    seq-- ;
2207
	}
2208
    }
2209
    while ( seq ) {
2210
	ENC_make_top ( bs ) ;
2211
	seq-- ;
2212
    }
2213
    return ( bs ) ;
2214
}
2215
 
2216
 
2217
/*
2218
    INITIALISE VIRTUAL BASE POINTERS
2219
 
2220
    This routine adds a list of virtual base pointer initialisations
2221
    for an object with tag number m and class ct to the bitstream bs.
2222
*/
2223
 
2224
static BITSTREAM *enc_virt_init
2225
    PROTO_N ( ( bs, ct, m ) )
2226
    PROTO_T ( BITSTREAM *bs X CLASS_TYPE ct X ulong m )
2227
{
2228
    LIST ( GRAPH ) bv = DEREF_list ( ctype_vbase ( ct ) ) ;
2229
    while ( !IS_NULL_list ( bv ) ) {
2230
	GRAPH gr = DEREF_graph ( HEAD_list ( bv ) ) ;
2231
	ulong tv = DEREF_ulong ( graph_real_off ( gr ) ) ;
2232
	while ( !IS_NULL_graph ( gr ) ) {
2233
	    ulong tp = compile_base ( gr, 1 ) ;
2234
	    ENC_assign ( bs ) ;
2235
	    ENC_add_to_ptr ( bs ) ;
2236
	    ENC_obtain_tag ( bs ) ;
2237
	    ENC_make_tag ( bs, m ) ;
2238
	    bs = enc_exp_token ( bs, tp ) ;
2239
	    ENC_add_to_ptr ( bs ) ;
2240
	    ENC_obtain_tag ( bs ) ;
2241
	    ENC_make_tag ( bs, m ) ;
2242
	    bs = enc_exp_token ( bs, tv ) ;
2243
	    gr = DEREF_graph ( graph_equal ( gr ) ) ;
2244
	}
2245
	bv = TAIL_list ( bv ) ;
2246
    }
2247
    return ( bs ) ;
2248
}
2249
 
2250
 
2251
/*
2252
    INITIALISE VIRTUAL FUNCTION TABLES
2253
 
2254
    This routine adds a list of virtual function table initialisations
2255
    for an object with tag number m and class ct to the bitstream bs.
2256
*/
2257
 
2258
static BITSTREAM *enc_vtab_init
2259
    PROTO_N ( ( bs, ct, m, virt ) )
2260
    PROTO_T ( BITSTREAM *bs X CLASS_TYPE ct X ulong m X int virt )
2261
{
2262
    VIRTUAL vt = DEREF_virt ( ctype_virt ( ct ) ) ;
2263
    while ( !IS_NULL_virt ( vt ) ) {
2264
	OFFSET off = DEREF_off ( virt_table_off ( vt ) ) ;
2265
	ulong tv = DEREF_ulong ( virt_table_tok ( vt ) ) ;
2266
	ulong tt = DEREF_ulong ( virt_table_tbl ( vt ) ) ;
2267
	record_usage ( tt, VAR_tag, USAGE_USE ) ;
2268
	ENC_assign ( bs ) ;
2269
	ENC_add_to_ptr ( bs ) ;
2270
	if ( is_zero_offset ( off ) ) {
2271
	    ENC_obtain_tag ( bs ) ;
2272
	    ENC_make_tag ( bs, m ) ;
2273
	} else {
2274
	    TYPE t = ptr_dummy_class ;
2275
	    bs = enc_dummy_exp ( bs, t, m, off, 0, virt ) ;
2276
	}
2277
	bs = enc_exp_token ( bs, tv ) ;
2278
	tt = link_no ( bs, tt, VAR_tag ) ;
2279
	ENC_obtain_tag ( bs ) ;
2280
	ENC_make_tag ( bs, tt ) ;
2281
	vt = DEREF_virt ( virt_next ( vt ) ) ;
2282
    }
2283
    return ( bs ) ;
2284
}
2285
 
2286
 
2287
/*
2288
    DELETE AN OBJECT
2289
 
2290
    This routine adds the conditional deletion for an object with tag
2291
    number m and class ct to the bitstream bs.
2292
*/
2293
 
2294
static BITSTREAM *enc_delete_obj
2295
    PROTO_N ( ( bs, ct, m ) )
2296
    PROTO_T ( BITSTREAM *bs X CLASS_TYPE ct X ulong m )
2297
{
2298
    IDENTIFIER cid = DEREF_id ( ctype_name ( ct ) ) ;
2299
    TYPE t = DEREF_type ( id_class_name_etc_defn ( cid ) ) ;
2300
    IDENTIFIER fid = find_allocator ( t, lex_delete, 0, NULL_id ) ;
2301
    if ( IS_NULL_id ( fid ) ) {
2302
	/* This shouldn't happen */
2303
	ENC_make_top ( bs ) ;
2304
    } else {
2305
	ulong d ;
2306
	BITSTREAM *ts ;
2307
	TYPE fn = DEREF_type ( id_function_etc_type ( fid ) ) ;
2308
	LIST ( TYPE ) ptypes = DEREF_list ( type_func_ptypes ( fn ) ) ;
2309
	unsigned npids = LENGTH_list ( ptypes ) ;
2310
 
2311
	/* Mark the function as to be compiled */
2312
	IGNORE capsule_id ( fid, VAR_tag ) ;
2313
	CONS_id ( fid, pending_funcs, pending_funcs ) ;
2314
 
2315
	/* Encode the function call */
2316
	ENC_apply_proc ( bs ) ;
2317
	ENC_top ( bs ) ;
2318
	ENC_obtain_tag ( bs ) ;
2319
	d = unit_no ( bs, fid, VAR_tag, 0 ) ;
2320
	ENC_make_tag ( bs, d ) ;
2321
	if ( npids > 2 ) npids = 2 ;
2322
	ENC_LIST_SMALL ( bs, npids ) ;
2323
	bs = enc_special ( bs, TOK_to_ptr_void ) ;
2324
	ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
2325
	ts = enc_al_ctype ( ts, ct ) ;
2326
	ENC_obtain_tag ( ts ) ;
2327
	ENC_make_tag ( ts, m ) ;
2328
	bs = enc_bitstream ( bs, ts ) ;
2329
	if ( npids == 2 ) {
2330
	    /* Allow for second argument */
2331
	    TYPE s ;
2332
	    TYPE c = type_char ;
2333
	    ptypes = TAIL_list ( ptypes ) ;
2334
	    s = DEREF_type ( HEAD_list ( ptypes ) ) ;
2335
	    if ( !IS_type_integer ( s ) ) s = type_size_t ;
2336
	    ENC_offset_div ( bs ) ;
2337
	    bs = enc_variety ( bs, s ) ;
2338
	    bs = enc_shape_offset ( bs, t ) ;
2339
	    bs = enc_shape_offset ( bs, c ) ;
2340
	}
2341
	ENC_OFF ( bs ) ;
2342
    }
2343
    return ( bs ) ;
2344
}
2345
 
2346
 
2347
/*
2348
    ENCODE A LIST OF CONSTRUCTOR INITIALISERS
2349
 
2350
    This routine adds the list of constructor initialisers given by e
2351
    to the bitstream bs.
2352
*/
2353
 
2354
BITSTREAM *enc_ctor_init
2355
    PROTO_N ( ( bs, e ) )
2356
    PROTO_T ( BITSTREAM *bs X EXP e )
2357
{
2358
    ulong n, m ;
2359
    CLASS_TYPE ct = last_class ;
2360
    int kind = DEREF_int ( exp_initialiser_kind ( e ) ) ;
2361
    LIST ( EXP ) p = DEREF_list ( exp_initialiser_args ( e ) ) ;
2362
    LIST ( OFFSET ) q = DEREF_list ( exp_initialiser_offs ( e ) ) ;
2363
 
2364
    /* Find number of items */
2365
    unsigned np = LENGTH_list ( p ) ;
2366
    unsigned nv = DEREF_unsigned ( exp_initialiser_virt ( e ) ) ;
2367
    unsigned nb = DEREF_unsigned ( exp_initialiser_base ( e ) ) ;
2368
    unsigned no = np - nv ;
2369
 
2370
    /* Compile the class */
2371
    IGNORE compile_class ( ct ) ;
2372
 
2373
    /* Find the 'this' pointer */
2374
    n = last_params [ DUMMY_this ] ;
2375
    m = unit_no ( bs, NULL_id, VAR_tag, 1 ) ;
2376
    ENC_identify ( bs ) ;
2377
    bs = enc_access ( bs, crt_func_access ) ;
2378
    ENC_make_tag ( bs, m ) ;
2379
    ENC_contents ( bs ) ;
2380
    ENC_pointer ( bs ) ;
2381
    bs = enc_al_ctype ( bs, ct ) ;
2382
    ENC_obtain_tag ( bs ) ;
2383
    ENC_make_tag ( bs, n ) ;
2384
 
2385
    if ( kind == DEFAULT_DESTR ) {
2386
	/* Deal with destructors */
2387
	int context = 0 ;
2388
	unsigned ns = no + 1 ;
2389
	ulong m2 = last_params [ DUMMY_extra ] ;
2390
	if ( last_params [ DUMMY_count ] != LINK_NONE ) {
2391
	    context = 5 ;
2392
	    ns-- ;
2393
	}
2394
	if ( nv ) ns++ ;
2395
	if ( ns > 1 ) {
2396
	    ENC_SEQUENCE ( bs, ns - 1 ) ;
2397
	} else {
2398
	    if ( ns == 0 ) ENC_make_top ( bs ) ;
2399
	}
2400
 
2401
	/* Destroy members and direct bases */
2402
	while ( no ) {
2403
	    EXP a = DEREF_exp ( HEAD_list ( p ) ) ;
2404
	    if ( IS_NULL_exp ( a ) ) {
2405
		ENC_make_top ( bs ) ;
2406
	    } else {
2407
		TYPE s = DEREF_type ( exp_type ( a ) ) ;
2408
		OFFSET off = DEREF_off ( HEAD_list ( q ) ) ;
2409
		bs = enc_term_local ( bs, m, off, 0, s, a, context ) ;
2410
	    }
2411
	    q = TAIL_list ( q ) ;
2412
	    p = TAIL_list ( p ) ;
2413
	    no-- ;
2414
	}
2415
 
2416
	/* Conditionally destroy virtual bases */
2417
	if ( nv ) {
2418
	    int mask = 0 ;
2419
	    if ( context == 0 ) mask = EXTRA_DESTR ;
2420
	    bs = enc_flag_test ( bs, m2, nv, mask, ntest_not_eq ) ;
2421
	    while ( !IS_NULL_list ( p ) ) {
2422
		EXP a = DEREF_exp ( HEAD_list ( p ) ) ;
2423
		if ( IS_NULL_exp ( a ) ) {
2424
		    ENC_make_top ( bs ) ;
2425
		} else {
2426
		    TYPE s = DEREF_type ( exp_type ( a ) ) ;
2427
		    OFFSET off = DEREF_off ( HEAD_list ( q ) ) ;
2428
		    bs = enc_term_local ( bs, m, off, 0, s, a, context ) ;
2429
		}
2430
		q = TAIL_list ( q ) ;
2431
		p = TAIL_list ( p ) ;
2432
	    }
2433
	    ENC_make_top ( bs ) ;
2434
	}
2435
 
2436
	/* Conditionally call 'operator delete' */
2437
	if ( context == 0 ) {
2438
	    ns = 1 ;
2439
	    bs = enc_flag_test ( bs, m2, ns, EXTRA_DELETE, ntest_not_eq ) ;
2440
	    bs = enc_delete_obj ( bs, ct, m ) ;
2441
	    ENC_make_top ( bs ) ;
2442
	}
2443
 
2444
    } else {
2445
	/* Deal with constructors */
2446
	int virt = 1 ;
2447
	unsigned ns, nu ;
2448
	unsigned ni = 0 ;
2449
	unsigned nt = 0 ;
2450
	unsigned ne = 1 ;
2451
 
2452
	/* Allow for copy constructors */
2453
	if ( kind == DEFAULT_COPY || kind == DEFAULT_ASSIGN ) {
2454
	    ulong n1 = last_params [ DUMMY_second ] ;
2455
	    ulong m1 = unit_no ( bs, NULL_id, VAR_tag, 1 ) ;
2456
	    ENC_identify ( bs ) ;
2457
	    bs = enc_access ( bs, crt_func_access ) ;
2458
	    ENC_make_tag ( bs, m1 ) ;
2459
	    ENC_contents ( bs ) ;
2460
	    ENC_pointer ( bs ) ;
2461
	    bs = enc_al_ctype ( bs, ct ) ;
2462
	    ENC_obtain_tag ( bs ) ;
2463
	    ENC_make_tag ( bs, n1 ) ;
2464
	    last_params [ DUMMY_copy ] = m1 ;
2465
	}
2466
 
2467
	/* Count number of items */
2468
	if ( kind != DEFAULT_ASSIGN ) {
2469
	    VIRTUAL vt = DEREF_virt ( ctype_virt ( ct ) ) ;
2470
	    if ( kind != DEFAULT_PRELUDE ) {
2471
		LIST ( GRAPH ) bv = DEREF_list ( ctype_vbase ( ct ) ) ;
2472
		while ( !IS_NULL_list ( bv ) ) {
2473
		    /* Virtual base pointers */
2474
		    GRAPH gr = DEREF_graph ( HEAD_list ( bv ) ) ;
2475
		    while ( !IS_NULL_graph ( gr ) ) {
2476
			ni++ ;
2477
			gr = DEREF_graph ( graph_equal ( gr ) ) ;
2478
		    }
2479
		    bv = TAIL_list ( bv ) ;
2480
		}
2481
	    }
2482
	    if ( !IS_NULL_virt ( vt ) ) {
2483
		/* Virtual function tables */
2484
		IDENTIFIER cid = DEREF_id ( ctype_name ( ct ) ) ;
2485
		compile_virtual ( ct, !has_linkage ( cid ) ) ;
2486
		while ( !IS_NULL_virt ( vt ) ) {
2487
		    nt++ ;
2488
		    vt = DEREF_virt ( virt_next ( vt ) ) ;
2489
		}
2490
	    }
2491
	    virt = 0 ;
2492
	}
2493
	if ( last_params [ DUMMY_count ] != LINK_NONE ) ne = 2 ;
2494
	ns = ne * no + nt ;
2495
	nu = ne * nv + ni ;
2496
	if ( nu ) ns++ ;
2497
	if ( ns > 1 ) {
2498
	    ENC_SEQUENCE ( bs, ns - 1 ) ;
2499
	} else {
2500
	    if ( ns == 0 ) ENC_make_top ( bs ) ;
2501
	}
2502
 
2503
	/* Conditionally initialise virtual bases */
2504
	if ( nu ) {
2505
	    int dv = 0 ;
2506
	    ulong m2 = last_params [ DUMMY_extra ] ;
2507
	    bs = enc_flag_test ( bs, m2, nu, 0, ntest_not_eq ) ;
2508
	    if ( ni ) {
2509
		/* Initialise virtual base pointers */
2510
		bs = enc_virt_init ( bs, ct, m ) ;
2511
	    }
2512
	    while ( nv ) {
2513
		/* Virtual base initialisers */
2514
		EXP a = DEREF_exp ( HEAD_list ( p ) ) ;
2515
		OFFSET off = DEREF_off ( HEAD_list ( q ) ) ;
2516
		bs = enc_ctor_exp ( bs, a, off, m, virt, ne ) ;
2517
		if ( !IS_NULL_exp ( a ) && IS_exp_paren ( a ) ) dv++ ;
2518
		q = TAIL_list ( q ) ;
2519
		p = TAIL_list ( p ) ;
2520
		nv-- ;
2521
	    }
2522
	    if ( ne == 1 || dv == 0 ) {
2523
		ENC_make_top ( bs ) ;
2524
	    } else {
2525
		bs = enc_destr_count ( bs, NULL_type, dv ) ;
2526
	    }
2527
	}
2528
 
2529
	/* Initialise direct bases */
2530
	while ( nb ) {
2531
	    EXP a = DEREF_exp ( HEAD_list ( p ) ) ;
2532
	    OFFSET off = DEREF_off ( HEAD_list ( q ) ) ;
2533
	    bs = enc_ctor_exp ( bs, a, off, m, virt, ne ) ;
2534
	    q = TAIL_list ( q ) ;
2535
	    p = TAIL_list ( p ) ;
2536
	    nb-- ;
2537
	}
2538
 
2539
	/* Initialise virtual function tables */
2540
	if ( nt ) bs = enc_vtab_init ( bs, ct, m, 1 ) ;
2541
 
2542
	/* Initialise members */
2543
	while ( !IS_NULL_list ( p ) ) {
2544
	    EXP a = DEREF_exp ( HEAD_list ( p ) ) ;
2545
	    OFFSET off = DEREF_off ( HEAD_list ( q ) ) ;
2546
	    bs = enc_ctor_exp ( bs, a, off, m, virt, ne ) ;
2547
	    q = TAIL_list ( q ) ;
2548
	    p = TAIL_list ( p ) ;
2549
	}
2550
	last_params [ DUMMY_copy ] = LINK_NONE ;
2551
    }
2552
    return ( bs ) ;
2553
}
2554
 
2555
 
2556
#endif /* LANGUAGE_CPP */
2557
#endif /* TDF_OUTPUT */