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
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
/**********************************************************************
32
$Author: pwe $
33
$Date: 1998/03/11 11:03:24 $
34
$Revision: 1.3 $
35
$Log: exp.c,v $
36
 * Revision 1.3  1998/03/11  11:03:24  pwe
37
 * DWARF optimisation info
38
 *
39
 * Revision 1.2  1998/02/18  11:22:10  pwe
40
 * test corrections
41
 *
42
 * Revision 1.1.1.1  1998/01/17  15:55:46  release
43
 * First version to be checked into rolling release.
44
 *
45
 * Revision 1.7  1998/01/09  09:28:45  pwe
46
 * prep restructure
47
 *
48
 * Revision 1.6  1997/10/23  09:24:10  pwe
49
 * extra diags
50
 *
51
 * Revision 1.5  1997/02/18  12:56:23  currie
52
 * NEW DIAG STRUCTURE
53
 *
54
 * Revision 1.4  1996/07/23  12:28:37  currie
55
 * copying env_offsets
56
 *
57
Revision 1.3  1996/04/19 10:42:28  currie
58
Globals flags in copy
59
 
60
 * Revision 1.2  1995/10/11  17:10:00  currie
61
 * avs errors
62
 *
63
 * Revision 1.1  1995/04/06  10:44:05  currie
64
 * Initial revision
65
 *
66
 * Revision 1.1  1995/04/06  10:44:05  currie
67
 * Initial revision
68
 *
69
***********************************************************************/
70
 
71
 
72
 
73
 
74
#include "config.h"
75
#include "common_types.h"
76
#include "externs.h"
77
#include "xalloc.h"
78
#include "installglob.h"
79
#include "expmacs.h"
80
#include "tags.h"
81
#include "table_fns.h"
82
#include "shapemacs.h"
83
#include "check.h"
84
#include "flpt.h"
85
#include "basicread.h"
86
#include "messages_c.h"
87
#include "install_fns.h"
88
#include "flags.h"
89
#ifdef NEWDIAGS
90
#include "readglob.h"
91
#include "dg_aux.h"
92
#endif
93
#include "exp.h"
94
 
95
/* VARIABLES */
96
/* All variables initialised */
97
 
98
int crt_labno = 0;	/* init by init_exp */
99
  /* the list of unused returned cells */
100
exp freelist;	/* init by init_exp */
101
  /* the number of unused cells in the block */
102
int exps_left;	/* init by init_exp */
103
 
104
  /* the next free pointer in the block which is used if the freelist
105
     is empty */
106
static exp next_exp_ptr;	/* no need to init */
107
 
108
 
109
  /* the types used to record a list of blocks for reuse, if
110
     separate_units is set */
111
struct expalloc_cell_t {struct expalloc_cell_t * tl; exp hd;};
112
typedef struct expalloc_cell_t expalloc_cell;
113
 
114
static expalloc_cell * alloc_list = (expalloc_cell *)0;
115
		/* good init for the whole run */
116
static expalloc_cell * alloc_freelist = (expalloc_cell *)0;
117
		/* good init for the whole run */
118
 
119
 
120
static char  ic_buff[21];	/* no init needed */
121
 
122
/* IDENTITY */
123
 
124
static int current_alloc_size = 20000;
125
 
126
/* PROCEDURES */
127
 
128
void altered PROTO_S ( ( exp, exp ) ) ;
129
 
130
exp next_exp
131
    PROTO_Z ()
132
{
133
  exp res;
134
  if (freelist != nilexp)
135
    {  /* first try to allocate fron the freelist */
136
      res = freelist;
137
      freelist = son(freelist);
138
      return res;
139
    };
140
 
141
    /* if the freelist is empty we allocate from a block of exps */
142
  if (exps_left == 0)
143
   {  /* if the block is empty we must allocate another */
144
     if (alloc_freelist)
145
       {  /* if there is anything in this list of blocks we can reuse
146
             it and we do not need to calloc */
147
         exps_left = current_alloc_size;
148
         next_exp_ptr = alloc_freelist -> hd;
149
         alloc_freelist = alloc_freelist -> tl;
150
       }
151
     else
152
       {  /* otherwise we must calloc a new block */
153
         exps_left = current_alloc_size;
154
         next_exp_ptr = (exp)xcalloc(exps_left, sizeof(struct exp_t));
155
          { /* and if we are after the start of tagdefs we put
156
               the block on to alloc_list so that it can be reused
157
               for the next unit */
158
            expalloc_cell * temp =
159
               (expalloc_cell *)xmalloc(sizeof(expalloc_cell));
160
            temp -> tl = alloc_list;
161
            temp -> hd = next_exp_ptr;
162
            alloc_list = temp;
163
          };
164
       };
165
   };
166
 
167
  --exps_left;
168
  res = next_exp_ptr++;
169
  return res;
170
}
171
 
172
void set_large_alloc
173
    PROTO_Z ()
