Subversion Repositories tendra.SVN

Rev

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

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