Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
6 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
6 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
6 7u83 42
 
2 7u83 43
	(1) Its Recipients shall ensure that this Notice is
44
	reproduced upon any copies or amended versions of it;
6 7u83 45
 
2 7u83 46
	(2) Any amended version of it shall be clearly marked to
47
	show both the nature of and the organisation responsible
48
	for the relevant amendment or amendments;
6 7u83 49
 
2 7u83 50
	(3) Its onward transfer from a recipient to another
51
	party shall be deemed to be that party's acceptance of
52
	these conditions;
6 7u83 53
 
2 7u83 54
	(4) DERA gives no warranty or assurance as to its
55
	quality or suitability for any purpose and DERA accepts
56
	no liability whatsoever in relation to any use to which
57
	it may be put.
58
*/
59
 
60
 
61
/*
62
$Log: needscan.c,v $
63
 * Revision 1.1.1.1  1998/01/17  15:56:03  release
64
 * First version to be checked into rolling release.
65
 *
66
 * Revision 1.18  1996/11/29  10:38:05  wfs
67
 *    Change to "needscan.c" - compound parameters of size > 32 and < 64 were
68
 * not being properly aligned on the stack.
69
 *
70
 * Revision 1.17  1996/08/30  09:02:27  wfs
71
 * Various fixes of bugs arising from avs and pl_tdf tests.
72
 *
73
 * Revision 1.16  1996/08/06  10:50:11  wfs
74
 * bug fixes to pic code, enum diagnostics enabled.
75
 *
76
 * Revision 1.15  1996/04/18  11:09:15  wfs
77
 * Fixed a bug in "needscan.c" where "locptr_tag" was being wrapped around
78
 * the wrong exps.
79
 *
80
 * Revision 1.14  1996/03/28  10:53:14  wfs
81
 * Bug fixes to scan(), peephole optimisations in proc.c, and enum diagnostics.
82
 *
83
 * Revision 1.13  1996/03/22  13:34:12  wfs
84
 * Corrections to the dynamic initialization stuff in translat.c + bad
85
 * needscan.c code deleted.
86
 *
87
 * Revision 1.12  1996/03/14  16:18:44  wfs
88
 * tophed is not valregable + ptr position in apply_general case of scan() + superfluous "set -x" in bl_install script.
89
 *
90
 * Revision 1.11  1996/03/06  17:26:27  wfs
91
 * Fixed a bug in the profiling option.
92
 *
93
 * Revision 1.10  1996/03/04  18:15:10  wfs
94
 * Bug fix in scan(). diagnose=1 made all idents visible - but bitfields cannot
95
 * be visible.
96
 *
97
 * Revision 1.9  1996/03/04  13:19:09  wfs
98
 * Changes to hppatrans.1 manual + Mike Gerrard's needscan bug fix.
99
 *
100
 * Revision 1.8  1996/01/18  15:17:38  wfs
101
 * Left out a ";" in "needscan.c".
102
 *
103
 * Revision 1.7  1996/01/18  15:09:42  wfs
104
 * Corrected a syntax error in "needscan.c".
105
 *
106
 * Revision 1.6  1996/01/18  14:58:18  wfs
107
 * The "-default" option of "build" now sets BE_VERBOSE="true". Made a change
108
 * to the "apply_tag" case in scan() to ensure that space is reserved for
109
 * long double procedure call results even if they are not used.
110
 *
111
 * Revision 1.5  1996/01/11  14:46:31  wfs
112
 * Fixed bug in "ass_tag" case of scan(). Removed superfluous macro and comment.
113
 *
114
 * Revision 1.4  1996/01/10  17:18:53  wfs
115
 * Corrected definition of "IS_TREG" macro + cosmetic changes to needscan.c
116
 *
117
 * Revision 1.3  1996/01/08  12:01:58  wfs
118
 * Cosmetic changes to usage message in "hppatrans.c". "issparc" set to 0 in
119
 * "config.h". Change to "scan()" regarding the passing of 64 bit int params.
120
 *
121
 * Revision 1.2  1995/12/18  13:12:09  wfs
122
 * Put hppatrans uder cvs control. Major Changes made since last release
123
 * include:
124
 * (i) PIC code generation.
125
 * (ii) Profiling.
126
 * (iii) Dynamic Initialization.
127
 * (iv) Debugging of Exception Handling and Diagnostics.
128
 *
129
 * Revision 5.6  1995/10/23  15:47:23  wfs
130
 * Positioning of byte and halfwords on the stack was incomplete.
131
 *
132
 * Revision 5.5  1995/10/20  14:07:32  wfs
133
 * gcc compilation changes.
134
 *
135
 * Revision 5.4  1995/10/11  15:59:12  wfs
136
 * Cosmetic changes.
137
 *
138
 * Revision 5.3  1995/10/05  08:56:38  wfs
139
 * "isoutpar" check applied to parameters.
140
 *
141
 * Revision 5.2  1995/09/25  10:45:17  wfs
142
 * Two bug fixes.
143
 *
144
 * Revision 5.1  1995/09/15  13:01:15  wfs
145
 * Changes to "ident_tag" case. "trap_tag" case added.
146
 *
147
 * Revision 5.0  1995/08/25  13:42:58  wfs
148
 * Preperation for August 25 Glue release
149
 *
150
 * Revision 3.3  1995/08/25  10:14:21  wfs
151
 * A major revision. New 3.1 and 4.0 cases. "ident_tag" case rewritten
152
 * for the parameters. Register synonyms changed. MJG's bug fix
153
 * incorporated
154
 *
155
 * Revision 3.3  1995/08/25  10:14:21  wfs
156
 * A major revision. New 3.1 and 4.0 cases. "ident_tag" case rewritten
157
 * for the parameters. Register synonyms changed. MJG's bug fix
158
 * incorporated
159
 *
160
 * Revision 3.1  95/04/10  16:27:33  16:27:33  wfs (William Simmonds)
161
 * Apr95 tape version.
6 7u83 162
 *
2 7u83 163
 * Revision 3.0  95/03/30  11:18:27  11:18:27  wfs (William Simmonds)
164
 * Mar95 tape version with CRCR95_178 bug fix.
6 7u83 165
 *
2 7u83 166
 * Revision 2.0  95/03/15  15:28:17  15:28:17  wfs (William Simmonds)
167
 * spec 3.1 changes implemented, tests outstanding.
6 7u83 168
 *
2 7u83 169
 * Revision 1.2  95/01/17  17:29:49  17:29:49  wfs (William Simmonds)
6 7u83 170
 *
171
 *
2 7u83 172
 * Revision 1.1  95/01/11  13:13:54  13:13:54  wfs (William Simmonds)
173
 * Initial revision
6 7u83 174
 *
2 7u83 175
*/
176
 
177
 
178
#define HPPATRANS_CODE
179
/*******************************************************************
180
 
181
		needscan.c
182
 
183
	Defines the scan through a program which reorganises it so that all
184
arguments of operations are suitable for later code-production. The procedure
185
scan evaluates the register requirements of an exp. The exps are produced
186
from the decoding process and the various exp -> exp transformations  in
187
the proc independent (common to other  translators)
188
 
189
******************************************************************/
190
 
191
 
192
#include "config.h"
193
#include "myassert.h"
194
#include "exptypes.h"
195
#include "exp.h"
196
#include "expmacs.h"
197
#include "tags.h"
198
#include "new_tags.h"
199
#include "common_types.h"
200
#include "check.h"
201
#include "proctypes.h"
202
#include "bitsmacs.h"
203
#include "maxminmacs.h"
204
#include "regable.h"
205
#include "tempdecs.h"
206
#include "shapemacs.h"
207
#include "special.h"
208
#include "const.h"
209
#include "flpt.h"
210
#include "install_fns.h"
211
#include "externs.h"
212
#include "regmacs.h"
213
#include "muldvrem.h"
214
#include "translat.h"
215
#include "comment.h"
216
#include "flags.h"
217
#include "proc.h"
218
#include "frames.h"
219
#include "extratags.h"
220
#include "needscan.h"
221
 
222
 
223
/* used by scan to set initial parameter positions */
6 7u83 224
extern alignment long_to_al(unsigned long);
225
extern int specialopt(exp);
2 7u83 226
 
227
extern long notbranch[];	/* in makecode.c */
228
extern bool do_tlrecursion;
229
extern int nexps;
230
 
231
extern procrec *cpr;
232
 
233
static int stparam;		/* Size of parameter list in bits */
234
static int fixparam;		/* Next available place for param */
235
static int fltparam;
236
 
237
static bool rscope_level = 0;
238
static bool nonevis = 1;
239
static int callerfortr;
240
 
241
bool gen_call;
242
bool has_tail_call;
243
 
244
int maxfix, maxfloat;		/* the maximum number of t-regs */
245
 
246
 
247
/* advance declaration of scan */
6 7u83 248
needs scan(exp *, exp **);
2 7u83 249
 
250
 
251
/*
252
	needs defined in proctypes.h.
253
 
254
	This is a structure which has two integers giving the number of
255
fixed and floating point registers required to contain live values in
256
the expression parameters. A further field prop is used for various
257
flags about certain forms of exp (mainly idents and procs). The maxargs
258
field gives the maximum size in bits for the parameters of all the
259
procs called in the exp. The needs of a proc body are preserved in the
260
needs field of the procrec (see proctypes.h).
261
*/
262
 
263
 
264
 
265
/* return ptrexp pointing to e */
6 7u83 266
exp *ptr_position
267
(exp e)
2 7u83 268
{
269
  exp *res;
270
  exp dad = father(e);
271
  exp sib = son(dad);
272
 
273
  if (sib == e)
274
  {
275
    res = &son(dad);
276
  }
277
  else
278
  {
6 7u83 279
    while (bro(sib)!= e)
2 7u83 280
    {
281
      sib = bro(sib);
282
    }
283
    res = &bro(sib);
284
  }
285
 
286
  return res;
287
}
288
 
289
 
290
 
291
/***************************************************************
292
		cca
293
 
294
This procedure effectively inserts a new declaration into an exp. This
295
is used to stop a procedure requiring more than the available number of
296
registers.
297
****************************************************************/
6 7u83 298
void tidy_ident(exp);
2 7u83 299
 
300
 
301
void cca
6 7u83 302
(exp **to, exp *x)
2 7u83 303
{
6 7u83 304
  if (name((**to)) ==diagnose_tag)
2 7u83 305
  {
6 7u83 306
      *to = & (son((**to)));
2 7u83 307
  }
308
  if (x == (*to))
309
  {
310
    exp def = *(x);
311
 
312
    /* replace by  Let tg = def In tg Ni */
313
    exp id = getexp(sh(def), bro(def), last(def), def, nilexp,
314
		    0, 1, ident_tag);
315
    exp tg = getexp(sh(def), id, 1, id, nilexp,
316
		    0, 0, name_tag);
317
 
318
    pt(id) = tg;		/* use of tag */
319
    bro(def) = tg;		/* bro(def) is body of Let = tg */
320
    clearlast(def);
321
    *(x) = id;			/* replace pointer to x by Let */
322
    return;
323
  }
324
  else
325
  {				/* replace by Let tg = def In ato/def = tg Ni */
326
    exp def = *(x);
327
    exp ato = *(*to);
328
    exp id = getexp(sh(ato), bro(ato), last(ato), def, nilexp,
329
		    0, 1, ident_tag);
330
    exp tg = getexp(sh(def), bro(def), last(def), id, nilexp,
331
		    0, 0, name_tag);
332
 
333
    pt(id) = tg;		/* use of tg */
334
    bro(def) = ato;		/* ato is body of Let */
335
    clearlast(def);
336
    bro(ato) = id;		/* its father is Let */
337
    setlast(ato);
338
    *(*to) = id;		/* replace pointer to 'to' by Let */
339
    *(x) = tg;			/* replace use of x by tg */
340
    *to = &bro(def);		/* later replacement to same 'to' will be at
341
				 * body of Let */
342
    return;
343
  }
344
}
345
 
346
needs onefix = {1, 0, 0, 0};	/* needs one fix pt reg */
347
needs twofix = {2, 0, 0, 0};	/* needs 2 fix pt regs */
348
needs onefloat = {0, 1, 0, 0};	/* needs 1 flt pt regs */
349
needs zeroneeds = {0, 0, 0, 0};	/* has no needs */
350
 
351
 
352
#if 0		/* +++ optimise sharing of regs for idents */
6 7u83 353
bool subvar_use
354
(exp uses)
2 7u83 355
{				/* check to see if any uses of id is
356
				 * initialiser to subvar dec */
357
  for (; uses != nilexp; uses = pt(uses))
358
  {
359
    if (last(uses) && name(bro(uses)) == cont_tag)
360
    {
361
      exp c = bro(uses);
362
 
363
      if (!last(c) && last(bro(c)) && name(bro(bro(c))) == ident_tag)
364
      {
365
	exp id = bro(bro(c));
366
 
6 7u83 367
	if ((props(id) & subvar)!= 0 && (props(id) & inanyreg)!= 0)
2 7u83 368
	  return 1;
369
      }
370
    }
371
  }
372
  return 0;
373
}
374
#endif
375
 
376
 
377
/* this gives the needs for manipulating a value of shape s */
6 7u83 378
needs shapeneeds
379
(shape s)
2 7u83 380
{
381
  if (is_floating(name(s)))
382
    return onefloat;
383
  else
384
  {
385
    if (valregable(s))
386
    {
387
      return onefix;
388
    }
389
    else
390
    {
391
      /* if the shape does not fit into a reg, needs two fixed regs for moving */
392
      return twofix;
393
    }
394
  }
395
}
396
 
397
 
398
/*
399
  Transform a non-bit offset into a bit offset.
400
  (borrowed from trans386)
401
*/
6 7u83 402
static void make_bitfield_offset
403
(exp e, exp pe, int spe, shape sha) {
2 7u83 404
  exp omul;
405
  exp val8;
6 7u83 406
  if (name(e) == val_tag) {
407
    no(e)*= 8;
2 7u83 408
    return;
409
  }
6 7u83 410
  omul = getexp(sha, bro(e), (int)(last(e)), e, nilexp, 0, 0, offset_mult_tag);
411
  val8 = getexp(slongsh, omul, 1, nilexp, nilexp, 0, 8, val_tag);
2 7u83 412
  clearlast(e);
413
  setbro(e, val8);
6 7u83 414
  if (spe) {
2 7u83 415
    son(pe) = omul;
416
  }
417
  else{
418
    bro(pe) = omul;
419
  }
420
  return;
421
}
422
 