174
{
175
  /* called at the start of tagdefs */
176
  alloc_freelist = alloc_list;
177
  freelist = nilexp;
178
  exps_left = 0;
179
  return;
180
}
181
 
182
   /* create a new exp */
183
exp getexp
184
    PROTO_N ( (s, b, l, sn, px, pr, n, tg) )
185
    PROTO_T ( shape s X exp b X int l X exp sn X exp px X prop pr X int n X unsigned char tg )
186
{
187
  exp res = next_exp();
188
  sh(res) = s;
189
  bro(res) = b;
190
  if (l)
191
   setlast(res);
192
  else
193
   clearlast(res);
194
  son(res) = sn;
195
  pt(res) = px;
196
  props(res) = pr;
197
  no(res) = n;
198
  name(res) = tg;
199
  parked(res) = 0;
200
#ifdef NEWDIAGS
201
  dgf(res) = nildiag;
202
#endif
203
  return res;
204
}
205
 
206
exp copyexp
207
    PROTO_N ( (e) )
208
    PROTO_T ( exp e )
209
{
210
  exp res = next_exp();
211
  *res = *e;
212
  return res;
213
}
214
 
215
  /* makes a new shape */
216
exp getshape
217
    PROTO_N ( (l, sn, px, pr, n, tg) )
218
    PROTO_T ( int l X alignment sn X alignment px X alignment pr X int n X unsigned char tg )
219
{
220
  exp res = next_exp();
221
  if (l)
222
   setlast(res);
223
  else
224
   clearlast(res);
225
  res ->sonf.ald = sn;
226
  res -> ptf.ald = px;
227
  res -> brof.ald = pr;
228
  no(res) = n;
229
  name(res) = tg;
230
  return res;
231
}
232
 
233
  /* return an exp cell to the freelist */
234
void retcell
235
    PROTO_N ( (e) )
236
    PROTO_T ( exp e )
237
{
238
  son(e) = freelist;
239
  freelist = (e);
240
  return;
241
}
242
 
243
 
244
  /* true if part is inside whole */
245
int internal_to
246
    PROTO_N ( (whole, part) )
247
    PROTO_T ( exp whole X exp part )
248
{
249
  int f = 1;
250
  exp q = part;
251
  while (q != whole && q != nilexp &&
252
      !(name (q) == ident_tag && isglob (q))) {
253
    f = (int)(last (q));
254
    q = bro (q);
255
  };
256
  /* ascend from part until we reach either whole or top of tree */
257
  return (f && q == whole);
258
}
259
 
260
static void kill_el PROTO_S ((exp e, exp scope));
261
 
262
  /* kill an exp, return it and its components to the freelist,
263
     if necessary remove uses of tags and labels, and propagate
264
     changes to identity and variable declarations and to labels
265
     but not outside scope */
266
void kill_exp
267
    PROTO_N ( (e, scope) )
268
    PROTO_T ( exp e X exp scope )