423
 
424
/*
425
 * these are basicly the expressions which cannot be accessed by a simple
426
 * load or store instruction
427
 */
6 7u83 428
bool complex
429
(exp e)
2 7u83 430
{				/* these are basically the expressions which
431
				 * cannot be accessed by a simple load or
432
				 * store instruction */
433
  if (name(e) == name_tag ||
6 7u83 434
     (name(e) == cont_tag && name(son(e)) == name_tag &&
2 7u83 435
       isvar(son(son(e))))
436
      || name(e) == val_tag || name(e) == real_tag)
437
  {
438
    return 0;
439
  }
440
  else
441
  {
442
    return 1;
443
  }
444
}
445
 
446
void change_to_var
6 7u83 447
(exp e)
2 7u83 448
{
449
	/* change identity to variable definition */
450
	exp p = pt(e);
451
	shape ns;
6 7u83 452
	assert(name(e) ==ident_tag && !isvar(e));
2 7u83 453
	setvar(e);
454
	setcaonly(e);
455
	ns = f_pointer(f_alignment(sh(son(e))));
456
	while (p != nilexp) {
457
		exp * pos = ptr_position(p);
458
		exp ncont = getexp(sh(p), bro(p), last(p), p, nilexp, 0, 0,
459
					cont_tag);
460
		bro(p) = ncont; setlast(p);
461
		sh(p) = ns;
462
		*pos = ncont;
463
		p = pt(p);
464
	}
465
}
466
 
467
void change_names
6 7u83 468
(exp f, exp t, exp except)
2 7u83 469
{
470
	/* replace uses of ident f (!= except) to uses of t */
471
	exp py = pt(f);
6 7u83 472
	assert(name(f) ==ident_tag && name(t) ==ident_tag && name(except) ==name_tag);
2 7u83 473
	while (py != nilexp) {
474
		exp ppy = pt(py);
475
		if (py != except) {
476
			son(py) = t; /* change f to t */
477
			pt(py) = pt(t);
6 7u83 478
			pt(t) = py;
2 7u83 479
			no(t)++;  /* maintain usage */
480
		}
481
		py = ppy;
482
	}
6 7u83 483
}
2 7u83 484
 
485
 
486
void tidy_ident
6 7u83 487
(exp e)
2 7u83 488
{
489
	/* replace Var/Id x = Var y = e1 in { e2; contents(y)} in e3;
490
	   by Var x = e1 in { e2/(y=>x); e3}
491
	   replace Var/Id x = Id y = e1 in {e2; y} in e3
492
	   by Var/Id x = e1 in { e2/y=>(cont)x; e3}
493
	*/
494
	exp init; exp bdyinit; exp idy;
495
	exp e1;
496
	exp e3;
6 7u83 497
	assert(name(e) ==ident_tag);
2 7u83 498
	init = son(e);
499
	e3 = bro(init);
6 7u83 500
	if (name(init)!= ident_tag || isparam(e)) { return ;}
2 7u83 501
	tidy_ident(init);
502
	e1 = son(init);
503
	bdyinit = bro(e1);
504
	if (!isvar(init)) {
505
	  if (name(bdyinit) == seq_tag) {
506
	    	exp idy = bro(son(bdyinit));
507
		exp broe3;
508
		bool laste3;
6 7u83 509
		if (name(idy)!= name_tag || son(idy)!= init ||
510
			no(idy)!=0 ||
511
			shape_size(sh(idy))!= shape_size(sh(e1)) ||
512
			shape_align(sh(idy))!= shape_align(sh(e1))) {
2 7u83 513
		    return;
514
		}
515
		if (isvar(e)) {
516
			change_to_var(init);
517
		}
6 7u83 518
		change_names(init, e, idy);
519
 
2 7u83 520
		broe3 = bro(e3);
521
		laste3 = last(e3);
522
		bro(son(bdyinit)) = e3;
523
		bro(e3) = bdyinit; setlast(bdyinit);
524
				/* bdyinit is now { e2/(y=>x); e3} */
525
		bro(bdyinit) = broe3;
526
		if (laste3) { setlast(bdyinit); }
527
		else { clearlast(bdyinit); }
528
		son(e) = e1;  /* bro(e1) is bdyinit */
529
		return;
530
	  }
531
	  else
6 7u83 532
	  if (name(bdyinit) == name_tag && (idy = son(bdyinit)) ==init
533
		&& no(idy) ==0 &&
2 7u83 534
		shape_size(sh(idy)) == shape_size(sh(e1)) &&
6 7u83 535
		shape_align(sh(idy)) == shape_align(sh(e1))) {
536
		/* form is Var/Id x = Id y = e1 in y in e3
2 7u83 537
			=> Var x = e1 in e3 */
538
		bro(e1) = e3;
539
		son(e) = e1;
540
	  }
6 7u83 541
	  else return;
2 7u83 542
	}
543
	else {
544
	  if (name(bdyinit) == seq_tag) {
545
		exp cy = bro(son(bdyinit));
546
		exp broe3;
547
		bool laste3;
6 7u83 548
		if (name(cy)!= cont_tag) return;
549
 
2 7u83 550
		idy = son(cy);
6 7u83 551
		if (name(idy)!= name_tag || no(idy)!= 0 ||
552
			son(idy)!= init ||
553
			shape_size(sh(cy))!= shape_size(sh(e1)) ||
554
			shape_align(sh(cy))!= shape_align(sh(e1))) {
2 7u83 555
			return;
556
		}
557
		if (!isvar(e)) {
558
			change_to_var(e);
559
			if (isvis(init)) { setvis(e); }
560
			if (!iscaonly(init)) { ClearCaonly(e); }
561
		}
6 7u83 562
 
2 7u83 563
		change_names(init,e,idy);
6 7u83 564
 
2 7u83 565
		broe3 = bro(e3);
566
		laste3 = last(e3);
567
		bro(son(bdyinit)) = e3;
568
		bro(e3) = bdyinit; setlast(bdyinit);
569
				/* bdyinit is now { e2/(y=>x); e3} */
570
		bro(bdyinit) = broe3;
571
		if (laste3) { setlast(bdyinit); }
572
		else { clearlast(bdyinit); }
573
		son(e) = e1;  /* bro(e1) is bdyinit */
574
		return;
575
	  }
576
	  else
577
	  if (name(bdyinit) == cont_tag) {
578
		exp cy =  bro(son(bdyinit));
579
		idy = son(cy);
6 7u83 580
		if (name(idy)!= name_tag || no(idy)!= 0 ||
581
			son(idy)!= init ||
582
			shape_size(sh(cy))!= shape_size(sh(e1)) ||
583
			shape_align(sh(cy))!= shape_align(sh(e1))) {
2 7u83 584
			return;
585
		}
6 7u83 586
		/* form is Var x = Var y = e1 in cont(y) in e3
2 7u83 587
			=> Var x = e1 in e3 */
588
		if (!isvar(e)) {
589
			change_to_var(e);
590
			if (isvis(init)) { setvis(e); }
591
			if (!iscaonly(init)) { ClearCaonly(e); }
592
		}
593
		bro(e1) = e3;
594
		son(e) = e1;
595
	  }
596
	  else return;
597
	}
598
 
599
}
600
 
601
 
602
int scan_cond
6 7u83 603
(exp * e, exp outer_id)
2 7u83 604
{
605
 
606
	exp ste = *e;
6 7u83 607
	exp first = son(ste);
608
	exp labst = bro(first);
609
	exp second = bro(son(labst));
2 7u83 610
 
6 7u83 611
	assert(name(ste) ==cond_tag);
2 7u83 612
 
6 7u83 613
	if (name(second) ==top_tag && name(sh(first)) ==bothd && no(son(labst)) ==1
614
		&& name(first) ==seq_tag && name(bro(son(first))) == goto_tag) {
2 7u83 615
		/* cond is { ... test(L); ? ; goto X | L:make_top}
616
			if ? empty can replace by seq { ... not-test(X); make_top }
617
		*/
618
		exp l = son(son(first));
6 7u83 619
		while (!last(l)) { l = bro(l); }
620
		while (name(l) ==seq_tag) { l = bro(son(l)); }
621
		if (name(l) ==test_tag && pt(l) ==labst) {
2 7u83 622
		   settest_number(l, notbranch[test_number(l)]);
623
		   pt(l) = pt(bro(son(first)));
624
		   bro(son(first)) = second;
625
		   bro(second) = first; setlast(second);
6 7u83 626
		   bro(first) = bro(ste);
627
		   if (last(ste)) { setlast(first);} else { clearlast(first); }
2 7u83 628
		   *e = first;
629
		   return 1;
630
		}
631
		else return 0;
632
	}
633
 
634
 
6 7u83 635
	if (name(first) == seq_tag && name(second) == cond_tag
636
	    && no(son(labst)) == 1
637
	    && name(son(son(first))) == test_tag
638
	    && pt(son(son(first))) == labst
639
	    && name(son(second)) == seq_tag
640
	    && name(son(son(son(second)))) == test_tag) {
641
				/* cond is ( seq (test to L;....|
2 7u83 642
				   L:cond(seq(test;...),...) ) ..... */
6 7u83 643
	  exp test1 = son(son(first));
644
	  exp test2 = son(son(son(second)));
2 7u83 645
	  exp op11 = son(test1);
646
	  exp op21 = bro(op11);
647
	  exp op12 = son(test2);
648
	  exp op22 = bro(op12);
6 7u83 649
	  bool c1 = complex(op11);
650
	  bool c2 = complex(op21);
2 7u83 651
 
6 7u83 652
	  if (c1 && eq_exp(op11, op12)) {
2 7u83 653
				/* ....if first operands of tests are
654
				   same, identify them */
6 7u83 655
	    exp newid = getexp(sh(ste), bro(ste), last(ste), op11, nilexp,
2 7u83 656
		0, 2, ident_tag);
6 7u83 657
	    exp tg1 = getexp(sh(op11), op21, 0, newid, nilexp, 0, 0, name_tag);
658
	    exp tg2 = getexp(sh(op12), op22, 0, newid, nilexp, 0, 0, name_tag);
2 7u83 659
 
6 7u83 660
	    pt(newid) = tg1;
2 7u83 661
	    pt (tg1) = tg2;	/* uses of newid */
662
	    bro (op11) = ste; clearlast (op11);/* body of newid */
663
	    /* forget son test2 = son test1 */
6 7u83 664
	    bro(ste) = newid;
2 7u83 665
	    setlast (ste);	/* father body = newid */
6 7u83 666
	    son(test1) = tg1;
2 7u83 667
	    son (test2) = tg2;	/* relace 1st operands of test */
6 7u83 668
	    if (!complex(op21)) {
2 7u83 669
		/* if the second operand of 1st test is simple, then identification
670
			could go in a t-teg (!!!NB overloading of inlined flag!!!).... */
6 7u83 671
		setinlined(newid);
2 7u83 672
	    }
673
	    kill_exp(op12, op12);
6 7u83 674
	    *(e) = newid;
675
	    if (scan_cond(&bro(son(labst)), newid) == 2 && complex(op22)) {
676
		/* ... however a further use of identification means that
2 7u83 677
		   the second operand of the second test must also be simple */
678
		clearinlined(newid);
679
	    }
680
	    return 1;
681
	  }
682
	  else
6 7u83 683
	  if (c2 && eq_exp(op21, op22)) {
2 7u83 684
				/* ....if second operands of tests are
685
				   same, identify them */
686
 
6 7u83 687
	      exp newid = getexp(sh(ste), bro(ste), last(ste), op21,
2 7u83 688
		  nilexp, 0, 2, ident_tag);
6 7u83 689
	      exp tg1 = getexp(sh(op21), test1, 1,
2 7u83 690
		  newid, nilexp, 0, 0, name_tag);
6 7u83 691
	      exp tg2 = getexp(sh(op22), test2, 1, newid, nilexp,
2 7u83 692
		  0, 0, name_tag);
693
 
6 7u83 694
	      pt(newid) = tg1;
2 7u83 695
	      pt (tg1) = tg2;	/* uses of newid */
6 7u83 696
	      bro(op21) = ste; clearlast(op21);
2 7u83 697
	      /* body of newid */
698
	      /* forget bro son test2 = bro son test1 */
6 7u83 699
	      bro(ste) = newid;
2 7u83 700
	      setlast (ste);	/* father body = newid */
6 7u83 701
	      bro(op11) = tg1;
702
	      bro(op12) = tg2;
703
	      if (!complex(op11)) { setinlined(newid); }
2 7u83 704
	      kill_exp(op22, op22);
705
	      /* relace 2nd operands of test */
6 7u83 706
	      *(e) = newid;
707
	      if (scan_cond(&bro(son(labst)), newid) == 2 && complex(op12)) {
708
			clearinlined(newid);
2 7u83 709
	      }
710
	      return 1;
711
	  }
712
	  else
6 7u83 713
	  if (name(op12)!= name_tag
714
		  && name(op11) == name_tag
715
		  && son(op11) == outer_id
716
		  && eq_exp(son(outer_id), op12)
2 7u83 717
		) {		/* 1st param of test1 is already identified with
718
				   1st param of  test2 */
6 7u83 719
		exp tg = getexp(sh(op12), op22, 0, outer_id,
720
		    pt(outer_id), 0, 0, name_tag);
721
		pt(outer_id) = tg;
722
		no(outer_id) += 1;
723
		if (complex(op21)) { clearinlined(outer_id); }
2 7u83 724
		/* update usage of ident */
6 7u83 725
		son(test2) = tg;
2 7u83 726
		kill_exp(op12, op12);
6 7u83 727
		if (scan_cond(&bro(son(labst)), outer_id) == 2 && complex(op22)) {
2 7u83 728
			clearinlined(outer_id);
729
		}
730
		return 2;
731
	      }
732
 
733
 
6 7u83 734
	}
2 7u83 735
	return 0;
736
}
737
 
738
/*
739
 * does the scan on commutative and associative operations and may perform
740
 * various transformations allowed by these properties
741
 */
6 7u83 742
needs likeplus
743
(exp * e, exp ** at)
2 7u83 744
{
745
  needs a1;
746
  needs a2;
747
  prop pc;
748
  exp *br = &son(*e);
749
  exp prev;
750
  bool commuted = 0;
6 7u83 751
  exp dad = *(e);
2 7u83 752
 
753
  a1 = scan(br, at);
754
  /* scan the first operand - won't be a val_tag */
755
 
756
  do {
757
    exp *prevbr;
758
    prevbr = br;
759
    prev = *(br);
760
    br = &bro(prev);
761
    a2 = scan(br, at);
762
    /* scan the next operand ... */
6 7u83 763
    if (name(*(br))!= val_tag) {
2 7u83 764
      a1.floatneeds = MAX_OF(a1.floatneeds, a2.floatneeds);
765
      pc = a2.propsneeds & hasproccall;
766
      if (a2.fixneeds < maxfix && pc == 0)
767
	/* ... its evaluation  will not disturb the accumulated result */
768
      {
769
	a1.fixneeds = MAX_OF(a1.fixneeds, a2.fixneeds + 1);
770
	a1.propsneeds = a1.propsneeds | a2.propsneeds;
771
      }
772
      else if (a1.fixneeds < maxfix && (a1.propsneeds & hasproccall) == 0 && !commuted)
773
      {
774
 
775
	/*
776
	 * ...its evaluation will call a proc, so put it first
777
	 */
778
	exp op1 = son(dad);
779
	exp cop = *(br);
780
	bool lcop = last(cop);
781
	bro(prev) = bro(cop);
782
	if (lcop)
783
	  setlast(prev);
784
	bro(cop) = op1;
785
	clearlast(cop);
786
	son(dad) = cop;
6 7u83 787
	br = (prev == op1)? &bro(cop): prevbr;
2 7u83 788
	op1->commuted=1;
789
	cop->commuted=1;
790
	commuted = 1;
791
	a1.fixneeds = MAX_OF(a2.fixneeds, a1.fixneeds + 1);
792
	a1.propsneeds |= a2.propsneeds;
793
	a1.maxargs = MAX_OF(a1.maxargs, a2.maxargs);
794
      }
795
      else
796
      {
797
 
798
	/*
799
	 * evaluation would disturb accumulated result, so replace it by a
800
	 * newly declared tag
801
	 */
802
	FULLCOMMENT("likeplus: insert ident");
803
	cca(at, br);
804
	a1.fixneeds = MAX_OF(a1.fixneeds, 2);
805
	a1.propsneeds = a1.propsneeds | morefix | (pc << 1);
806
	a1.maxargs = MAX_OF(a1.maxargs, a2.maxargs);
807
      }
808
    }
809
    else
810
    {
811
      FULLCOMMENT("likeplus: val_tag");
812
    }
813
  } while (!last(*(br)));
814
#if 1           			/* exception handling regs */
815
  if (!optop(*(e)))
816
  {
817
    if (a1.fixneeds < 4)
818
      a1.fixneeds = 4;
819
  }
820
#endif
821
 
822
  return a1;
823
}
824
 
825
 
826
/* scan non-commutative fix pt operation */
6 7u83 827
needs likediv
828
(exp * e, exp ** at)
2 7u83 829
{
830
  needs l;
831
  needs r;
832
  prop pc;
833
  exp *arg = &son(*e);
834
 
835
  l = scan(arg, at);
836
  /* scan 1st operand */
837
  arg = &bro(*arg);
838
  r = scan(arg, at);
839
  /* scan second operand ... */
840
  l.floatneeds = MAX_OF(l.floatneeds, r.floatneeds);
841
 
842
  pc = r.propsneeds & hasproccall;
843
  if (r.fixneeds < maxfix && pc == 0)
844
  {
845
    /* fits into registers */
846
    l.fixneeds = MAX_OF(l.fixneeds, r.fixneeds + 1);
847
    l.propsneeds = l.propsneeds | r.propsneeds;
848
    FULLCOMMENT2("likediv: r.fixneeds(%d) < maxfix(%d) && pc == 0", r.fixneeds, maxfix);
849
  }
850
  else
851
  {
852
    /* requires new declaration of second operand */
853
    cca(at, arg);
854
    l.fixneeds = MAX_OF(l.fixneeds, 1);
855
    l.propsneeds = l.propsneeds | morefix | (pc << 1);
856
    l.maxargs = MAX_OF(l.maxargs, r.maxargs);
857
    FULLCOMMENT2("likediv: insert decl r.fixneeds=%d maxfix=%d", r.fixneeds, maxfix);
858
  }
859
#if 1				/* exception handling regs (from mips) */
860
  if (!optop(*(e)))
861
  {
862
    if (l.fixneeds < 4)
863
      l.fixneeds = 4;
864
  }
865
#endif
866
  return l;
867
}
868
 
6 7u83 869
needs fpop
870
(exp * e, exp ** at)
2 7u83 871
{
872
  /* scans diadic floating point operation  */
873
  needs l;
874
  needs r;
875
  exp op = *(e);
876
  prop pcr, pcl;
877
  exp *arg = &son(op);
878
 
879
  l = scan(arg, at);
880
  arg = &bro(*arg);
881
  r = scan(arg, at);
882
  l.fixneeds = MAX_OF(l.fixneeds, r.fixneeds);
883
  pcr = r.propsneeds & hasproccall;
884
  pcl = l.propsneeds & hasproccall;
885
 
886
  if (!optop(*(e)))
887
  {
888
    if (l.fixneeds < 2)
889
      l.fixneeds = 2;
890
  }
891
 
892
#if use_long_double
6 7u83 893
    if (name(sh(son(op))) ==doublehd)
2 7u83 894
    {
6 7u83 895
	ClearRev(op);
896
	arg=&son(op);
897
	if (!is_o(name(*arg)) || pcl)cca(at,arg);
898
	arg = &bro(son(op));
899
	if (!is_o(name(*arg)) || pcr)cca(at, arg);
900
	l.floatneeds = MAX_OF(l.floatneeds, r.floatneeds);
901
	l.maxargs = MAX_OF(l.maxargs, r.maxargs);
902
	pnset(l,hasproccall);
903
	return(l);
2 7u83 904
    }
905
#endif
906
 
907
  if (r.floatneeds <= l.floatneeds && r.floatneeds < maxfloat && pcr == 0)
908
  {
909
    l.floatneeds = MAX_OF(2, MAX_OF(l.floatneeds, r.floatneeds + 1));
910
    l.propsneeds = l.propsneeds | r.propsneeds;
911
    ClearRev(op);
912
  }
913
  else if (pcl == 0 && l.floatneeds <= r.floatneeds && l.floatneeds < maxfloat)
914
  {
915
    l.floatneeds = MAX_OF(2, MAX_OF(r.floatneeds, l.floatneeds + 1));
916
    l.propsneeds = l.propsneeds | r.propsneeds;
917
    SetRev(op);
918
  }
919
  else if (r.floatneeds < maxfloat && pcr == 0)
920
  {
921
    l.floatneeds = MAX_OF(2, MAX_OF(l.floatneeds, r.floatneeds + 1));
922
    l.propsneeds = l.propsneeds | r.propsneeds;
923
    ClearRev(op);
924
  }
925
  else
926
  {
927
    cca(at, arg);
928
    ClearRev(op);
929
    l.floatneeds = MAX_OF(l.floatneeds, 2);
930
    l.propsneeds = l.propsneeds | morefloat | (pcr << 1);
931
    l.maxargs = MAX_OF(l.maxargs, r.maxargs);
932
  }
933
  return l;
934
}
935
 
936
/**********************************************************************
937
	maxneeds
938
 
939
Calculates a needs value. Each element of which is the maximum of the
940
corresponding elements in the two parameter needs
941
**********************************************************************/
942
 
6 7u83 943
needs maxneeds
944
(needs a, needs b)
2 7u83 945
{
946
  needs an;
947
 
948
  an.fixneeds = MAX_OF(a.fixneeds, b.fixneeds);
949
  an.floatneeds = MAX_OF(a.floatneeds, b.floatneeds);
950
  an.maxargs = MAX_OF(a.maxargs, b.maxargs);
951
  an.propsneeds = a.propsneeds | b.propsneeds;
952
  return an;
953
}
954
 
955
/**********************************************************************
956
	maxtup
957
 
958
**********************************************************************/
959
 
6 7u83 960
needs maxtup
961
(exp e, exp ** at)
2 7u83 962
{				/* calculates the needs of a tuple of
963
				 * expressions; any new declarations required
964
				 * by a component expression will replace the
965
				 * component expression */
966
  exp *stat = &son(e);
967
  needs an;
968
 
969
  an = zeroneeds;
970
  while (an = maxneeds(an, scan(stat, at)), !last(*stat))
971
  {
972
    stat = &bro(*stat);
973
  }
974
  return an;
975
}
976
 
6 7u83 977
bool unchanged
978
(exp usedname, exp ident)
2 7u83 979
 
980
 /*
981
  * finds if usedname is only used in cont operation or as result of ident
982
  * i.e. value of name is unchanged over its scope
983
  */
984
{
985
  exp uses = pt(usedname);
986
 
987
  while (uses != nilexp)
988
  {
989
    if (intnl_to(ident, uses))
990
    {
6 7u83 991
      if (!last(uses) || name(bro(uses))!= cont_tag)
2 7u83 992
      {
993
	exp z = uses;
994
 
995
	while (z != ident)
996
	{
997
	  if (!last(z) ||
6 7u83 998
	     (name(bro(z))!= seq_tag && name(bro(z))!= ident_tag))
2 7u83 999
	  {
1000
	    return 0;
1001
	  }
1002
	  z = bro(z);
1003
	}
1004
      }
1005
    }
1006
    uses = pt(uses);
1007
  }
1008
  return 1;
1009
}
1010
 
1011
 
1012
 
1013
/*
1014
 * The HPPA convention for delivering a struct from a procedure is is have an
1015
 * extra pointer parameter in the proc; this means that there always must be
1016
 * space in the calling work-space for the result struct whether or not the
1017
 * value is used e.g. as in f(x); or f(x).a etc. This proc is part of the
1018
 * mechanism to determine whether it is necessary to insert a dummy
1019
 * declaration to ensure that this space exists.
1020
 */
6 7u83 1021
bool chase
1022
(exp sel, exp * e)
2 7u83 1023
{
1024
  bool b = 0;
1025
  exp *one;
1026
 
1027
  switch (name(*e))
1028
  {
1029
  case ident_tag:
1030
  case seq_tag:
1031
  case rep_tag:
1032
  case labst_tag:
1033
    {
1034
      b = chase(sel, &bro(son(*e)));
1035
      break;
1036
    }
1037
 
1038
  case solve_tag:
1039
  case cond_tag:
1040
    {
1041
      one = &son(*e);
1042
      for (;;)
1043
      {
1044
	b |= chase(sel, one);
1045
	if (last(*one))
1046
	  break;
1047
	one = &bro(*one);
1048
      }
1049
      break;
1050
    }
1051
  case field_tag:
1052
    {
1053
      if (chase(*e, &son(*e)))
1054
      {
1055
	/* inner field has been distributed */
1056
	exp stare = *e;
1057
	exp ss = son(stare);
6 7u83 1058
 
2 7u83 1059
	if (!last(stare))
1060
	    clearlast(ss);
1061
	bro(ss) = bro(stare);
1062
	sh(ss) = sh(stare);
1063
	*e = ss;
1064
	return chase(sel, e);
1065
      }				/* ... continue to default */
1066
    }
1067
  default:
1068
    {
6 7u83 1069
      if ((son(sel)!= *e) && (name(sh(*e))!= bothd))
2 7u83 1070
      {				/* only change if not outer */
1071
	exp stare = *e;
1072
	exp newsel = getexp(sh(sel), bro(stare), last(stare), stare, nilexp,
1073
			    props(sel), no(sel), name(sel));
1074
 
1075
	*e = newsel;
1076
	bro(stare) = newsel;
1077
	setlast(stare);
1078
	b = 1;
1079
      }
1080
    }
1081
  }
1082
  if (b)
1083
    sh(*e) = sh(sel);
1084
  return b;
1085
}
1086
 
1087
 
1088
 
1089
 
1090
/********************************************************************
1091
		scan
1092
 
1093
	This procedure works out register requirements of an exp. At each
1094
call the fix field of the needs is the number of fixpnt registers required to
1095
contain live values to evaluate this expression. This never exceeds maxfix
1096
because if it would have, a new declaration is introduced in the exp tree
1097
(similarly for floating regs and maxfloat). In these cases the prop field will
1098
contain the bits morefix (or morefloat).
1099
	Scan also works out various things concerned with proc calls.
1100
The maxargs field contains the max size in bits of the space required for the
1101
parameters of all the procedures called in the exp. An exp proc call
1102
produces a hasproccall bit in the prop field, if this is transformed as part of
1103
the definition of a new declaration the bit is replaced by a usesproccall. The
1104
distinction is only used in unfolding nested proc calls; SPARC requires this to
1105
be done statically. The condition that a proc exp is a leaf (i.e no proc calls)
1106
is that its prop contains neither bit.
1107
	If an ident exp is suitable, scan marks the props of ident with
1108
either inreg or infreg bits to indicate that a t reg may be used for this tag.
1109
 
1110
	A thorough understanding of needs along with other procedures
1111
that do switch(name(exp)) requires a knowledge of the meaning of the fields
1112
of the exp in each case.
1113
 
1114
********************************************************************/
1115
 
1116
 