269
{
270
  if (e != nilexp) {
271
    unsigned char n = name (e);
272
 
273
 
274
    if (n == name_tag) {
275
      exp q = son (e);
276
#ifdef NEWDIAGS
277
      if (!isdiaginfo(e))
278
	--no (son (e));		/* decrease usage count */
279
#else
280
      --no (son (e));		/* decrease usage count */
281
#endif
282
      while (pt (q) != e)
283
	q = pt (q);
284
      pt (q) = pt (e);		/* remove from usage list */
285
      if (
286
          no (son (e)) == 0 &&
287
	  son (son (e)) != nilexp &&
288
	  bro (son (son (e))) != nilexp &&
289
	  (scope == nilexp || internal_to (scope, son (e))))
290
	IGNORE check (son (e), scope);
291
      /* check the declaration if now no use */
292
      retcell (e);
293
      return;
294
    };
295
 
296
    if (n == solve_tag) {
297
      int looping;
298
      if (!last (son (e))) {
299
	exp t = bro (son (e));
300
	do {
301
	  no (son (t)) = 0;
302
	  looping = !last (t);
303
	  t = bro (t);
304
	}
305
	while (looping);
306
      };
307
      if (pt(e) != nilexp)
308
        son (pt (e)) = nilexp;
309
      kill_el (son (e), scope);
310
      retcell (e);
311
      return;
312
    };
313
 
314
    if (n == ident_tag) {
315
      ++no (e);
316
      kill_el (son (e), scope);
317
#ifdef NEWDIAGS
318
      if (diagnose && pt(e))	/* allow diags to hold on to id */
319
	diag_kill_id (e);
320
      else
321
#endif
322
      retcell (e);
323
      return;
324
    };
325
 
326
 
327
    if (n == labst_tag) {
328
      ++no (e);
329
      --proc_label_count;
330
      kill_el (bro (son (e)), scope);
331
      retcell (son (e));
332
      retcell (e);
333
      return;
334
    };
335
 
336
    if (n == case_tag) {
337
      exp b = bro(son(e));
338
      while (b != nilexp) {
339
	exp nextb = bro(b);
340
	int l = last(b);
341
	--no(son(pt(b)));
342
	if (son(b) != nilexp) retcell(son(b));
343
	retcell(b);
344
	if (l) break;
345
	b = nextb;
346
      }
347
      kill_exp (son (e), scope);
348
      retcell (e);
349
      return;
350
    };
351
 
352
    if (n == cond_tag) {
353
      no (son (bro (son (e)))) = 0;
354
      kill_el (son (e), scope);
355
      retcell (e);
356
      return;
357
    };
358
 
359
    if (n == rep_tag) {
360
      if (pt(e) != nilexp)
361
        son (pt (e)) = nilexp;
362
      no (son (bro (son (e)))) = 0;
363
      kill_el (son (e), scope);
364
      retcell (e);
365
      return;
366
    };
367
 
368
    if (n == real_tag || (n == val_tag && isbigval(e))) {
369
      flpt_ret (no (e));
370
      retcell (e);
371
      return;
372
    };
373
 
374
    if (n == val_tag) {
375
      retcell (e);
376
      return;
377
    };
378
 
379
    if (n == env_offset_tag || n == string_tag || n==general_env_offset_tag)
380
     {
381
      retcell (e);
382
      return;
383
     };
384
 
385
    {
386
      exp p = pt (e);
387
      if (p != nilexp && (props (son (p)) & 1) == 0) {
388
	/* decrease label usage count */
389
	--no (son (p));
390
	if (
391
            no (son (p)) == 0 && !is_loaded_lv(p) &&
392
	    bro (son (p)) != nilexp &&
393
	    (scope == nilexp || internal_to (scope, p)))
394
	  altered (p, scope);	/* process if now no use of label and not
395
				   doing deadvar */
396
      };
397
      kill_el (son (e), scope);
398
      retcell (e);
399
      return;
400
    };
401
  };
402
}
403
 
404
 
405
/* kill the arguments of a construction */
406
static void kill_el
407
    PROTO_N ( (e, scope) )
408
    PROTO_T ( exp e X exp scope )
409
{
410
  if (e != nilexp) {
411
    int l;
412
    exp next;
413
    do {
414
      l = (int)(last (e));
415
      next = bro (e);
416
      kill_exp (e, scope);
417
      e = next;
418
    }
419
    while (!l && e != nilexp);
420
  };
421
}
422
 
423
  /* return the shape delivered by a conditional (or similar construct)
424
     which delivers an a from one branch and a b from the other */
425
shape lub_shape
426
    PROTO_N ( (a, b) )
427
    PROTO_T ( shape a X shape b )
428
{
429
  int asz = shape_size(a);
430
  int bsz = shape_size(b);
431
  if (name(a) ==bothd)
432
   return b;
433
  if (name(b) == bothd)
434
   return a;
435
  if (asz == bsz && shape_align(a) == shape_align(b))
436
    return (a);
437
  return (f_top);
438
}
439
 
440
  /* true if the shapes are equal */
441
int eq_shape
442
    PROTO_N ( (a, b) )
443
    PROTO_T ( shape a X shape b )
444
{
445
  if (name(a) != name(b))
446
     return 0;
447
  if (shape_size(a)!=shape_size(b) ||
448
           is_signed(a)!=is_signed(b) ||
449
           shape_align(a)!=shape_align(b) ||
450
           al1(a)!=al1(b))
451
     return 0;
452
  if (name(a) == nofhd)
453
     return 1;
454
  else
455
     return (al2(a)==al2(b));
456
}
457
 
458
  /* source of numbers for local labels */
459
int next_lab
460
    PROTO_Z ()
461
{
462
  return crt_labno++;
463
}
464
 
465
char *intchars
466
    PROTO_N ( (n) )
467
    PROTO_T ( int n )
468
{
469
  int  r, d;
470
  char *ind;
471
 
472
  ind = &ic_buff[19];
473
  ic_buff[20] = 0;
474
  d = (n < 0) ? -n : n;
475
 
476
  do {
477
    r = d % 10;
478
    d = d / 10;
479
    *ind = (char)(r + 48); /* CAST:jmf: must be in 48:57 */
480
    --ind;
481
  }
482
  while (d != 0);
483
  if (n < 0) {
484
    *ind = '-';
485
    --ind;
486
  };
487
 
488
  return (ind + 1);
489
}
490
 
491
 
492
void case_item
493
    PROTO_N ( (i) )
494
    PROTO_T ( exp i )
495
{
496
  exp l = global_case;
497
  exp t = l;
498
  int go = 1;
499
  exp  newhigh = (son (i) == nilexp) ? i : son (i);
500
  exp  thigh;
501
  exp  nlow,
502
        nhigh;
503
 
504
  while (go && bro (t) != nilexp) {
505
    exp j = bro (t);
506
    exp  highj = (son (j) == nilexp) ? j : son (j);
507
    if (docmp_f((int)f_greater_than, i, highj))
508
      t = bro (t);
509
    else
510
      go = 0;
511
  };
512
 
513
  if (t != l) {
514
    thigh = (son (t) == nilexp) ? t : son (t);
515
  }
516
  else {
517
    SET(thigh);
518
  };
519
 
520
  if (bro (t) != nilexp) {
521
    nlow = bro (t);
522
    nhigh = (son (bro (t)) == nilexp) ? nlow : son (bro (t));
523
  }
524
  else {
525
    SET(nlow); SET(nhigh);
526
  };
527
 
528
  if (t != l && docmp_f((int)f_less_than_or_equal, i, thigh))
529
    failer (CASE_OVERLAP);
530
  if (bro (t) != nilexp &&
531
	 docmp_f((int)f_greater_than_or_equal, newhigh, nlow))
532
    failer (CASE_OVERLAP);
533
 
534
  if (isbigval(i) || isbigval(newhigh)) {
535
    bro (i) = bro (t);
536
    bro (t) = i;
537
    return;
538
  };
539
 
540
  if (t != l && (no(i)-1) == no(thigh) && pt (i) == pt (t)) {
541
    if (bro (t) != nilexp && (no(newhigh)+1) == no(nlow)
542
	&& pt (i) == pt (bro (t))) {
543
      if (son (bro (t)) != nilexp) {
544
	if (son (t) != nilexp)
545
	  retcell (son (t));
546
	son (t) = son (bro (t));
547
	bro (t) = bro (bro (t));
548
	return;
549
      };
550
      if (son (t) != nilexp) {
551
	no (son (t)) = no(nhigh);
552
	bro (t) = bro (bro (t));
553
	return;
554
      };
555
      setson (t, getexp (slongsh, nilexp, 1, nilexp, nilexp, 0,
556
			  no(nhigh), 0));
557
      bro (t) = bro (bro (t));
558
      return;
559
    };
560
    if (son (t) != nilexp) {
561
      no (son (t)) = no(newhigh);
562
      return;
563
    };
564
    setson (t, getexp (slongsh, nilexp, 1, nilexp,
565
			 nilexp, 0, no(newhigh), 0));
566
    return;
567
  };
568
 
569
  if (bro (t) != nilexp && (no(newhigh) + 1) == no(nlow)
570
      && pt (i) == pt (bro (t))) {
571
    if (son (bro (t)) != nilexp) {
572
      no (bro (t)) = no(i);
573
      return;
574
    };
575
    if (son (i) != nilexp) {
576
      no (son (i)) = no(nhigh);
577
      bro (i) = bro (bro (t));
578
      bro (t) = i;
579
      return;
580
    };
581
    son (i) = bro (t);
582
    bro (i) = bro (bro (t));
583
    bro (t) = i;
584
    return;
585
  };
586
 
587
  bro (i) = bro (t);
588
  bro (t) = i;
589
  return;
590
}
591
 
592
 
593
/*******************************************************************
594
  scan_solve is part of the process of reading a solve construction.
595
  It scans the exp e, to increment the count of labels used by e.
596
 *******************************************************************/
597
void scan_solve
598
    PROTO_N ( (e) )
599
    PROTO_T ( exp e )
600
{
601
  unsigned char  n = name (e);
602
  switch (n) {
603
    case name_tag:
604
    case make_lv_tag:
605
    case env_offset_tag:
606
    case general_env_offset_tag:
607
      return;
608
    case clear_tag:
609
      return;
610
    case ident_tag: {
611
	scan_solve (son (e));
612
	scan_solve (bro (son (e)));
613
	return;
614
      };
615
    case case_tag:
616
      {
617
	exp t = son (e);
618
	while (!last (t)) {
619
	  exp s = son (pt (bro (t)));
620
	  if (isvar (s)) {
621
	    ++no (s);
622
	  };
623
	  t = bro (t);
624
	};
625
	scan_solve (son (e));
626
	return;
627
      };
628
    default:
629
      {
630
	if (pt (e) != nilexp) {
631
	  exp s = son (pt (e));
632
	  if (isvar (s)) {
633
	    ++no (s);
634
	  };
635
	};
636
	if (son (e) != nilexp) {
637
	  exp t = son (e);
638
	  while (scan_solve (t), !last (t))
639
	    t = bro (t);
640
	};
641
	return;
642
      };
643
  };
644
}
645
/*********************************************************************
646
  clean_labelled processes a labelled statement after it has been read.
647
  It places the labelled statements in a good order.
648
 *********************************************************************/
649
 
650
exp clean_labelled
651
    PROTO_N ( (main, placelabs) )
652
    PROTO_T ( exp main X label_list placelabs )