6 7u83 1117
needs scan
1118
(exp * e, exp ** at)
2 7u83 1119
{
1120
 
1121
  /*
1122
   * e is the expression to be scanned, at is the place to put any new decs .
1123
   * NB order of recursive calls with same at is critical
1124
   */
1125
  exp ste = *(e);
1126
  int nstare = name(ste);
1127
 
1128
  nexps++;
1129
 
1130
  /* ignore diagnostic information */
1131
#if 0
1132
  while (nstare == diag_tag || nstare == cscope_tag || nstare == fscope_tag)
1133
  {
1134
    e = &son(ste);
6 7u83 1135
    ste = *(e);
1136
    nstare = name(ste);
2 7u83 1137
  }
1138
#endif
1139
 
6 7u83 1140
  FULLCOMMENT1("scan: %s",(int)TAG_NAME(nstare));
2 7u83 1141
 
1142
  switch (nstare)
1143
  {
1144
  case 0:
1145
    {
1146
      return zeroneeds;
1147
      /* NOTREACHED */
1148
    }
1149
 
1150
  case compound_tag:
1151
    {
1152
      return maxtup(ste, at);
1153
    }
1154
 
1155
  case nof_tag:
1156
  case concatnof_tag:
1157
  case ncopies_tag:
1158
      {
1159
	needs nl;
1160
	bool cantdo;
1161
	exp dad;
1162
#if 1
6 7u83 1163
      if (nstare==nof_tag && son(ste) ==nilexp)
2 7u83 1164
	return zeroneeds;
1165
#endif
6 7u83 1166
	if (name(ste) ==ncopies_tag && name(son(ste))!=name_tag
1167
	    && name(son(ste))!= val_tag) {
2 7u83 1168
	  nl = scan(&son(*e), at);
1169
	  cca(at, &son(*e));
1170
	}
1171
	else nl = maxtup(*(e), at);
1172
	ste = *e;
1173
	dad = father(ste);
1174
 
6 7u83 1175
	if (name(dad) ==compound_tag || name(dad) == nof_tag
2 7u83 1176
	    || name(dad) == concatnof_tag)
1177
	{
1178
	  cantdo = 0;
1179
	}
1180
	else
1181
	if (last(ste))
1182
	{
6 7u83 1183
	  if (name(bro(ste)) == ass_tag)
2 7u83 1184
	  {
1185
	    exp a = son(bro(ste));
6 7u83 1186
	    cantdo = (name(a)!= name_tag || !isvar(son(a)));
2 7u83 1187
	  }
1188
	  else
1189
	  {
1190
	    cantdo = 1;
1191
	  }
1192
	}
1193
	else
6 7u83 1194
	if (last(bro(ste)))
2 7u83 1195
	{
6 7u83 1196
	  cantdo = (name(bro(bro(ste)))!= ident_tag);
2 7u83 1197
	}
1198
	else
1199
	{
1200
	  cantdo = 1;
1201
	}
1202
 
1203
	if (cantdo)
1204
	{
1205
	  /* can only deal with tuples in simple assignment or identity */
1206
	  int prps = (nl.propsneeds & hasproccall) << 1;
1207
	  cca(at, ptr_position(ste));
1208
	  nl = shapeneeds(sh(*(e)));
1209
	  nl.propsneeds |= morefix;
1210
	  nl.propsneeds |= prps;
1211
	}
1212
 
6 7u83 1213
	if (nl.fixneeds <2)nl.fixneeds = 2;
2 7u83 1214
	return nl;
1215
      }
1216
 
1217
  case cond_tag:
1218
    {
1219
#if 1
6 7u83 1220
      if (scan_cond(e, nilexp)!=0)
2 7u83 1221
      {
1222
	 return scan(e, at);
1223
      }
1224
      /* else goto next case */
1225
#else
1226
      exp first = son(ste);
1227
      exp labst = bro(first);
6 7u83 1228
      exp second = bro(son(labst));
2 7u83 1229
      exp t, f, v;
1230
      if (name(first) == seq_tag && name(second) == cond_tag &&
1231
	  name(son(son(first))) == test_tag && pt(son(son(first))) == labst
1232
	  && name(son(second)) == seq_tag
1233
	  && name(son(son(son(second)))) == test_tag)
1234
      {				/* cond is ( seq (test to L;....),
1235
				 * L:cond(seq(test;...),...) ) ..... */
1236
	exp test1 = son(son(first));
1237
	exp test2 = son(son(son(second)));
1238
	bool c1 = complex(son(test1));
1239
	bool c2 = complex(bro(son(test1)));
1240
 
1241
	if (c1 && eq_exp(son(test1), son(test2)))
1242
	  /* ....if first operands of tests are same, identify them */
1243
	{
1244
	  exp o21 = bro(son(test1));
1245
	  exp o22 = bro(son(test2));
1246
	  exp newid = getexp(sh(ste), bro(ste), last(ste), son(test1), nilexp,
1247
			     0, 2, ident_tag);
1248
	  exp tg1 = getexp(sh(son(test1)), o21, 0, newid, nilexp, 0, 0, name_tag);
1249
	  exp tg2 = getexp(sh(son(test2)), o22, 0, newid, nilexp, 0, 0, name_tag);
1250
 
1251
	  pt(newid) = tg1;
1252
	  pt(tg1) = tg2;	/* uses of newid */
1253
	  bro(son(test1)) = ste;
1254
	  clearlast(son(test1));/* body of newid */
1255
	  /* forget son test2 = son test1 */
1256
	  bro(ste) = newid;
1257
	  setlast(ste);		/* father body = newid */
1258
	  son(test1) = tg1;
1259
	  son(test2) = tg2;	/* relace 1st operands of test */
1260
	  *(e) = newid;
1261
	  return scan(e, at);
1262
	}
1263
	else if (c2 && eq_exp(bro(son(test1)), bro(son(test2))))
1264
	  /* ....if second operands of tests are same, identify them */
1265
	{
1266
	  exp o21 = bro(bro(son(test1)));
1267
	  exp o22 = bro(bro(son(test2)));
1268
	  exp newid = getexp(sh(ste), bro(ste), last(ste), bro(son(test1)),
1269
			     nilexp, 0, 2, ident_tag);
1270
	  exp tg1 = getexp(sh(bro(son(test1))), o21, 1,
1271
			   newid, nilexp, 0, 0, name_tag);
1272
	  exp tg2 = getexp(sh(bro(son(test2))), o22, 1, newid, nilexp,
1273
			   0, 0, name_tag);
1274
 
1275
	  pt(newid) = tg1;
1276
	  pt(tg1) = tg2;	/* uses of newid */
1277
	  bro(bro(son(test1))) = ste;
1278
	  clearlast(bro(son(test1)));
1279
	  /* body of newid */
1280
	  /* forget bro son test2 = bro son test1 */
1281
	  bro(ste) = newid;
1282
	  setlast(ste);		/* father body = newid */
1283
	  bro(son(test1)) = tg1;
1284
	  bro(son(test2)) = tg2;
1285
	  /* relace 2st operands of test */
1286
	  *(e) = newid;
1287
	  return scan(e, at);
1288
	}
6 7u83 1289
	else if (name(son(test2))!= name_tag
2 7u83 1290
		 && name(son(test1)) == name_tag &&
1291
		 name(son(son(test1))) == ident_tag && !isvar(son(son(test1)))
1292
		 && !isglob(son(son(test1)))
1293
		 && eq_exp(son(son(son(test1))), son(test2))
6 7u83 1294
	 )
2 7u83 1295
	  /* 1st param of test1 is identified with 1st param of  test2 */
1296
	{
1297
	  exp tg = getexp(sh(son(test1)), bro(son(test2)), 0, son(son(test1)),
1298
			  pt(son(son(test1))), 0, 0, name_tag);
1299
 
1300
	  pt(son(son(test1))) = tg;
1301
	  no(son(son(test1))) += 1;
1302
	  /* update usage of ident */
1303
	  son(test2) = tg;
1304
	  /* and then drop into next case */
1305
	  FULLCOMMENT("scan() cond_tag: case 3");
1306
	}
1307
 
1308
      }				/* else goto next case */
1309
      FULLCOMMENT("scan() cond_tag: case 4");
1310
#endif
1311
    }
1312
    /* FALLTHOUGH */
1313
 
1314
 
1315
  case labst_tag:
1316
  case rep_tag:
1317
  case solve_tag:
1318
    {
1319
      exp *stat;
1320
      exp *statat;
1321
      needs an;
1322
 
1323
      stat = &son(*e);
1324
      statat = stat;
1325
      an = zeroneeds;
1326
      while (an = maxneeds(an, scan(stat, &statat)),
1327
 
1328
	     !last(*(stat)))
1329
      {
1330
	stat = &bro(*stat);
1331
	statat = stat;
1332
      }
6 7u83 1333
      if ((an.propsneeds & usesproccall)!= 0)
2 7u83 1334
      {
1335
	an.propsneeds |= hasproccall;
1336
      }
1337
      return an;
1338
    }
1339
 
1340
/*********************************************************************
1341
	ident
1342
 
1343
shape of exp is body,
1344
son is def, brother of son is body,
1345
ptr of ident exp is chain of uses
1346
*********************************************************************/
1347
 
1348
  case ident_tag:
1349
  {
1350
     needs bdy;
1351
     needs def;
1352
     exp stare = *(e);
1353
     exp *arg = &bro(son(stare));
1354
     exp t = pt(stare), s;
1355
     shape shdef = sh(son(stare));
1356
     bool fxregble;
1357
     bool flregble;
1358
     bool old_nonevis = nonevis;
1359
 
6 7u83 1360
     if (pt(stare) == nilexp)
2 7u83 1361
     {
1362
	/* no uses, should have caonly flag and no var flag */
1363
	setcaonly(stare);
1364
	clearvar(stare);
1365
     }
1366
     if (diagnose && (name(shdef)!=bitfhd))
1367
	setvis(stare);
1368
/*     if (!iscaonly(stare) || all_variables_visible)*/
1369
     if (isvar(stare) && (!iscaonly(stare) || all_variables_visible))
1370
     {
1371
	setvis(stare);
1372
     }
1373
 
1374
     if (isparam(stare))
1375
     {
1376
	exp def = son(stare);
1377
	shape shdef = sh(def);
1378
	long sz = shape_size(shdef);
1379
	if (name(son(stare))!= formal_callee_tag)
1380
	{
1381
	   assert(name(def) == clear_tag);
1382
	   /* round up bytes and halfwords to full words */
1383
	   if (sz>0 && sz<32)
1384
	      sz=32;
1385
	   /* round up small (i.e. < 64 byte) structues to two words */
1386
	   else if (sz>32 && sz<64)
1387
	      sz=64;
6 7u83 1388
 
2 7u83 1389
	   /* parameters must be properly aligned */
1390
	   stparam = rounder(stparam+sz,sz);
1391
 
6 7u83 1392
	   fixparam = ARG0+ (stparam>>5) -1;
1393
	   fltparam = 3*(3+ (stparam>>5)) +1;
2 7u83 1394
 
6 7u83 1395
	   if (valregable(shdef) && (shape_size(shdef) ==8 ||
1396
				      shape_size(shdef) ==16))
2 7u83 1397
	      /* Right align bytes and halfwords. */
6 7u83 1398
	      no(def) = stparam-32+shape_size(shdef);
2 7u83 1399
	   else
6 7u83 1400
	      no(def) = stparam;
2 7u83 1401
 
1402
	   if (is_floating(name(shdef)))
1403
	   {
6 7u83 1404
	      if (fltparam < (3*8) +1)
2 7u83 1405
	      {
1406
		 /* floating paramter passed in registers */
6 7u83 1407
		 props(def) = fltparam;
2 7u83 1408
		 maxfloat--;
1409
	      }
1410
	      else
1411
	      {
1412
		 /* floating parameter passed by stack */
1413
		 props(def) = 0;
1414
	      }
1415
	   }
1416
	   else
6 7u83 1417
	   {
2 7u83 1418
	      if (fixparam<ARG3+1)
1419
	      {
1420
 	         /* param reg(s) free for the param */
1421
		 props(def) = fixparam;
1422
		 if (name(shdef)!=cpdhd && name(shdef)!=nofhd)
1423
		    maxfix--;
1424
	      }
1425
	      else
1426
 	         props(def) = 0;	/* Pass by stack */
1427
	  }
1428
       }
1429
       else
1430
       {
1431
	  long alp = shape_align(shdef);
1432
	  long n = rounder(callee_sz, alp);
1433
	  no(def) = n;
1434
	  callee_sz = rounder(n+sz,32);
6 7u83 1435
       }
2 7u83 1436
    }
1437
 
1438
    nonevis &= !isvis(stare);
1439
 
1440
    /* scan the body of the identity */
1441
    bdy = scan(arg, &arg);
1442
 
1443
    /* scan the body-scope */
1444
    arg = &son(stare);
1445
    def = scan(arg, &arg);
1446
    /* scan the initialisation of tag */
1447
 
1448
    nonevis = old_nonevis;
1449
    t = son(stare);
1450
    s = bro(t);
1451
    fxregble = fixregable(stare);
1452
    flregble = floatregable(stare);
1453
 
1454
    if (isparam(stare))
1455
    {
6 7u83 1456
       if (name(son(stare)) ==formal_callee_tag)
2 7u83 1457
       {
1458
	  /* IDENT is a callee parameter. */
1459
	  no(stare) = R_NO_REG;
1460
       }
1461
       else
1462
       {
6 7u83 1463
	  bool is_aggregate = (name(shdef) ==cpdhd || name(shdef) ==nofhd ||
1464
			       name(shdef) ==s64hd || name(shdef) ==u64hd);
2 7u83 1465
	  if (!is_aggregate && !isvis(stare) &&
6 7u83 1466
	      !isoutpar(stare) &&
1467
	     ((bdy.propsneeds & anyproccall) == 0 ||
1468
	      (!has_tail_call &&
1469
		tempdec(stare,(fxregble && bdy.fixneeds <= 2) ||
1470
	     	                (flregble && bdy.floatneeds <= 1)))))
2 7u83 1471
	  {
1472
	     int x = props(son(stare)); /* param reg it comes in, or else 0 */
1473
	     if (x != 0 && (props(stare) & notparreg) == 0)
1474
	     {
1475
		/*
1476
		 * use input param for leaf proc, unless it is R_RESULT=ARG0
1477
		 * and we plan to use that specially
1478
		 */
1479
		no(stare) = x;
1480
		if (flregble)
1481
		{
1482
		   /* props(stare) |= infreg_bits; */
6 7u83 1483
		   no(stare) =0;
2 7u83 1484
		}
1485
		else
1486
		{
1487
		   props(stare) |= inreg_bits;
1488
		}
1489
	     }
1490
	     else
6 7u83 1491
	     if (fxregble && bdy.fixneeds<maxfix && (bdy.propsneeds & morefix) ==0)
2 7u83 1492
	     {
1493
		no(stare) = 0;
1494
		props(stare) |= inreg_bits;
1495
		bdy.fixneeds += 1;
1496
	     }
1497
	     else
1498
	     if (flregble && bdy.floatneeds < maxfloat && 0 && (bdy.propsneeds & morefloat) == 0)
1499
	     {
1500
		no(stare) = 0;
1501
		props(stare) |= infreg_bits;
1502
		bdy.floatneeds += 1;
1503
	     }
1504
	     else
1505
		no(stare) = R_NO_REG;
1506
	  }
1507
	  else
1508
	     no(stare) = R_NO_REG;
1509
       }
1510
    }
1511
    else
1512
    {
1513
       /* NON PARAMETER */
1514
       assert(!isparam(*e));			/* handled above */
1515
       if (!isvis(*e) && !isparam(*e) &&
6 7u83 1516
	  (bdy.propsneeds & (anyproccall | uses_res_reg_bit)) == 0
2 7u83 1517
	   && (fxregble /*|| flregble*/) &&
6 7u83 1518
	  (name(t) == apply_tag ||
1519
	   (name(s) == seq_tag && name(bro(son(s))) == res_tag &&
2 7u83 1520
	     name(son(bro(son(s)))) == cont_tag && isvar(stare) &&
1521
	     name(son(son(bro(son(s))))) == name_tag &&
1522
	     son(son(son(bro(son(s))))) == stare
1523
	     )			/* Let a := ..; return cont a */
6 7u83 1524
	   )
1525
	)
2 7u83 1526
       {
1527
	  /* +++ integrate this with the block above, otherwise NOTREACHED */
1528
	  /* put tag in result reg if definition is call
1529
	   * of proc, or body ends with return tag,
1530
	   * provided result is not used other wise */
1531
	  FULLCOMMENT1("scan: ident_tag(%d): use result reg", EXP_NUM(stare));
6 7u83 1532
	  props(stare) |= (fxregble)? inreg_bits : infreg_bits;
2 7u83 1533
	  if (fxregble)
1534
	  {
1535
 	     props(stare) |= inreg_bits;
1536
	     bdy.fixneeds++;
1537
	  }
1538
	  else
1539
	  {
1540
 	     props(stare) |= infreg_bits;
1541
	  }
1542
	  bdy.propsneeds |= uses_res_reg_bit;
1543
	  no(stare) = R_USE_RES_REG;	/* identification  uses result reg in body */
1544
	}
1545
	else if (isenvoff(stare)) /* MUST go on stack */
1546
	{
6 7u83 1547
	   no(stare) = R_NO_REG;
2 7u83 1548
	}
1549
	else if (!isvar(*e) && !isparam(*e) &&
6 7u83 1550
		((name(t) == reff_tag && name(son(t)) == cont_tag &&
2 7u83 1551
		   name(son(son(t))) == name_tag && isvar(son(son(son(t))))
1552
		   && !isvis(son(son(son(t)))) && !isglob(son(son(son(t))))
1553
		   && unchanged(son(son(son(t))), stare)
1554
 
1555
	  /*
1556
	   * reff cont variable-not assigned to in scope
1557
	   */
6 7u83 1558
		  ) ||
1559
		 (name(t) == cont_tag && name(son(t)) == name_tag &&
2 7u83 1560
	    isvar(son(son(t))) && !isvis(son(son(t))) && !isglob(son(son(t)))
1561
		   && unchanged(son(son(t)), stare)
1562
 
1563
	  /*
1564
	   * cont variable - not assigned to in scope
1565
	   */
1566
		  )
6 7u83 1567
		 )
1568
	 )
2 7u83 1569
	{
1570
	  FULLCOMMENT1("scan: ident_tag(%d): dont take space for this dec", EXP_NUM(stare));
1571
	  props(stare) |= defer_bit;
1572
	  /* dont take space for this dec */	}
1573
	else if (!isvar(stare) &&
1574
		 ((props(stare) & 0x10 /* forced in const */ ) == 0)
1575
		 && (name(t) == name_tag || name(t) == val_tag))
1576
	{
1577
	  FULLCOMMENT1("scan: ident_tag(%d): dont take space for this dec (#2)", EXP_NUM(stare));
1578
	  props(stare) |= defer_bit;
1579
	  /* dont take space for this dec */
1580
	}
1581
	else if (fxregble && bdy.fixneeds < maxfix &&
6 7u83 1582
		(bdy.propsneeds & morefix) == 0 &&
1583
		((bdy.propsneeds & anyproccall) == 0
1584
		  || tempdec(stare,((bdy.propsneeds & morefix) == 0 &&
2 7u83 1585
				     bdy.fixneeds < maxfix_tregs - 2))))
1586
	{
1587
	  /*
1588
	   * put this tag in some  fixpt t-reg - which will be decided  in
1589
	   * make_code
1590
	   */
1591
	  FULLCOMMENT1("scan: ident_tag(%d): use fixpt t-reg", EXP_NUM(stare));
1592
	  FULLCOMMENT2("	bdy.fixneeds=%d def.fixneeds=%d",
1593
		       bdy.fixneeds, def.fixneeds);
1594
	  props(stare) |= inreg_bits;
1595
	  no(stare) = 0;
1596
	  bdy.fixneeds += 1;
1597
	}
1598
	else if (bdy.floatneeds < maxfloat && (bdy.propsneeds & morefloat) == 0
1599
		 && flregble &&
6 7u83 1600
		((bdy.propsneeds & anyproccall) == 0
1601
		  || tempdec(stare,((bdy.propsneeds & morefloat) == 0 &&
2 7u83 1602
				     bdy.floatneeds < MAXFLOAT_TREGS - 1))))
1603
	{
1604
 
1605
	  /*
1606
	   * put this tag in some  float t-reg - which will be decided  in
1607
	   * make_code
1608
	   */
1609
	  FULLCOMMENT1("scan: ident_tag(%d): use float t-reg", EXP_NUM(stare));
1610
	  props(stare) |= infreg_bits;
1611
	  no(stare) = 0;
1612
	  bdy.floatneeds += 1;
1613
	}
1614
	else
1615
	{
1616
	  FULLCOMMENT1("scan: ident_tag(%d): use stack or saved reg", EXP_NUM(stare));
1617
	  no(stare) = R_NO_REG;
1618
 
1619
	  /*
1620
	   * allocate either on stack or saved reg
1621
	   */
1622
	}
1623
      }
1624
      bdy = maxneeds(bdy, def);
6 7u83 1625
      if ((bdy.propsneeds & usesproccall)!= 0)
2 7u83 1626
      {
1627
	bdy.propsneeds |= hasproccall;
1628
      }
1629
      return bdy;
1630
    }
1631
 
1632
/*********************************************************************
1633
	sequence
1634
 
1635
shape of exp is shape of end of sequence
1636
son is sequence holder, son of this is list of voided statements.
1637
*********************************************************************/
1638
 
1639
  case seq_tag:
1640
    {
1641
      exp *arg = &bro(son(*e));
1642
      needs an;
1643
      exp *stat;
1644
 
1645
      an = scan(arg, &arg);
1646
      stat = &son(son(*e));
1647
 
1648
      arg = stat;
1649
      for (;;)
1650
      {
1651
	needs stneeds;
1652
 
1653
	stneeds = scan(stat, &arg);
1654
	/* initial statements voided */
1655
	an = maxneeds(an, stneeds);
1656
	if (last(*(stat)))
1657
	{
6 7u83 1658
	  if ((an.propsneeds & usesproccall)!= 0)
2 7u83 1659
	  {
1660
	    an.propsneeds |= hasproccall;
1661
	  }
1662
	  return an;
1663
	}
1664
	stat = &bro(*stat);
1665
	arg = stat;
1666
      }
1667
 
1668
    };
1669
 
1670
/********************************************************************
1671
	goto
1672
 
1673
shape is bottom
1674
son is exp for value jumped with
1675
ptr is labelled exp
1676
*********************************************************************/
1677
 
1678
  case trap_tag:
1679
  case goto_tag:
1680
    {
1681
      return zeroneeds;
1682
    };
1683
 
1684
  case ass_tag:
1685
  case assvol_tag:
1686
    {
1687
      exp *lhs = &son(*e);
1688
      exp *rhs = &bro(*lhs);
1689
      needs nr;
1690
      ash a;
1691
 
1692
      nr = scan(rhs, at);
1693
      /* scan source */
1694
 
1695
      a = ashof(sh(*(rhs)));
1696
 
1697
      if (nstare != ass_tag || a.ashsize != a.ashalign || a.ashalign == 1)
1698
      {
1699
	/* struct/union assign */
1700
	if (!(a.ashsize <= 32 && a.ashsize == a.ashalign))
1701
	  nr.fixneeds += 2;	/* memory block copy */
1702
      }
1703
 
1704
      if (name(*(lhs)) == name_tag &&
6 7u83 1705
	 (isvar(son(*(lhs))) &&
1706
	  ((nr.propsneeds & (hasproccall | morefix)) == 0
2 7u83 1707
	    && nr.fixneeds < maxfix
1708
	   )
6 7u83 1709
	  )
2 7u83 1710
	)			/* simple destination */
1711
      {
1712
	return nr;
1713
      }
1714
      else
1715
      {
1716
	needs nl;
1717
	prop prps = (nr.propsneeds & hasproccall) << 1;
1718
 
1719
	nl = scan(lhs, at);
1720
	if (name(*(rhs)) == apply_tag && nstare == ass_tag &&
6 7u83 1721
	   (nl.propsneeds & (uses_res_reg_bit | anyproccall)) == 0)
2 7u83 1722
	{
1723
	  /* source is proc call, so assign result reg directly */
1724
	   /* SKIP */ ;
1725
	}
1726
	else if (nr.fixneeds >= maxfix || prps != 0)
1727
	{
1728
	  /* source and destination regs overlap, so identify source */
1729
	  cca(at, rhs);
1730
	  nl = shapeneeds(sh(*(rhs)));
1731
	  nl.propsneeds |= morefix;
1732
	  nl.propsneeds &= ~(prps >> 1);
1733
	  nl.propsneeds |= prps;
1734
	}
1735
	nr.fixneeds += 1;
1736
	return maxneeds(nl, nr);
1737
      }
1738
    };
1739
 
1740
  case untidy_return_tag:
1741
  case res_tag:
1742
    {
1743
      ash a;
1744
      needs x;
1745
      shape s;
1746
      exp *arg = &son(*e);
1747
      /* exp r,ss,t; */
1748
      s = sh(*(arg));
1749
      a = ashof(s);
1750
      props(*e) = 0;		/* clear possibility of tlrecirsion; may be
1751
				 * set later */
1752
      x = scan(arg, at);
1753
      /* scan result exp ... */
1754
      if (is_floating(name(s)) && a.ashsize <=64)  /* ... floating pt result */
1755
      {
1756
	x.propsneeds |= realresult_bit;
6 7u83 1757
	if (name(s)!= shrealhd)
2 7u83 1758
	{
1759
	  x.propsneeds |= longrealresult_bit;
1760
	}
1761
	FULLCOMMENT("scan res_tag: long real/real result");
1762
      }
1763
      else
1764
      {
1765
	if (!valregable(s) && !(name(son(*e)) == top_tag)) /* .... result does not fit into reg */
1766
	{
1767
	  x.propsneeds |= long_result_bit;
1768
	FULLCOMMENT("scan res_tag: struct/union result");
1769
	}
1770
      }
1771
 
1772
      FULLCOMMENT1("scan res_tag: result size %d", a.ashsize);
1773
      if (a.ashsize != 0 && name(*arg) != clear_tag)  /* not a void result */
1774
      {
1775
	x.propsneeds|= has_result_bit;
1776
      }
1777
 
1778
      return x;
1779
    };
1780
 
1781
 
1782
    /* spec 3.1 procedure stuff */
1783
 
1784
    case apply_general_tag: {
1785
	exp application = *(e);
6 7u83 1786
	exp *fn = &son(application);
2 7u83 1787
	exp cers = bro(*fn);
1788
	exp *cerl = &son(cers);
1789
	long stpar = 0;
6 7u83 1790
 
2 7u83 1791
	needs nds;
1792
	needs plnds;
1793
	int i;
1794
 
1795
	gen_call = 1;
6 7u83 1796
 
2 7u83 1797
	nds = scan(fn, at);
6 7u83 1798
	if ((nds.propsneeds & hasproccall)!= 0) {
2 7u83 1799
				/* .... it must be identified */
6 7u83 1800
	  cca(at, fn);
2 7u83 1801
	  nds.propsneeds &= ~hasproccall;
1802
	  nds.propsneeds |= usesproccall;
1803
	  fn = &son(application);
1804
	}
6 7u83 1805
 
1806
	for (i=0; i<no(cers); i++) {
2 7u83 1807
		needs onepar;
1808
		shape shonepar = sh(*cerl);
6 7u83 1809
		exp * par = (name(*cerl) ==caller_tag)?&son(*cerl):cerl;
1810
		int n = rounder(stpar, shape_align(shonepar));
2 7u83 1811
		onepar = scan(par,at);
6 7u83 1812
	    	if ((i != 0 && (onepar.propsneeds & hasproccall)!= 0) ||
1813
	  		onepar.fixneeds+ (stpar>>5) > maxfix) {
2 7u83 1814
				/* if it isn't the first parameter, and it
1815
				   calls a proc, identify it */
6 7u83 1816
	    	  cca(at, par);
2 7u83 1817
	    	  nds.propsneeds |= usesproccall;
6 7u83 1818
	    	  nds = maxneeds(shapeneeds(sh(*(par))), nds);
2 7u83 1819
	    	  nds.maxargs = MAX_OF(nds.maxargs, onepar.maxargs);
1820
	  	}
1821
	  	else {
6 7u83 1822
	  	  nds = maxneeds(onepar, nds);
2 7u83 1823
	  	}
6 7u83 1824
	  	if (name(*cerl) ==caller_tag) { no(*cerl) = n; };
2 7u83 1825
	  	n = n + shape_size(shonepar);
1826
	  	stpar = rounder(n,32);
1827
	  	cerl = &bro(*cerl);
1828
	}
1829
	nds.maxargs = MAX_OF(nds.maxargs, stpar);
1830
	nds = maxneeds(scan(&bro(bro(son(application))), at), nds);
6 7u83 1831
 
2 7u83 1832
	plnds = scan(&bro(bro(bro(son(application)))), at);
6 7u83 1833
 
1834
 
1835
 
1836
 
1837
	if ((plnds.propsneeds & (anyproccall | uses2_bit))!= 0) {
2 7u83 1838
		props(application) = 1;
1839
		if (is_floating(name(sh(application))) || valregable(sh(application))) {
1840
			cca(at, ptr_position(application));
1841
			plnds.propsneeds |= usesproccall;
1842
		}
1843
	}
1844
	else { props(application) = 0; }
6 7u83 1845
 
2 7u83 1846
	nds = maxneeds(nds, plnds);
1847
	nds.propsneeds |= hasproccall;
1848
	return nds;
1849
	}
6 7u83 1850
 
2 7u83 1851
   case make_callee_list_tag: {
1852
   	exp cees = *e;
1853
	exp * par = &son(cees);
1854
	needs nds;
1855
	long stpar = 0;
1856
	int i;
1857
	nds = zeroneeds;
6 7u83 1858
	for (i=0; i<no(cees); i++) {
2 7u83 1859
		needs onepar;
1860
		shape shonepar = sh(*par);
6 7u83 1861
		int n = rounder(stpar, shape_align(shonepar));
2 7u83 1862
		onepar = scan(par,at);
6 7u83 1863
	    	if (((onepar.propsneeds & hasproccall)!= 0) ||
2 7u83 1864
	  		onepar.fixneeds+1 > maxfix) {
1865
				/* if it calls a proc, identify it */
6 7u83 1866
	    	   cca(at, par);
2 7u83 1867
	    	   nds.propsneeds |= usesproccall;
6 7u83 1868
	    	   nds = maxneeds(shapeneeds(sh(*(par))), nds);
2 7u83 1869
	    	   nds.maxargs = MAX_OF(nds.maxargs, onepar.maxargs);
1870
	  	}
1871
	  	else {
6 7u83 1872
	  	  nds = maxneeds(onepar, nds);
2 7u83 1873
	  	}
1874
	  	n = n + shape_size(shonepar);
1875
	  	stpar = rounder(n,32);
1876
	  	par = &bro(*par);
1877
	  }
1878
	no(cees) = stpar;
1879
	return nds;
1880
   }
1881
   case make_dynamic_callee_tag: {
1882
	exp cees = *e;
1883
	exp *ptr = &son(cees);
1884
	needs ndsp;
1885
	needs nds;
1886
	nds = zeroneeds;
1887
	ndsp = scan(ptr, at);
6 7u83 1888
	if (((ndsp.propsneeds & hasproccall)!= 0) ||
2 7u83 1889
	  		ndsp.fixneeds+1 > maxfix) {
6 7u83 1890
	    	 cca(at, ptr);
2 7u83 1891
	    	 nds.propsneeds |= usesproccall;
6 7u83 1892
	    	 nds = maxneeds(shapeneeds(sh(*(ptr))), nds);
2 7u83 1893
	    	 nds.maxargs =  MAX_OF(nds.maxargs, ndsp.maxargs);
1894
	}
1895
	else {
1896
	  	nds = ndsp;
1897
	}
1898
	ndsp = scan(&bro(son(*e)), at);
6 7u83 1899
	if (((ndsp.propsneeds & hasproccall)!= 0) ||
2 7u83 1900
	  		ndsp.fixneeds+2 > maxfix) {
6 7u83 1901
	    	 cca(at, &bro(son(cees)));
2 7u83 1902
	    	 nds.propsneeds |= usesproccall;
6 7u83 1903
	    	 nds = maxneeds(shapeneeds(sh(bro(son(*e)))), nds);
2 7u83 1904
	    	 nds.maxargs = MAX_OF(nds.maxargs, ndsp.maxargs);
1905
	}
1906
	else {
6 7u83 1907
	  	nds = maxneeds(ndsp, nds);
2 7u83 1908
	}
6 7u83 1909
	if (nds.fixneeds<5)nds.fixneeds = 5;
2 7u83 1910
	return nds;
1911
    }
6 7u83 1912
 
2 7u83 1913
    case same_callees_tag: {
1914
    	needs nds;
1915
    	nds = zeroneeds;
1916
    	nds.fixneeds = 4;
1917
    	return nds;
1918
    }
6 7u83 1919
 
2 7u83 1920
    case tail_call_tag: {
1921
	needs ndsp;
1922
	needs nds;
1923
	exp *fn = &son(*e);
1924
	ndsp =  scan(fn, at);
6 7u83 1925
	if (((ndsp.propsneeds & hasproccall)!= 0) ||
2 7u83 1926
	  		ndsp.fixneeds+1 > maxfix) {
6 7u83 1927
	    	 cca(at, fn);
2 7u83 1928
	    	 nds.propsneeds |= usesproccall;
6 7u83 1929
	    	 nds = maxneeds(shapeneeds(sh(*(fn))), nds);
2 7u83 1930
	    	 nds.maxargs =  MAX_OF(nds.maxargs, ndsp.maxargs);
1931
	}
1932
	else {
1933
	  	nds = ndsp;
1934
	}
1935
	gen_call = 1;
1936
	has_tail_call = 1;
1937
 
1938
	ndsp = scan(&bro(son(*e)), at);
1939
	nds = maxneeds(nds, ndsp);
1940
	return nds;
1941
   }
6 7u83 1942
 
1943
 
2 7u83 1944
   case env_size_tag:
1945
    {
1946
      exp *arg = &son(*e);
1947
      return scan(arg,at);
1948
    }
1949
 
1950
 
1951
  case apply_tag:
1952
    {
1953
      exp application = *(e);
1954
      exp fn = son(application);
1955
      exp *par = &bro(fn);
1956
      exp *fnexp = &son(*e);
1957
      int parsize = 0;
1958
      needs nds;
1959
      bool tlrecpos = nonevis && callerfortr && (rscope_level == 0);
1960
      int i;
6 7u83 1961
      bool notinreg = !(
2 7u83 1962
#if use_long_double
6 7u83 1963
			 name(sh(application)) ==shrealhd    ||
1964
			 name(sh(application)) ==realhd      ||
2 7u83 1965
#else
1966
			 is_floating(name(sh(application))) ||
6 7u83 1967
#endif
1968
			 valregable(sh(application)));
2 7u83 1969
 
1970
      bool long_result_space_needed = notinreg && !(name(sh(*e)) == tophd);
1971
 
1972
      nds = scan(fnexp, at);
1973
      /* scan the function exp ... */
6 7u83 1974
      if ((nds.propsneeds & hasproccall)!= 0)
2 7u83 1975
      {
1976
	/* .... it must be identified */
1977
	cca(at, fnexp);
1978
	nds.propsneeds &= ~hasproccall;
1979
	nds.propsneeds |= usesproccall;
1980
	fn = son(application);
1981
	par = &bro(fn);
1982
      }
1983
 
6 7u83 1984
      if (name(fn)!= name_tag ||
1985
	 (son(son(fn))!= nilexp && name(son(son(fn)))!= proc_tag))
2 7u83 1986
      {
1987
	tlrecpos = 0;
1988
      }
1989
 
1990
      for (i = 1; !last(fn); ++i)
1991
      {				/* scan parameters in turn ... */
1992
	needs onepar;
1993
	shape shpar = sh(*par);
1994
 
1995
	onepar = scan(par, at);
1996
 
6 7u83 1997
	if ((i != 1 && (onepar.propsneeds & hasproccall)!= 0) ||
2 7u83 1998
	    onepar.fixneeds + (parsize >> 5) > maxfix)
1999
	{
2000
 
2001
	  /*
2002
	   * if it isn't the first parameter, and it calls a proc, identify it
2003
	   */
2004
	  FULLCOMMENT1("apply_tag: identifying parameter %d (1..) containing proc call",i);
2005
	  cca(at, par);
2006
	  nds.propsneeds |= usesproccall;
2007
	  nds = maxneeds(shapeneeds(sh(*(par))), nds);
2008
	  nds.maxargs = MAX_OF(nds.maxargs, onepar.maxargs);
2009
	}
2010
	else
2011
	{
2012
	  nds = maxneeds(onepar, nds);
2013
	}
2014
 
2015
	parsize = rounder(parsize + shape_size(shpar), 32);
2016
	/* round up bytes and halfwords */
2017
 
6 7u83 2018
	parsize = rounder(parsize, shape_align(shpar));
2 7u83 2019
	/* parameters must be properly aligned on the stack */
2020
 
2021
	if ((!valregable(shpar) && !is_floating(name(shpar))) || parsize > 128)
2022
	{
2023
	  tlrecpos = 0;
2024
	}
2025
	if (last(*(par)))
2026
	{
2027
	  break;
2028
	};
2029
	par = &bro(*par);
2030
      }
2031
 
2032
      if (specialopt(fn))
2033
	nds.propsneeds |= dont_optimise; /* eg vfork */
6 7u83 2034
 
2 7u83 2035
      if ((i = specialfn(fn)) > 0)
2036
      {				/* eg strlen */
2037
#if 0
2038
	nds = maxneeds(specialneeds(i), nds);
2039
#endif
2040
	assert("specialfn - specialneeds");
2041
	return nds;
2042
      }
2043
      else if (i == -1)
2044
      {				/* call of strcpy .... */
6 7u83 2045
#if 0
2 7u83 2046
	exp par2 = *(par);
2047
 
2048
	/*
2049
	 * TEST for constant string????????????????? if (name (par2) ==
2050
	 * eval_tag && name (son (par2)) == pack_tag && name (son (son
2051
	 * (par2))) == string_tag) {
2052
	 *
2053
	 * setname (* (e), ass_tag); son (* (e)) = * (parlist); son (par2) = son
2054
	 * (son (par2)); sh (par2) = sh (son (par2)); bro (par2) = * (e) ;
2055
	 * bro(son(par2)) = par2;	return maxneeds (nds, twofix); }
2056
	 */
2057
#endif
2058
      }
2059
 
2060
      if (tlrecpos)
2061
      {
2062
	exp dad = father(application);
2063
 
2064
	if (name(dad) == res_tag)
2065
	{
2066
	  props(dad) = 1;	/* do a tl recursion */
2067
	}
2068
      }
2069
 
2070
      if (long_result_space_needed)
2071
      {
2072
	/* find space for tuple result */
2073
	FULLCOMMENT("apply_tag: identifying notinreg result");
6 7u83 2074
	assert(name(*(ptr_position(application))) ==apply_tag);
2075
	cca(at,ptr_position(application));
2 7u83 2076
	nds.propsneeds |= usesproccall;
2077
      }
2078
      else
2079
      {
2080
	nds.propsneeds |= hasproccall;
2081
      }
2082
      nds.maxargs = MAX_OF(nds.maxargs, parsize);
2083
      nds.fixneeds = MAX_OF(nds.fixneeds, 7); /* clobber %o0..%o5,%07 */
2084
      return nds;
2085
 
2086
    }
2087
 
2088
  case val_tag:
2089
    {
2090
      exp s = sh(*e);
2091
      if (name(s) == offsethd && al2(s) >= 8)
2092
      {
2093
	/* express disps in bytes */
2094
	no(*e) = no(*e) >> 3;
2095
      }
2096
      FULLCOMMENT2("val_tag %s no=%d", SH_NAME(name(s)), no(*e));
2097
      /* ... and continue */
2098
    }
2099
 
2100
  case name_tag:
2101
  case null_tag:
2102
  case real_tag:
2103
  case string_tag:
6 7u83 2104
  case env_offset_tag: case general_env_offset_tag:
2 7u83 2105
  case current_env_tag:
2106
  case make_lv_tag:
2107
  case last_local_tag:
2108
  case caller_name_tag:
2109
  case give_stack_limit_tag:
2110
/*  case next_frame_tag:  */
2111
    {
2112
       if (nstare==last_local_tag)
2113
	  cpr->Has_ll = 1;
2114
       return shapeneeds(sh(*(e)));
2115
    };
2116
 
2117
  case clear_tag:
2118
  case top_tag:
2119
  case local_free_all_tag:
2120
  case prof_tag:
2121
  case formal_callee_tag:
2122
    {
2123
      return zeroneeds;
2124
    };
2125
 
2126
#if 0
2127
  case rscope_tag:
2128
    {
2129
      needs sn;
2130
      exp *s = &son(*e);
2131
      exp lst;
2132
 
2133
      rscope_level++;
2134
#if 0 /* only needed when (do_tlrecursion!=0) */
2135
      (void) last_statement(son(*e), &lst);	/* always true */
2136
      if (name(lst) == res_tag)
2137
      {
2138
	/* can remove res */
2139
	exp *pos = ptr_position(lst);
2140
	exp t;
2141
 
2142
	bro(son(lst)) = bro(lst);
2143
	if (last(lst))
2144
	{
2145
	  setlast(son(lst));
2146
	}
2147
	else
2148
	{
2149
	  clearlast(son(lst));
2150
	}
2151
	*pos = son(lst);
2152
	for (t = father(*pos); name(sh(t)) == bothd; t = father(t))
2153
	{
2154
	  sh(t) = sh(*pos);	/* adjust ancestors to correct shape */
2155
	}
2156
      }
2157
#endif
2158
      sn = scan(s, &s);
2159
      rscope_level--;
2160
      return sn;
2161
    };
2162
#endif
2163
 
2164
 
2165
  case set_stack_limit_tag:
2166
  case abs_tag:
2167
  case neg_tag:
2168
  case case_tag:
2169
  case not_tag:
2170
  case goto_lv_tag: /* for COBOL */
2171
  case offset_negate_tag:
2172
  case diagnose_tag:
2173
  case local_free_tag:
2174
#if 1
2175
  case return_to_label_tag:
2176
#endif
2177
    {
2178
      exp *arg = &son(*e);
2179
      return scan(arg, at);
2180
    };
2181
 
6 7u83 2182
    case fneg_tag: case fabs_tag:
2 7u83 2183
    case chfl_tag:
2184
    {
2185
      needs nds;
2186
      exp *pste;
6 7u83 2187
      nds = scan(&son(*e), at);
2 7u83 2188
      pste = ptr_position(ste);
6 7u83 2189
      if (!optop(*pste) && nds.fixneeds <2)nds.fixneeds = 2;
2 7u83 2190
#if use_long_double
2191
	    {
6 7u83 2192
	      exp op = *pste;
2193
	      if (name(sh(op)) == doublehd ||
2194
		  name(sh(son(op))) == doublehd) {
2195
		if (!is_o(name(son(op))) ||
2196
		    pntst(nds, hasproccall)) {
2197
		  cca(at, &son(op));
2 7u83 2198
		}
6 7u83 2199
		pnset(nds, hasproccall);
2 7u83 2200
	      }
2201
	    }
2202
#endif
2203
      return nds;
6 7u83 2204
    }
2 7u83 2205
 
2206
  case bitf_to_int_tag:
2207
    {
2208
      exp *arg = &son(*e);
2209
      needs nds;
2210
      exp stararg;
2211
      exp stare;
2212
      int sizeb;
2213
 
2214
      nds = scan(arg, at);
2215
      stararg = *(arg);
2216
      stare = *(e);
2217
      sizeb = ashof(sh(stararg)).ashsize;
2218
      if ((name(stararg) == name_tag &&
6 7u83 2219
	  ((sizeb == 8 && (no(stararg) & 7) == 0)
2 7u83 2220
	    || (sizeb == 16 && (no(stararg) & 15) == 0)
2221
	    || (sizeb == 32 && (no(stararg) & 31) == 0)
6 7u83 2222
	   )
2223
	  ) || (name(stararg) == cont_tag &&
2224
	 ((name(son(stararg))!= name_tag && name(son(stararg))!= reff_tag)
2 7u83 2225
	   || (sizeb == 8 && (no(son(stararg)) & 7) == 0)
2226
	   || (sizeb == 16 && (no(son(stararg)) & 15) == 0)
2227
	   || (sizeb == 32 && (no(son(stararg)) & 31) == 0)
6 7u83 2228
	  )
2229
		)
2 7u83 2230
	)
2231
 
2232
	/*
2233
	 * these bitsint(trimnof(X)) could be implemented by lb or lh
2234
	 * instructions ...
2235
	 */
2236
      {
2237
	int sgned = is_signed(sh(stare));
6 7u83 2238
	shape ns = (sizeb == 8)?((sgned)? scharsh : ucharsh)
2239
	:(sizeb == 16)?((sgned)? swordsh : uwordsh)
2 7u83 2240
	: sh(stare);
2241
 
2242
	/* can use short loads instead of bits extractions */
2243
	if (name(stararg) == cont_tag)
2244
	{
2245
	  /* make the ptr shape consistent */
2246
	  sh(son(stararg)) = f_pointer(long_to_al(shape_align(ns)));
2247
	}
2248
	sh(stararg) = ns;
2249
	setname(stare, chvar_tag);
2250
      }
2251
      return nds;
2252
    }
2253
 
2254
 
2255
  case int_to_bitf_tag:
2256
    {
2257
      exp *arg = &son(*e);
2258
      return scan(arg, at);
2259
    }
2260
 
2261
  case round_tag:
2262
    {
2263
      needs s;
2264
      exp *arg;
2265
      exp *pste;
6 7u83 2266
      int rm = (int)round_number(*e);
2267
      arg = &son(*e);
2 7u83 2268
      s = scan(arg,at);
2269
      pste = ptr_position(ste);
2270
      s.fixneeds = MAX_OF(s.fixneeds,2);
6 7u83 2271
      if (rm < 3 || name(sh(*pste)) == ulonghd)
2 7u83 2272
      {
6 7u83 2273
	 s.floatneeds = MAX_OF(s.floatneeds, 3);
2 7u83 2274
      }
2275
      else
2276
      {
6 7u83 2277
	 s.floatneeds = MAX_OF(s.floatneeds, 2);
2 7u83 2278
      }
2279
#if use_long_double
2280
      {
6 7u83 2281
	 exp op = *pste;
2282
	 if (name(sh(son(op))) == doublehd)
2 7u83 2283
	 {
6 7u83 2284
	    if (!is_o(name(son(op))) ||
2285
		    pntst(s, hasproccall))
2 7u83 2286
	    {
6 7u83 2287
	       cca(at, &son(op));
2 7u83 2288
	    }
6 7u83 2289
	    pnset(s, hasproccall);
2 7u83 2290
	 }
2291
      }
2292
#endif
2293
      return s;
2294
    };
2295
 
2296
  case shl_tag:
2297
  case shr_tag:
2298
  case long_jump_tag:
2299
    {
2300
      exp *lhs = &son(*e);
2301
      exp *rhs = &bro(*lhs);
2302
      needs nl, nr;
2303
      prop prps;
6 7u83 2304
      if (name(*rhs) ==val_tag)
2 7u83 2305
      {
6 7u83 2306
	 return scan(lhs, at);
2 7u83 2307
      }
2308
      nr = scan(rhs, at);
2309
      nl = scan(lhs, at);
2310
      rhs = &bro(*lhs);
2311
      prps = (nr.propsneeds & hasproccall) << 1;
2312
      if (nr.fixneeds >= maxfix || prps != 0)
2313
	/* if reg requirements overlap, identify second operand */
2314
      {
2315
	cca(at, rhs);
2316
	nl = shapeneeds(sh(*(rhs)));
2317
	nl.propsneeds |= morefix;
2318
	nl.propsneeds &= ~(prps >> 1);
2319
	nl.propsneeds |= prps;
2320
      }
2321
      nr.fixneeds += 1;
2322
      return maxneeds(nl, nr);
2323
    };
2324
 
2325
 
2326
  case test_tag:
2327
    {
2328
      exp stare = *(e);
2329
      exp l = son(stare);
2330
      exp r = bro(l);
2331
 
2332
      if (!last(stare) && name(bro(stare)) == test_tag &&
2333
	  no(stare) == no(bro(stare)) &&
2334
	  test_number(stare) == test_number(bro(stare)) &&
2335
	  eq_exp(l, son(bro(stare))) && eq_exp(r, bro(son(bro(stare))))
2336
	)
2337
      {				/* same test following in seq list - remove
2338
				 * second test */
2339
	if (last(bro(stare)))
2340
	  setlast(stare);
2341
	bro(stare) = bro(bro(stare));
2342
      }
2343
 
2344
      if (last(stare) && name(bro(stare)) == 0	/* seq holder */
2345
	  && name(bro(bro(stare))) == test_tag &&
2346
	  name(bro(bro(bro(stare)))) == seq_tag &&
2347
	  no(stare) == no(bro(bro(stare))) &&
2348
	  test_number(stare) == test_number(bro(bro(stare))) &&
2349
	  eq_exp(l, son(bro(bro(stare))))
2350
	  && eq_exp(r, bro(son(bro(bro(stare)))))
2351
	)
2352
      {				/* same test following in seq res - void
2353
				 * second test */
2354
	setname(bro(bro(stare)), top_tag);
2355
	son(bro(bro(stare))) = nilexp;
2356
	pt(bro(bro(stare))) = nilexp;
2357
      }
2358
 
2359
      if (name(l) == val_tag && (props(stare) == 5 || props(stare) == 6))
2360
      {
2361
	/* commute  const = x */
2362
	bro(l) = stare;
2363
	setlast(l);
2364
	bro(r) = l;
2365
	clearlast(r);
2366
	son(stare) = r;
2367
	r = l;
2368
	l = son(stare);
2369
      }
2370
 
2371
      if (name(l) == bitf_to_int_tag && name(r) == val_tag &&
6 7u83 2372
	 (props(stare) == 5 || props(stare) == 6) &&
2373
	 (name(son(l)) == cont_tag || name(son(l)) == name_tag))
2 7u83 2374
      {				/* equality of bits against +ve consts doesnt
2375
				 * need sign adjustment */
2376
	long n = no(r);
2377
 
2378
	switch (name(sh(l)))
2379
	{
2380
	case scharhd:
2381
	  {
2382
	    if (n >= 0 && n <= 127)
2383
	    {
2384
	      sh(l) = ucharsh;
2385
	    } break;
2386
	  }
2387
	case swordhd:
2388
	  {
2389
	    if (n >= 0 && n <= 0xffff)
2390
	    {
2391
	      sh(l) = uwordsh;
2392
	    } break;
2393
	  }
2394
 
2395
	default:;
2396
	}
2397
      }
2398
      else if (is_floating(name(sh(l))))
2399
      {
2400
	return fpop(e, at);
2401
      }
2402
      else if (name(r) == val_tag && no(r) == 1
2403
	       && (props(stare) == 3 || props(stare) == 2))
2404
      {
2405
	no(r) = 0;
2406
	if (props(stare) == 3)
2407
	{
2408
	  props(stare) = 4;	/* branch >=1 -> branch > 0 */
2409
	}
2410
	else
2411
	{
2412
	  props(stare) = 1;	/* branch <1 -> branch <= 0 */
2413
	}
2414
      }
2415
      return likediv(e, at);
2416
    }
2417
 
2418
 
2419
  case plus_tag:
2420
    {
2421
      /* replace any operands which are neg(..) by -, if poss */
2422
      exp sum = *(e);
2423
      exp list = son(sum);
2424
      bool someneg = 0;
2425
      bool allneg = 1;
2426
 
2427
      for (; optop(sum);)
2428
      {
2429
	if (name(list) == neg_tag)
2430
	  someneg = 1;
2431
	else
2432
	  allneg = 0;
2433
	if (last(list))
2434
	  break;
2435
	list = bro(list);
2436
      }
2437
 
2438
      FULLCOMMENT2("scan case plus_tag,addptr_tag: allneg=%d someneg=%d", allneg, someneg);
2439
 
2440
      if (someneg)
2441
      {
2442
	/* there are some neg() operands */
2443
	if (allneg)
2444
	{
2445
	  /* transform -..-... to -(..+.. +...) */
2446
	  exp x;
2447
 
2448
	  /*
2449
	   * Build a new list form operand of neg_tags, which will
2450
	   * become plus_tag operands.
2451
	   */
2452
	  x = son(sum);
2453
	  list = son(x);
2454
	  for (;;)
2455
	  {
2456
	    /*
2457
	     * 'x' moves along neg_tag's lists
2458
	     * 'list' moves along sons of neg_tag's lists, building a new list
2459
	     * eventually new list is made son of plus_tag
2460
	     */
2461
 
2462
	    bro(list) = son(bro(x));
2463
	    if (!last(x))
2464
	    {
2465
	      clearlast(list);
2466
	      list = bro(list);
2467
	      x = bro(x);
2468
	    }
2469
	    else
2470
	    {
2471
	      setlast(list);
2472
	      bro(list) = sum;		/* set father to be */
2473
	      son(sum) = son(son(sum)); /* set new sons of plus_tag */
2474
	      break;
2475
	    }
2476
	  }
2477
 
2478
	  /*
2479
	   * create new neg_tag to replace plus_tag,
2480
	   * old plus_tag being the operand of the new neg_tag.
2481
	   */
2482
	  x = getexp(sh(sum), bro(sum), last(sum), sum, nilexp,
2483
		     0, 0, neg_tag);
2484
 
2485
	  setlast(sum);
2486
 
2487
	  /* set father of sum, new neg_tag exp */
2488
	  bro(sum) = x;
2489
 
2490
	  *(e) = x;
2491
	}			/* end allneg */
2492
	else
2493
	{
2494
	  /* transform to  ((..(..+..) - ..) -..) */
2495
	  int n = 0;
2496
	  exp brosum = bro(sum);
2497
	  bool lastsum = last(sum);
2498
	  exp x = son(sum);
2499
	  exp newsum = sum;
2500
 
2501
	  list = nilexp;
2502
	  for (;;)
2503
	  {
2504
	    exp nxt = bro(x);
2505
	    bool final = last(x);
2506
 
2507
	    if (name(x) == neg_tag)
2508
	    {
2509
	      bro(son(x)) = list;
2510
	      list = son(x);
2511
	    }
2512
	    else
2513
	    {
2514
	      bro(x) = newsum;
2515
	      newsum = x;
2516
	      if ((n++) == 0)
2517
		setlast(newsum);
2518
	      else
2519
		clearlast(newsum);
2520
	    }
2521
	    if (final)
2522
	      break;
2523
	    x = nxt;
2524
	  }
2525
 
2526
	  if (n > 1)
2527
	  {
2528
	    son(sum) = newsum;
2529
	    newsum = sum;	/* use existing exp for add operations */
2530
	  }
2531
	  for (;;)
2532
	  {			/* introduce - operations */
2533
	    exp nxt = bro(list);
2534
 
2535
	    bro(newsum) = list;
2536
	    clearlast(newsum);
2537
	    x = getexp(sh(sum), nilexp, 0, newsum, nilexp, 0, 0, minus_tag);
2538
 
2539
	    bro(list) = x;
2540
	    setlast(list);
2541
	    newsum = x;
2542
	    if ((list = nxt) == nilexp)
2543
	      break;
2544
	  }
2545
	  bro(newsum) = brosum;
2546
	  if (lastsum)
2547
	  {
2548
	    setlast(newsum);
2549
	  }
2550
	  else
2551
	  {
2552
	    clearlast(newsum);
2553
	  }
2554
	  *(e) = newsum;
2555
 
2556
	}			/* end else allneg */
2557
 
2558
	return scan(e, at);
2559
 
2560
      }				/* end someneg - else continue to next case */
2561
    }
2562
    /* FALLTHROUGH */
2563
 
6 7u83 2564
 
2 7u83 2565
  case and_tag:
2566
  case or_tag:
2567
  case xor_tag:
2568
    {
2569
      return likeplus(e, at);
2570
    };
2571
 
6 7u83 2572
  case addptr_tag:
2 7u83 2573
    {
2574
    	exp p = son(*e);
2575
    	exp d = bro(p);
6 7u83 2576
    	int fal = frame_al_of_ptr(sh(p));
2577
    	if (fal!=0) {
2 7u83 2578
    		int oal = frame_al1_of_offset(sh(d));
2579
#if 0
6 7u83 2580
    		if (((oal-1) &oal)!= 0) {
2 7u83 2581
    			failer("can't cope with mixed frame offsets yet");
2582
    		}
2583
#endif
6 7u83 2584
    		if (includes_vcallees(fal) && ((oal & 20)!= 0)) {
2 7u83 2585
    			/* oal = callees and callers are offset relative to
2586
			   FP when there are variable callees */
2587
    		   exp ne = getexp(sh(p), d, 0, p, nilexp, 0, 0,
2588
    		   		locptr_tag);
2589
    		   bro(p) = ne; setlast(p);
2590
    		   son(*e) = ne;
2591
    		}
2592
    	}
6 7u83 2593
    	/* ... and continue */
2 7u83 2594
    }
2595
 
2596
  case minus_tag:
2597
  case subptr_tag:
2598
  case minptr_tag:
2599
    {
2600
      return likediv(e, at);
2601
    };
2602
 
2603
  case reff_tag:
2604
  case float_tag:
2605
  case offset_pad_tag:
6 7u83 2606
  case locptr_tag:
2 7u83 2607
  case chvar_tag:
2608
    {
2609
      exp *arg = &son(*e);
2610
      exp *pste;
2611
      needs nds;
2612
      nds = shapeneeds(sh(*e));
2613
      nds = maxneeds(scan(arg, at), nds);
2614
      pste = ptr_position(ste);
2615
#if use_long_double
2616
	    {
6 7u83 2617
	      exp op = *pste;
2618
	      if (name(sh(op)) ==doublehd)
2 7u83 2619
	      {
6 7u83 2620
		 pnset(nds, hasproccall);
2 7u83 2621
	      }
2622
	    }
2623
#endif
6 7u83 2624
      return(nds);
2 7u83 2625
    };
2626
 
2627
  case cont_tag:
2628
  case contvol_tag:
2629
  {
2630
    exp *arg = &son(*e);
2631
    needs nds;
6 7u83 2632
 
2 7u83 2633
    nds = maxneeds(scan(arg, at), shapeneeds(sh(*(e))));
2634
    nds.fixneeds = MAX_OF(nds.fixneeds, 2);
2635
    return nds;
2636
  };
6 7u83 2637
 
2 7u83 2638
  mult_tag_case:
2639
  case mult_tag:
2640
  {
2641
    return multneeds(e, at);
2642
  };
2643
 
2644
  case offset_mult_tag:
2645
  case offset_div_tag:
2646
  {
6 7u83 2647
	    exp op2 = bro(son(*e));
2648
	    shape s = sh(op2);
2 7u83 2649
 
6 7u83 2650
	    if (name(op2) == val_tag && no(op2) == 8 &&
2651
		 name(s) == offsethd && al2(s) >= 8) {
2 7u83 2652
		/* offset is one byte */
6 7u83 2653
		exp op1 = son(*e);
2654
		bro(op1) = bro(*e);
2655
		if (last(*e)) {
2656
		    setlast(op1);
2 7u83 2657
		} else {
6 7u83 2658
		    clearlast(op1);
2 7u83 2659
		}
6 7u83 2660
		*e = op1;
2661
		return(scan(e, at));
2 7u83 2662
	    }
6 7u83 2663
	    if (nstare == offset_mult_tag)goto mult_tag_case;
2 7u83 2664
	    /* FALL THROUGH */
2665
	}
2666
 
2667
#if 0
2668
  case offset_div_tag:
2669
  {
2670
     exp op1 = son(*e);
2671
     exp op2 = bro(op1);
2672
     shape s = sh(op2);
6 7u83 2673
     if (name(op2) ==val_tag  && name(s) ==offsethd
2 7u83 2674
	 && al2(s) >= 8) {
6 7u83 2675
       int n = no(op2) /8;
2 7u83 2676
       if (n == 1) {
2677
	 /* offset is one  byte */
2678
	 bro(op1) = bro(*e);
2679
	 if (last(*e)) { setlast(op1); } else {clearlast(op1); }
2680
	 *e = op1;
6 7u83 2681
	 return(scan(e, at));
2 7u83 2682
       }
6 7u83 2683
       else
2684
	 if (name(*e) == offset_mult_tag && n > 1 && (n& (n-1)) == 0)
2685
	   if (name(op1) == and_tag
2686
	      && name(son(op1)) == shr_tag &&
2687
	      name(bro(son(op1))) ==val_tag) {
2 7u83 2688
	     exp shexp = son(op1);
2689
	     exp ac = bro(shexp);
2690
	     exp shop1 = son(shexp);
2691
	     exp shop2 = bro(shop1);
2692
	     int na = no(ac);
6 7u83 2693
	     if ((na& (na+1)) ==0 && name(shop2) ==val_tag) {
2 7u83 2694
	       int pn = 0;
2695
	       int ns = no(shop2);
2696
	       int i = n;
2697
	       while (i>1) { i >>= 1; pn++; }
6 7u83 2698
 
2699
	       if (ns > pn)
2 7u83 2700
	       {
2701
		 /* can do transform:
2702
		    (((shop1>>ns) & na) * n) =>
2703
		    shop1>>(ns-pn) & (na*n)
2704
		      */
2705
		 no(shop2) = ns-pn;
2706
		 no(ac) = na*n;
2707
		 bro(op1) = bro(*e);
6 7u83 2708
		 if (last(*e))
2 7u83 2709
		 {
6 7u83 2710
		   setlast(op1);
2711
		 }
2712
		 else
2 7u83 2713
		 {
2714
		   clearlast(op1);
6 7u83 2715
		 }
2 7u83 2716
		 *e = op1;
6 7u83 2717
		 return(scan(e, at));
2 7u83 2718
	       }
2719
	     }
2720
	   }
6 7u83 2721
	   else
2722
	   {
2 7u83 2723
	     /* will do this by literal shift */
2724
	     no(op2) = n;
2725
	     return scan(&son(*e), at);
6 7u83 2726
	   }
2 7u83 2727
     }
6 7u83 2728
     if (nstare == offset_mult_tag)goto mult_tag_case;
2 7u83 2729
   }
2730
#endif
2731
 
2732
    case div0_tag:
6 7u83 2733
    case div2_tag:
2734
    case offset_div_by_int_tag:
2 7u83 2735
    {
6 7u83 2736
	return(divneeds(e, at));
2 7u83 2737
    }
2738
 
2739
    case offset_add_tag:
2740
    {
6 7u83 2741
	  if ((al2(sh(son(*e))) == 1) && (al2(sh(bro(son(*e))))!= 1)) {
2 7u83 2742
	    make_bitfield_offset(bro(son(*e)),son(*e),0,sh(*e));
2743
	  }
6 7u83 2744
	  if ((al2(sh(son(*e)))!= 1) && (al2(sh(bro(son(*e)))) == 1)) {
2 7u83 2745
	    make_bitfield_offset(son(*e),*e,1,sh(*e));
2746
	  }
2747
    }
6 7u83 2748
    case offset_subtract_tag:
2749
    case component_tag:
2 7u83 2750
    {
6 7u83 2751
	return(likediv(e, at));
2 7u83 2752
    }
2753
 
6 7u83 2754
    case make_stack_limit_tag:
2 7u83 2755
	{ needs nd;
2756
	  nd = likediv(e, at);
2757
	  nd.fixneeds = MAX_OF(nd.fixneeds, 2);
2758
	  return nd;
6 7u83 2759
	}
2 7u83 2760
 
2761
    case offset_max_tag: case max_tag: case min_tag:
2762
	{ needs nd;
2763
	  nd = likediv(e, at);
2764
	  nd.fixneeds = MAX_OF(nd.fixneeds, 3);
2765
	  return nd;
6 7u83 2766
	}
2767
 
2 7u83 2768
    case rem0_tag:
6 7u83 2769
    case rem2_tag:
2 7u83 2770
    {
6 7u83 2771
	return(remneeds(e, at));
2 7u83 2772
    }
2773
 
2774
    case div1_tag:
2775
    {
6 7u83 2776
      if (is_signed(sh(*e)) ==0)
2 7u83 2777
      {
2778
	setname(*e, div2_tag);
2779
      }
2780
      return divneeds(e,at);
2781
    }
2782
 
2783
    case mod_tag:
2784
    {
6 7u83 2785
    	if (is_signed(sh(*e)) ==0)
2 7u83 2786
	{
2787
	  setname(*e, rem2_tag);
2788
	}
2789
    	return remneeds(e,at);
2790
    }
2791
 
2792
  case fdiv_tag:
2793
#if 0
2794
    {
2795
      exp z = *(e);
2796
      exp a2 = bro(son(z));
2797
 
2798
      if (name(a2) == real_tag)	/* replace X/const by X*const^-1 */
2799
      {
2800
	flt inverse;
2801
	flt unitflt;
2802
 
6 7u83 2803
	unitflt = flptnos[fone_no];
2 7u83 2804
	if (flt_div(unitflt, flptnos[no(a2)], &inverse) == OKAY)
2805
	{
2806
	  /* a/const => a* (1.0/const) */
2807
	  int f = new_flpt();
2808
 
2809
	  flptnos[f] = inverse;
2810
	  no(a2) = f;
2811
	  setname(z, fmult_tag);
2812
	}
2813
      }
2814
    }
2815
    /* FALLTHROUGH */
2816
#endif
2817
 
2818
  case fplus_tag:
2819
  case fminus_tag:
2820
  case fmult_tag:
2821
    {
2822
      exp op = *(e);
2823
      exp a2 = bro(son(op));
2824
 
2825
      if (!last(a2))
2826
      {				/* + and * can have >2 parameters - make them
2827
				 * diadic - can do better a+exp => let x = exp
2828
				 * in a+x */
2829
	exp opn = getexp(sh(op), op, 0, a2, nilexp, 0, 0, name(op));
2830
 
2831
	/* dont need to transfer error treatment - nans */
2832
	exp nd = getexp(sh(op), bro(op), last(op), opn, nilexp, 0, 1,
2833
			ident_tag);
2834
	exp id = getexp(sh(op), op, 1, nd, nilexp, 0, 0, name_tag);
2835
 
2836
	pt(nd) = id;
2837
	bro(son(op)) = id;
2838
	setlast(op);
2839
	bro(op) = nd;
2840
	while (!last(a2))
2841
	  a2 = bro(a2);
2842
	bro(a2) = opn;
2843
	*(e) = nd;
2844
	return scan(e, at);
2845
      }
2846
 
2847
      return fpop(e, at);
2848
    };
2849
 
2850
  case field_tag:
2851
    {
2852
      needs str;
2853
      exp *arg = &son(*e);
2854
 
2855
      if (chase(*e, arg))
2856
      {				/* field has been distributed */
2857
	exp stare = *e;
2858
	exp ss = son(stare);
2859
 
2860
	if (!last(stare))
2861
	  clearlast(ss);
2862
	bro(ss) = bro(stare);
2863
	sh(ss) = sh(stare);
2864
	*e = ss;
6 7u83 2865
	return(scan(e, at));
2 7u83 2866
      }
2867
      str = scan(arg, at);
2868
      return maxneeds(str, shapeneeds(sh(*(e))));
2869
    };
2870
 
2871
/*********************************************************************
2872
	load_proc
2873
 
2874
 
2875
number is number of proc (useful for indexing)
2876
*********************************************************************/
2877
 
2878
  case proc_tag:
2879
  case general_proc_tag:
2880
  {
2881
     exp *bexp;
2882
     exp *bat;
2883
     needs body;
2884
     exp stare = *(e);
2885
 
2886
     /* set number temp t-regs that can be used in proc */
2887
     maxfix = maxfix_tregs;
2888
     maxfloat = MAXFLOAT_TREGS;
2889
 
2890
     assert(do_tlrecursion==0);
2891
 
2892
     callerfortr = do_tlrecursion && !proc_has_setjmp(stare) &&
2893
		   !proc_has_alloca(stare) && !proc_has_lv(stare) &&
2894
		   !proc_uses_crt_env(stare);
2895
 
6 7u83 2896
      gen_call = (name(stare) ==general_proc_tag);
2 7u83 2897
      has_tail_call = 0;
2898
 
2899
      callee_sz = 0;
2900
      stparam = 0;
2901
      fixparam = ARG0;
2902
      nonevis = 1;
2903
      rscope_level = 0;
2904
 
2905
      bexp = &son(*e);
2906
      bat = bexp;
2907
      body = scan(bexp, &bat);
2908
      /* scan the body of the proc */
2909
 
2910
      return body;		/* should never require this in reg in C */
2911
 
2912
  }
2913
 
2914
 case absbool_tag:
2915
  {
2916
    assert(has_setcc==0);
2917
    fail("absbool_tag not covered in needs scan");
2918
    /*NOTREACHED*/
2919
  }
2920
 
2921
 case alloca_tag:
2922
  {
2923
    needs nds;
2924
    cpr->Has_checkalloc = checkalloc(*e);
2925
    nds = scan(&son(*e), at);
2926
    if (nds.fixneeds < 2)
2927
	nds.fixneeds = 2;
6 7u83 2928
    builtin|= (1<<5);
2929
    return(nds);
2 7u83 2930
  }
2931
 
2932
 
2933
    case movecont_tag:{
2934
	exp * d = &son(*e);
2935
	exp * s = & bro(*d);
2936
	exp * sz = &bro(*s);
2937
	needs nd;
2938
	needs ns;
2939
	needs nsz;
6 7u83 2940
	prop prps;
2 7u83 2941
	nd = scan(d, at);
6 7u83 2942
	ns = scan(s, at);
2 7u83 2943
	nsz = scan(sz, at);
2944
	prps = (ns.propsneeds & hasproccall) << 1;
2945
	if (ns.fixneeds >= maxfix || prps != 0) {
2946
			      /* if reg requirements overlap, identify
2947
				 second operand */
6 7u83 2948
	  cca(at, d);
2949
	  ns = shapeneeds(sh(*(s)));
2 7u83 2950
	  ns.propsneeds |= morefix;
2951
	  ns.propsneeds &= ~(prps >> 1);
2952
	  ns.propsneeds |= prps;
2953
	}
2954
	nd.fixneeds += 1;
6 7u83 2955
	nd = maxneeds(nd, ns);
2 7u83 2956
	prps= (nsz.propsneeds & hasproccall) << 1;
2957
	if (nd.fixneeds +nsz.fixneeds >= maxfix || prps != 0) {
2958
			      /* if reg requirements overlap, identify
2959
				 last operand */
6 7u83 2960
	  cca(at, d);
2961
	  nsz = shapeneeds(sh(*(sz)));
2 7u83 2962
	  nsz.propsneeds |= morefix;
2963
	  nsz.propsneeds &= ~(prps >> 1);
2964
	  nsz.propsneeds |= prps;
6 7u83 2965
	}
2 7u83 2966
	nd.fixneeds+=1;
2967
	nd = maxneeds(nd,nsz);
6 7u83 2968
	if (nd.fixneeds < 4)nd.fixneeds = 3;
2 7u83 2969
	return nd;
2970
     }
2971
 
2972
 
2973
 case testbit_tag:
2974
  {
2975
    /* not in MIPS */
2976
    fail("testbit_tag not covered in needs scan");
2977
    /*NOTREACHED*/
2978
  }
2979
 
2980
 
2981
  default:
2982
    {
2983
       char s[64];
2984
       /*Know to NOT be covered:
2985
	 cscope_tag		(ignored)
2986
	 diag_tag		(ignored)
2987
	 fscope_tag		(ignored)
2988
	 local_free_all_tag
2989
	 local_free_tag
2990
	 offset_pad_tag
2991
	 testbit_tag
2992
	 */
2993
       FULLCOMMENT1("scan: bad nstare=%d", nstare);
2994
       sprintf(s,"case %d not covered in needs scan",nstare);
2995
       fail(s);
2996
       return zeroneeds;
2997
    }
2998
 
2999
  }
3000
}
3001
 
3002
 
3003
/* commented out return_to_label_tag and make_stack_limit_tag for puposes
3004
of debugging until proper 4.0 libraries are built. */