653
{
654
  int   i,
655
        crt_no;
656
  int go = 1;
657
  shape s;
658
  exp r, q;
659
  int n = placelabs.number;
660
  int  *ord;			/* records the order in which the
661
				   statemnts are to be placed */
662
  int   ord_no;
663
  for (i = 0; i < n; ++i) {	/* set up the labels */
664
    exp l = get_lab(placelabs.elems[i]);
665
    exp t = son (l);
666
    no (t) = is_loaded_lv(l);
667
    setcrtsolve (t);		/* defined in expmacs = props(t) = 1 */
668
  };
669
  crt_no = 0;
670
  ord = (int *) xcalloc (n, sizeof (int));
671
  ord_no = 0;
672
  scan_solve (main);		/* mark the labels used by the initiator
673
				*/
674
  while (go) {			/* continue as long as we have added a
675
				   statement */
676
    go = 0;
677
    for (i = 0; i < n; ++i) {	/* look for unprocessed but used sts */
678
      int   j = ((i + crt_no) % n);
679
      exp t = get_lab(placelabs.elems[j]);
680
      if ((props (son (t)) & 8) == 0 && no (son (t)) != 0) {
681
	/* we have found an unprocessed but used statement */
682
	go = 1;
683
	props (son (t)) = 5;
684
	scan_solve (t);		/* now scan it to mark the things it uses
685
				*/
686
	props (son (t)) = (prop)((props (son (t)) & 0xfb) | 8);
687
	ord[ord_no++] = j;
688
      };
689
    };
690
  };
691
  s = sh (main);
692
  for (i = 0; i < n; ++i) {
693
    exp lab = get_lab(placelabs.elems[i]);
694
    exp t = son (lab);
695
    if ((props (t) & 8) != 8) {
696
      kill_exp (bro (t), bro (t));/* remove unwanted statements */
697
 
698
    }
699
    else
700
      s = lub_shape (s, sh (lab));
701
    /* form the result shape of the whole */
702
  };
703
  r = getexp (s, nilexp, 0, main, crt_repeat, 0, 0, solve_tag);
704
  q = main;
705
  for (i = 0; i < ord_no; ++i) {/* set up the solve with the statements in
706
				   the order specified by ord */
707
    clearlast (q);
708
    bro (q) = get_lab(placelabs.elems[ord[i]]);
709
    q = bro (q);
710
    props (son (q)) = (prop)(props(son(q)) & 0xfe);
711
  };
712
  son (crt_repeat) = r;
713
  crt_repeat = bro(crt_repeat);
714
  setfather(r, q);
715
  return (r);
716
}
717
 
718
/* find the (unique) downward reference to e */
719
exp * refto
720
    PROTO_N ( (f, e) )
721
    PROTO_T ( exp f X exp e )
722
{
723
  exp * x = &son (f);
724
  while (*x != e)
725
    x = &bro (*x);
726
  return (x);
727
}
728
 
729
/* find the father of u */
730
exp father
731
    PROTO_N ( (e) )
732
    PROTO_T ( exp e )
733
{
734
  if (e == nilexp)
735
    return (e);
736
  while (!last (e))
737
    e = bro (e);
738
  return (bro (e));
739
}
740
 
741
/* auxiliary routine for altered, looks up
742
   in the tree n levels, checking */
743
static void altaux
744
    PROTO_N ( (e, n, scope) )
745
    PROTO_T ( exp e X int n X exp scope )
746
{
747
  exp f;
748
  if (bro (e) == nilexp || e == scope ||
749
      (name (e) == ident_tag && isglob (e)))
750
    return;			/* ignore if top of tree */
751
  f = father (e);
752
  if (f == nilexp || bro (f) == nilexp ||
753
      (name (f) == ident_tag && isglob (f)))
754
    return;			/* ignore if top of tree */
755
  if (name (f) == 0) {
756
    altaux (f, n, scope);
757
    return;
758
  };
759
  if (!check (f, scope) && n > 1) {
760
    /* do check until n is exhausted */
761
    altaux (f, n - 1, scope);
762
    return;
763
  };
764
}
765
 
766
/* e has been altered. see if any exp
767
   higher up the tree can now recognise an
768
   optimisation (using check) */
769
void altered
770
    PROTO_N ( (e, scope) )
771
    PROTO_T ( exp e X exp scope )
772
{
773
  altaux (e, 1, scope);
774
}
775
 
776
/* replace old by e, and (if not doing
777
   deadvar) check whether any
778
   consequential optimisations are
779
   possible */
780
void replace
781
    PROTO_N ( (old, e, scope) )
782
    PROTO_T ( exp old X exp e X exp scope )
783
{
784
  exp f = father (old);
785
  exp * ref = refto (f, old);
786
  if (last (*ref))
787
    setlast (e);
788
  else
789
    clearlast (e);
790
  bro (e) = bro (*ref);
791
  *ref = e;
792
  if (scope == old)
793
    return;
794
  altered (e, scope);
795
}
796
 
797
/* copy a labelled statement and put links
798
   into pt so that copies of uses of the
799
   original can refer to the copy */
800
void copy_labst
801
    PROTO_N ( (e) )
802
    PROTO_T ( exp e )
803
{
804
  exp t = copyexp (e);
805
  exp d = copyexp (son (e));
806
  setcopy(e);
807
  no (t) = 0;
808
  no (d) = 0;
809
  pt (d) = pt (e);
810
  pt (t) = nilexp;
811
  pt (e) = t;
812
  son (t) = d;
813
  ++proc_label_count;
814
}
815
 
816
/* end the copy of a labelled statement
817
   and restore the original state */
818
exp undo_labst
819
    PROTO_N ( (e) )
820
    PROTO_T ( exp e )
821
{
822
  exp r = pt (e);
823
  pt (e) = pt (son (r));
824
  clearcopy(e);
825
  return (r);
826
}
827
 
828
exp copy_res PROTO_S ( ( exp, exp, exp ) ) ;
829
exp copy PROTO_S ( ( exp ) ) ;
830
 
831
/* used to copy cond, repeat and solve so
832
   that copies of references to the
833
   labelled statements can refer to the
834
   copies of the labelled statements */
835
static exp copy_cpd
836
    PROTO_N ( (e, new_record, var, lab) )
837
    PROTO_T ( exp e X exp new_record X exp var X exp lab )
838
{
839
  exp t = copyexp (e);
840
  exp q;
841
  exp j, c, s, n, k;
842
 
843
  if (new_record != nilexp) {	/* record the construction */
844
    pt (t) = new_record;
845
    son (new_record) = t;
846
  };
847
 
848
  /* copy the labelled statements */
849
  q = bro (son (e));
850
  copy_labst (q);
851
  while (!last (q)) {
852
    q = bro (q);
853
    copy_labst (q);
854
  }
855
 
856
  /* copy the bodies of the labelled statments */
857
  q = bro (son (e));
858
  while (j = copy_res (bro (son (q)), var, lab),
859
      c = pt (q),
860
      bro (son (c)) = j,
861
      bro (j) = c,
862
      setlast (j),
863
      !last (q))
864
    q = bro (q);
865
 
866
  /* copy the lead statement */
867
  s = copy_res (son (e), var, lab);
868
  son (t) = s;
869
  clearlast (s);
870
  q = bro (son (e));
871
  n = s;
872
 
873
  /* restore the labelled statements */
874
  while (k = undo_labst (q),
875
      bro (n) = k,
876
      clearlast (n),
877
      !last (q)) {
878
    q = bro (q);
879
    n = bro (n);
880
  };
881
 
882
  n = bro (n);
883
  setlast (n);
884
  bro (n) = t;
885
  return (t);
886
}
887
 
888
/******************************************************************
889
  copy copies e and all its sub-cells recursively, amending usage
890
  counts as necessary. It sets up identifier usage lists for the
891
  declarations which it copies.
892
 ******************************************************************/
893
 
894
exp copy_res
895
    PROTO_N ( (e, var, lab) )
896
    PROTO_T ( exp e X exp var X exp lab )
897
{
898
  if (e == nilexp)
899
    return (e);
900
#ifdef NEWDIAGS
901
  else
902
  if (dgf(e) != nildiag)
903
    return copy_res_diag (e, dgf(e), var, lab);
904
#endif
905
  else {
906
    unsigned char n = name (e);
907
 
908
    if (n == ident_tag) {
909
      exp t = copyexp (e);
910
      exp x = pt (e);		/* remember the usage list */
911
      exp s, bs;
912
      setcopy (e);		/* mark e as being copied */
913
      no (t) = 0;		/* clear the usage count */
914
      pt (e) = t;		/* record the copy in the pt field of the
915
				   original */
916
      pt (t) = nilexp;		/* set the new usage list to empty */
917
      s = copy_res (son (e), var, lab);	/* copy the definition */
918
      bs = copy_res (bro (son (e)), var, lab);/* copy the body */
919
      son (t) = s;
920
      bro (s) = bs;
921
      bro (bs) = t;
922
      clearlast (s);
923
      setlast (bs);
924
      pt (e) = x;		/* reset the remembered usage list */
925
      clearcopy (e);		/* remove the copying flag */
926
      if (n == ident_tag)
927
	sh (t) = sh (bro (son (t)));/* in case bro(son(t)) is a tuple */
928
      return (t);
929
    };
930
 
931
    if (n == name_tag) {
932
      /* see if the corresponding declaration is being copied and pick up
933
         the correct usage list */
934
      exp tp = (copying (son (e)) ? pt (son (e)) : son (e));
935
      exp r = copyexp (e);
936
      son (r) = tp;		/* add this use onto the correct usage
937
				   list */
938
      pt (r) = pt (tp);
939
      pt (tp) = r;
940
#ifdef NEWDIAGS
941
      if (!isdiaginfo(r))
942
#endif
943
      {
944
	++no (tp);		/* increment the correct usage count */
945
	if (isglob(tp)) proc_externs = 1;
946
      }
947
      return (r);
948
    };
949
 
950
    if (n == env_offset_tag || n == general_env_offset_tag) {
951
      /* see if the corresponding declaration is being copied and pick up
952
         the correct usage list */
953
      exp tp = (copying (son (e)) ? pt (son (e)) : son (e));
954
      exp r = copyexp (e);
955
      son (r) = tp;		/* add this use onto the correct usage
956
				   list */
957
      return (r);
958
    };
959
 
960
    if (n == cond_tag) {
961
      exp z = copy_cpd (e, nilexp, var, lab);
962
      return (z);
963
    };
964
 
965
    if (n == rep_tag || n == solve_tag) {
966
      /* we have to update the repeat records */
967
      exp record = pt (e);
968
      exp z;
969
      if (record != nilexp) {
970
        exp senior = bro (record);
971
        exp new_record = copyexp (record);
972
	if (senior == nilexp) { /* XX008 */
973
	  senior = crt_repeat;
974
	  bro(new_record) = senior;
975
	};
976
        set_copying_solve (record);/* mark as being copied */
977
        pt (record) = new_record;
978
 
979
        if (senior != nilexp) {	/* update repeat records */
980
	  if ((props (senior) & 1) == 1)
981
	    bro (new_record) = pt (senior);
982
	  else
983
	    ++no (senior);
984
        };
985
        z = copy_cpd (e, new_record, var, lab);
986
        clear_copying_solve(record);	/* unmark copying flag */
987
      }
988
      else {
989
	z = copy_cpd (e, nilexp, var, lab);
990
      };
991
      return (z);
992
    };
993
 
994
    if (n == case_tag) {
995
      exp t = copy_res (son (e), var, lab);
996
      exp z = copyexp (e);
997
      exp q = son (e);
998
      exp p = t;
999
      exp labloc, tp;
1000
      son (z) = t;
1001
      while (!last (q)) {
1002
	setbro (p, copyexp (bro (q)));
1003
	if (son (bro (q)) != nilexp)
1004
	  setson (bro (p), copyexp (son (bro (q))));
1005
	labloc = pt (bro (p));
1006
	tp = (copying(labloc)) ? pt (labloc) : labloc;
1007
	pt (bro (p)) = tp;
1008
	no (son (tp))++;
1009
	p = bro (p);
1010
	q = bro (q);
1011
      };
1012
      bro (p) = z;
1013
      if (PIC_code) proc_externs = 1;
1014
      return (z);
1015
    };
1016
 
1017
    if (n == real_tag || (n == val_tag && isbigval(e))) {
1018
      exp z = copyexp (e);
1019
      flpt f = new_flpt ();
1020
      flt_copy (flptnos[no (e)], &flptnos[f]);
1021
      no (z) = f;
1022
      if (PIC_code) proc_externs =1;
1023
      return (z);
1024
    };
1025
 
1026
   if (n == string_tag)
1027
    {
1028
      exp r = copyexp(e);
1029
      if (PIC_code) proc_externs =1;
1030
      return (r);
1031
    };
1032
 
1033
    if (n == res_tag) {
1034
      if (lab != nilexp) {
1035
	exp go = getexp(f_bottom, nilexp, 0, nilexp, lab,
1036
			 0, 0, goto_tag);
1037
	no(son(lab))++;
1038
 
1039
	if (name(son(e)) == clear_tag) {
1040
#ifdef NEWDIAGS
1041
	  if (extra_diags)
1042
	    diag_inline_result (go);
1043
#endif
1044
	  return go;
1045
	}
1046
        else
1047
        if (var == nilexp) {
1048
	  exp_list el;
1049
          exp c = copy(son(e));
1050
	  exp s;
1051
	  el.start = c;
1052
	  el.end = c;
1053
	  el.number = 1;
1054
	  s = f_sequence(el, go);
1055
#ifdef NEWDIAGS
1056
	  if (extra_diags)
1057
	    diag_inline_result (go);
1058
	  return diag_hold_check (s);	/* not inlining */
1059
#else
1060
          return hold_check(s);
1061
#endif
1062
	}
1063
	else {
1064
	  exp ass;
1065
	  exp_list el;
1066
	  exp old_var;
1067
	  exp ident;
1068
 
1069
	  old_var = copyexp(var);	/* careful - we must not use
1070
					   copy on var because it belongs
1071
					   in the other context recurse!
1072
					*/
1073
	  ident = (copying(son(var))) ? pt(son(var)) : son(var);
1074
	  pt(old_var) = pt(ident);
1075
	  pt(ident) = old_var;
1076
	  ++no(ident);
1077
	  ass = f_assign(old_var, copy(son(e)));
1078
	  el.start = ass;
1079
	  el.end = ass;
1080
	  el.number = 1;
1081
#if NEWDIAGS
1082
	  if (extra_diags)
1083
	    diag_inline_result (bro(son(ass)));
1084
#endif
1085
	  return f_sequence(el, go);
1086
	};
1087
      };
1088
 
1089
       /* FALL THROUGH if lab == nilexp */
1090
     };
1091
    {
1092
      exp p = pt (e);
1093
      exp z = copyexp (e);
1094
      exp tp;
1095
      switch (name(e)) {
1096
	case alloca_tag: case apply_general_tag: has_alloca = 1; break;
1097
	case tail_call_tag: has_alloca = 1; has_setjmp = 1; break;
1098
	case current_env_tag: uses_crt_env = 1; uses_loc_address = 1;
1099
		if (in_proc_def) sh(z) = f_pointer(frame_alignment);
1100
		break;
1101
        case untidy_return_tag: case local_free_all_tag: case long_jump_tag:
1102
			has_setjmp = 1; break;
1103
      }
1104
 
1105
      if (p != nilexp) {
1106
	/* the pt field must be a label */
1107
	/* look to see if label is being copied and pick up right
1108
	   statement */
1109
	tp = (copying(p)) ? pt (p) : p;
1110
	pt (z) = tp;
1111
	no (son (tp))++;	/* update label use count */
1112
      };
1113
 
1114
      if (son (e) == nilexp) {
1115
	return (z);
1116
      };
1117
      {
1118
	exp t = son (e);
1119
	exp q = copy_res (t, var, lab);
1120
	exp ptt = q;
1121
	while (!last (t)) {	/* copy the arguments */
1122
	  setbro (ptt, copy_res (bro (t), var, lab));
1123
	  clearlast (ptt);
1124
	  t = bro (t);
1125
	  ptt = bro (ptt);
1126
	};
1127
	son (z) = q;
1128
	bro (ptt) = z;
1129
	setlast (ptt);
1130
 
1131
	if (n == labst_tag || n == seq_tag)
1132
	  sh (z) = sh (bro (son (z)));
1133
	/* in case bro(son(z)) is a tuple */
1134
 
1135
	return (z);
1136
      };
1137
    };
1138
  }
1139
}
1140
 
1141
exp copy
1142
    PROTO_N ( (e) )
1143
    PROTO_T ( exp e )
1144
{
1145
  return copy_res(e, nilexp, nilexp);
1146
}
1147
 
1148
int is_comm
1149
    PROTO_N ( ( e ) )
1150
    PROTO_T ( exp e )
1151
{
1152
    if (no_bss)
1153
      return 0;
1154
    switch ( name ( e ) ) {
1155
 
1156
	case val_tag : return ( no ( e ) ? 0 : 1 ) ;
1157
 
1158
	case int_to_bitf_tag :
1159
	case chvar_tag : return ( is_comm ( son ( e ) ) ) ;
1160
 
1161
	case real_tag : {
1162
	    flpt f = no ( e ) ;
1163
	    return ( flptnos [f].sign ? 0 : 1 ) ;
1164
	}
1165
 
1166
	case compound_tag : {
1167
	    exp t = son ( e ) ;
1168
	    if ( t == nilexp ) return ( 1 ) ;
1169
	    while ( 1 ) {
1170
		t = bro ( t ) ;
1171
		if ( name ( sh ( t ) ) != bitfhd ) {
1172
		    if ( !is_comm ( t ) ) return ( 0 ) ;
1173
		} else {
1174
		    if ( name ( t ) == val_tag ) {
1175
			if ( no ( t ) ) return ( 0 ) ;
1176
		    } else {
1177
			if ( no ( son ( t ) ) ) return ( 0 ) ;
1178
		    }
1179
		}
1180
		if ( last ( t ) ) return ( 1 ) ;
1181
		t = bro ( t ) ;
1182
	    }
1183
	    /* Not reached */
1184
	}
1185
 
1186
	case ncopies_tag : return ( is_comm ( son ( e ) ) ) ;
1187
 
1188
	case nof_tag : {
1189
	    exp t = son ( e ) ;
1190
	    if ( t == nilexp ) return 1;
1191
	    while ( 1 ) {
1192
		if ( !is_comm ( t ) ) return ( 0 ) ;
1193
		if ( last ( t ) ) return ( 1 ) ;
1194
		t = bro ( t ) ;
1195
	    }
1196
	    /* Not reached */
1197
	}
1198
 
1199
	case concatnof_tag : {
1200
	    exp t = son ( e ) ;
1201
	    return ( is_comm ( t ) && is_comm ( bro ( t ) ) ) ;
1202
	}
1203
 
1204
	case clear_tag :
1205
	case res_tag :  return ( 1 ) ;
1206
 
1207
	case null_tag : return ( no(e) == 0 ) ;
1208
    }
1209
    return ( 0 ) ;
1210
}