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-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
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
/* 80x86/scan2.c */
62
 
63
/**********************************************************************
64
$Author: release $
65
$Date: 1998/01/17 15:55:52 $
66
$Revision: 1.1.1.1 $
67
$Log: scan2.c,v $
68
 * Revision 1.1.1.1  1998/01/17  15:55:52  release
69
 * First version to be checked into rolling release.
70
 *
71
 * Revision 1.31  1997/12/04  20:01:12  pwe
72
 * ANDF-DE V1.9
73
 *
74
 * Revision 1.30  1997/10/10  18:25:26  pwe
75
 * prep ANDF-DE revision
76
 *
77
 * Revision 1.29  1997/02/18  11:43:05  pwe
78
 * NEWDIAGS for debugging optimised code
79
 *
80
 * Revision 1.28  1996/12/10  15:11:49  pwe
81
 * prep NEWDIAGS
82
 *
83
 * Revision 1.27  1996/07/09  16:57:36  pwe
84
 * cont_arg offset from global const
85
 *
86
 * Revision 1.26  1996/07/09  09:43:56  pwe
87
 * caller env_offset if callees present, and tidy
88
 *
89
 * Revision 1.25  1996/05/20  14:30:42  pwe
90
 * improved 64-bit handling
91
 *
92
 * Revision 1.24  1996/05/13  12:52:07  pwe
93
 * undo premature commit
94
 *
95
 * Revision 1.22  1996/02/01  09:34:39  pwe
96
 * PIC oddities for AVS
97
 *
98
 * Revision 1.21  1996/01/31  12:24:26  pwe
99
 * is_crc v is_opnd  &  end_contop must not preceed move_reg
100
 *
101
 * Revision 1.20  1996/01/22  14:31:09  pwe
102
 * PIC const*const, contop top_tag & linux 64-bit ints
103
 *
104
 * Revision 1.19  1996/01/17  11:24:38  pwe
105
 * resurrect performance
106
 *
107
 * Revision 1.18  1995/12/19  13:34:11  pwe
108
 * PIC global idents, and static vars
109
 *
110
 * Revision 1.17  1995/12/01  10:48:37  pwe
111
 * PIC static variables
112
 *
113
 * Revision 1.16  1995/11/01  18:41:29  pwe
114
 * PIC tail_call and exception handling
115
 *
116
 * Revision 1.15  1995/10/25  17:41:22  pwe
117
 * PIC_code current_env and callees
118
 *
119
 * Revision 1.14  1995/10/16  17:45:50  pwe
120
 * frame alignments
121
 *
122
 * Revision 1.13  1995/09/13  14:25:23  pwe
123
 * tidy for gcc
124
 *
125
 * Revision 1.12  1995/09/05  16:25:08  pwe
126
 * specials and exception changes
127
 *
128
 * Revision 1.11  1995/08/30  16:06:54  pwe
129
 * prepare exception trapping
130
 *
131
 * Revision 1.10  1995/08/23  09:43:01  pwe
132
 * track fpu control word for trap etc
133
 *
134
 * Revision 1.9  1995/08/14  13:54:05  pwe
135
 * several corrections, tail calls and error jumps
136
 *
137
 * Revision 1.8  1995/08/04  08:29:44  pwe
138
 * 4.0 general procs implemented
139
 *
140
 * Revision 1.7  1995/03/10  18:11:58  pwe
141
 * offset_div_by_int chvar to 32 bit
142
 *
143
 * Revision 1.6  1995/03/02  17:46:04  pwe
144
 * revise conditions for calling make_bitfield_offset
145
 *
146
 * Revision 1.5  1995/02/24  16:11:14  pwe
147
 * dynamic offsets, including mixed bit/byte representations
148
 *
149
 * Revision 1.4  1995/02/02  15:17:26  pwe
150
 * implement offset_max as max
151
 *
152
 * Revision 1.3  1995/02/01  18:51:18  pwe
153
 * correct empty make_nof
154
 *
155
 * Revision 1.2  1995/01/30  12:56:46  pwe
156
 * Ownership -> PWE, tidy banners
157
 *
158
 * Revision 1.1  1994/10/27  14:15:22  jmf
159
 * Initial revision
160
 *
161
 * Revision 1.1  1994/07/12  14:40:36  jmf
162
 * Initial revision
163
 *
164
**********************************************************************/
165
 
166
 
167
/**********************************************************************
168
                            scan2.c
169
     Defines the scan through a program which
170
     reorganises it so that all arguments of
171
     operations are 80386 operands.
172
     80386 specific.
173
 
174
     These procedures use a pair of a boolean and and exp (eg sto and to)
175
     instead of a pointer to an exp. The boolean is true if the exp
176
     being referred to is the son of the given exp, and false if it is
177
     the brother. This is to allow exps to be represented by indices
178
     into arrays and to allow the arrays to be realloced, which
179
     invalidates the use of &son(to) and &bro(to).
180
 
181
**********************************************************************/
182
 
183
 
184
#include "config.h"
185
#include "common_types.h"
186
#include "exp.h"
187
#include "expmacs.h"
188
#include "tags.h"
189
#include "shapemacs.h"
190
#include "flags.h"
191
#include "label_ops.h"
192
#include "install_fns.h"
193
#include "externs.h"
194
#include "coder.h"
195
#include "instr386.h"
196
#include "scan2.h"
197
#include "basicread.h"
198
 
199
/* MACROS */
200
 
7 7u83 201
#define assexp(isson, p, v) if (isson)setson(p, v); else setbro(p, v)
202
#define contexp(isson, p)((isson)? son(p): bro(p))
2 7u83 203
 
204
/* PROCEDURES */
205
 
206
/* inserts an identity declaration of x at
207
   to, and replaces x by a use of the
208
   identifier */
209
static void cca
7 7u83 210
(int sto, exp to, int sx, exp x)
2 7u83 211
{
212
  exp def, ato, id, tg;
7 7u83 213
  def = contexp(sx, x);
2 7u83 214
  if (name(def)==caller_tag) {	/* position sensitive */
7 7u83 215
    cca(sto, to, 1, def);
2 7u83 216
    return;
217
  }
7 7u83 218
  ato = contexp(sto, to);
219
  id = getexp(sh(ato), bro(ato), (int)(last(ato)), def, nilexp,
2 7u83 220
      0, 1, ident_tag);
7 7u83 221
  tg = getexp(sh(def), bro(def), (int)(last(def)), id, nilexp,
2 7u83 222
      0, 0, name_tag);
7 7u83 223
  pt(id) = tg;
224
  clearlast(def);
2 7u83 225
  if (def != ato) {
7 7u83 226
    bro(def) = ato;
227
    bro(ato) = id;
228
    setlast(ato);
229
    assexp(sto, to, id);
230
    assexp(sx, x, tg);
2 7u83 231
  }
232
  else {
7 7u83 233
    bro(def) = tg;
234
    bro(tg) = id;
235
    setlast(tg);
236
    clearlast(def);
237
    assexp(sto, to, id);
2 7u83 238
  };
239
#ifdef NEWDIAGS
240
  if (diagnose) {
241
    dgf(id) = dgf(bro(son(id)));
242
    dgf(bro(son(id))) = nildiag;
243
  }
244
#endif
245
  return;
246
}
247
 
248
/* keeping the same to, scans along the
249
   bro list e, applying cca to introduce
250
   an identity declaration when doit is 1.
251
   Keeps count as the index position along
252
   the list in order to pass it to doit.
253
   If it uses cca it scans the resulting
254
   declaration, using the same to. If it
255
   doesnt use cca, it scans the list
256
   element, still using the same to. This
257
   keeps all operations in the same order.
258
   Result of cc is true if the operands
259
   are all of 80386 form. some operations
260
   are allowed to have not more than one
261
   operand not of 80386 form; this is then
262
   precomputed in reg0 before the
263
   operations. This boolean result is used
264
   to ensure that not more than one
265
   operand is so treated */
266
static int cc
7 7u83 267
(int sto, exp to, int se, exp e,	      int(*doit)(exp, int, int),
268
 int count, int usereg0)
2 7u83 269
{
270
  int unused = usereg0;	/* can still use reg0 */
7 7u83 271
  exp ec = contexp(se, e);
272
  if (last(ec)) {
273
    if (doit(ec, count, unused)) {
274
      cca(sto, to, se, e);
275
      ec = contexp(sto, to);
276
      return(scan2(1, ec, son(ec), unused));
2 7u83 277
    }
278
    else {
279
      if (unused)
7 7u83 280
	return(scan2(se, e, ec, 1));
281
      return(scan2(sto, to, ec, unused));
2 7u83 282
    }
283
  }
284
  else {
7 7u83 285
    unused = cc(sto, to, 0, ec, doit, count + 1, unused);
2 7u83 286
    /* can we still use reg0? */
7 7u83 287
    ec = contexp(se, e);
288
    if (doit(ec, count, unused)) {
289
      cca(sto, to, se, e);
290
      ec = contexp(sto, to);
291
      return(scan2(1, ec, son(ec), unused));
2 7u83 292
    }
293
    else {
294
      if (unused)
7 7u83 295
	return(scan2(sto, to, ec, 1));
296
      return(scan2(sto, to, ec, unused));
2 7u83 297
    };
298
  };
299
}
300
 
301
/* keeping the same to, scans along the
302
   bro list e, applying cca to introduce
303
   an identity declaration when doit is 1.
304
   Keeps count as the index position along
305
   the list in order to pass it to doit.
306
   If it uses cca it scans the resulting
307
   declaration, using the same to. If it
308
   doesnt use cca, it scans the list
309
   element, still using the same to. This
310
   keeps all operations in the same order.
311
   The difference in detail from cc supports
312
   the asymmetry of div etc */
313
static void cc1
7 7u83 314
(int sto, exp to, int se, exp e,	      int(*doit)(exp, int, int),
315
 int count, int usereg0)
2 7u83 316
{
7 7u83 317
  int unused = ((count == 1)? usereg0 : 0);
2 7u83 318
	/* can we still use reg0? */
7 7u83 319
  exp ec = contexp(se, e);
320
  if (last(ec)) {
321
    if (doit(ec, count, unused)) {
322
      cca(sto, to, se, e);
323
      ec = contexp(sto, to);
324
      IGNORE scan2(1, ec, son(ec), unused);
2 7u83 325
      return;
326
    }
327
    else {
7 7u83 328
      if (unused) {
329
	IGNORE scan2(se, e, ec, 1);
2 7u83 330
        return;
331
      };
7 7u83 332
      IGNORE scan2(sto, to, ec, unused);
2 7u83 333
      return;
334
    }
335
  }
336
  else {
7 7u83 337
    cc1(sto, to, 0, ec, doit, count + 1, unused);
2 7u83 338
    /* can we still use reg0? */
7 7u83 339
    ec = contexp(se, e);
340
    if (doit(ec, count, unused)) {
341
      cca(sto, to, se, e);
342
      ec = contexp(sto, to);
343
      IGNORE scan2(1, ec, son(ec), unused);
2 7u83 344
      return;
345
    }
346
    else {
7 7u83 347
      if (unused) {
348
	IGNORE scan2(se, e, ec, 1);
2 7u83 349
	return;
350
      };
7 7u83 351
      IGNORE scan2(sto, to, ec, unused);
2 7u83 352
      return;
353
    };
354
  };
355
}
356
 
357
 
358
/* does cca and forces the declaration to use a register */
359
static void ccp
7 7u83 360
(int sto, exp to, int sx, exp x)
2 7u83 361
{
362
  exp toc;
7 7u83 363
  cca(sto, to, sx, x);
364
  toc = contexp(sto, to);
365
  setusereg(toc);
366
  IGNORE scan2(1, toc, son(toc), 0);
2 7u83 367
  return;
368
}
369
 
370
/* is an operand */
371
static int is_opnd
7 7u83 372
(exp e)
2 7u83 373
{
374
				/* make sure (is_o && is_crc -> !is_opnd) */
7 7u83 375
  unsigned char  n = name(e);
2 7u83 376
  if (n == name_tag) {
377
    if (isvar(son(e)))
7 7u83 378
	return(isglob(son(e)) && !PIC_code);
379
    return(son(son(e))!= nilexp &&
380
	(!isglob(son(e)) || !PIC_code || name(sh(son(e)))!= prokhd ||
2 7u83 381
				(brog(son(e)) -> dec_u.dec_val.extnamed)) &&
7 7u83 382
	(name(son(son(e)))!= ident_tag || !isparam(son(son(e)))));
2 7u83 383
  }
7 7u83 384
  return(
2 7u83 385
      n == val_tag || n == real_tag || n == env_size_tag ||
386
      n == cont_tag ||
387
      n == string_tag ||
388
      n == null_tag ||
389
      n == proc_tag || n == general_proc_tag);
390
}
391
 
392
 
393
 
394
 
395
/* This checks the integer argument of an
396
   addptr to make sure that it is of the
397
   right form, including the scale factor
398
   for the kind of operand. This
399
   introduces two declarations, only the
400
   inner one forces the use of a register.
401
   This guarantees that we only load the
402
   registers as close to the actual
403
   instruction as possible, since we are
404
   short of registers on the 80386 */
405
static void ap_argsc
7 7u83 406
(int sto, exp to, exp e)
2 7u83 407
{
408
  exp p, a, q;
409
  int  k;
410
  int do1 = 1;
411
 
7 7u83 412
  if (name(son(e)) == reff_tag)
413
    q = son(son(e));
2 7u83 414
  else
415
    q = son (e);		/* q must be addptr - all addptrs processed here */
416
 
417
  if ((frame_al_of_ptr(sh(son(q))) & al_includes_vcallees) &&
418
	(frame_al1_of_offset(sh(bro(son(q)))) & al_includes_caller_args)) {
419
				/* env_offset to arg requires indirection from
420
				   frame pointer */
421
    shape pc_sh = f_pointer(f_callers_alignment(0));
7 7u83 422
    exp c = getexp(pc_sh, bro(son(q)), 0, nilexp, nilexp, 0, 0, cont_tag);
423
    exp r = getexp(pc_sh, c, 1, son(q), nilexp, 0, 64, reff_tag);
424
    setfather(r, son(q));
2 7u83 425
    son(c) = r;
426
    son(q) = c;
427
  }
428
 
7 7u83 429
  p = son(q);
430
  a = bro(p);
2 7u83 431
 
7 7u83 432
  if (name(p) == name_tag && isvar(son(p)) && isglob(son(p)))
2 7u83 433
    do1 = 0;
434
 
435
  if (do1)
7 7u83 436
    ccp(1, e, 1, q);
2 7u83 437
 
7 7u83 438
  if (name(a) == offset_mult_tag && name(bro(son(a))) == val_tag &&
439
  (k = no(bro(son(a))), k == 8 || k == 16 || k == 32 || k == 64))
440
    ccp(1, e, 1, bro(son(q)));
2 7u83 441
  else
7 7u83 442
    ccp(1, e, 0, son(q));
2 7u83 443
 
444
  if (do1) {
7 7u83 445
    cca(sto, to, 1, son(e));
446
    cca(sto, to, 1, bro(son(son(e))));
2 7u83 447
  }
448
  else
7 7u83 449
    cca(sto, to, 1, son(e));
2 7u83 450
 
451
  return;
452
 
453
}
454
 
455
 
456
 
457
/* checks that the argument of a cont or
458
   the destination of an assign has the
459
   right form for an operand, and
460
   introduces a declaration if not.
461
   Continues processing with the same to.
462
   These arguments can contain
463
   declarations, so that we can load
464
   addresses as close as possible to the
465
   instructions that use them, since we
466
   are short of registers in the 80386.
467
   This is done by contop in instr386, during
468
   the code production. */
469
static int cont_arg
7 7u83 470
(int sto, exp to, exp e, int usereg0)
2 7u83 471
{
7 7u83 472
  unsigned char  n = name(son(e));
2 7u83 473
 
474
 
7 7u83 475
    if (n == name_tag && isvar(son(son(e))))
2 7u83 476
      return usereg0;
477
 
478
    if (n == cont_tag && usereg0 && shape_size(sh(e)) <= 32) {
479
      cont_arg(sto, to, son(e), 1);
480
      return 0;
481
    }
482
 
483
    if (n == reff_tag) {
7 7u83 484
      exp s = son(son(e));
485
      if (name(s) == name_tag) {
486
	if (isusereg(son(s)))
2 7u83 487
          return 0;
488
        if (!PIC_code && isglob(son(s)) && isvar(son(s)))
489
          return 0;
490
      };
491
 
492
      if (name(s) == cont_tag && usereg0 && shape_size(sh(e)) <= 32) {
493
	cont_arg(sto, to, s, 1);
494
	return 0;
495
      }
496
 
7 7u83 497
      if (name(s) == addptr_tag) {
498
	ap_argsc(sto, to, e);
2 7u83 499
	return 0;
500
      }
501
    };
502
 
503
 
504
    if (n == addptr_tag) {
7 7u83 505
      ap_argsc(sto, to, e);
2 7u83 506
      return 0;
507
    };
508
 
509
  if (n == reff_tag)
7 7u83 510
    ccp(1, e, 1, son(e));
2 7u83 511
  else
7 7u83 512
    ccp(1, e, 1, e);
2 7u83 513
 
7 7u83 514
  cca(sto, to, 1, son(e));
2 7u83 515
 
516
  return 0;
517
}
518
 
519
 
520
/* is assignable */
521
static int is_assable
7 7u83 522
(exp e)
2 7u83 523
{
7 7u83 524
  return(is_a(name(e)) || name(e) == alloca_tag ||
525
	((name(e) == apply_tag || name(e) == apply_general_tag) &&
526
	(name(sh(e)) <= ulonghd || name(sh(e)) == ptrhd)));
2 7u83 527
}
528
 
529
/* doit routine, is not an operand */
530
static int notopnd
7 7u83 531
(exp t, int c, int usereg0)
2 7u83 532
{
533
  UNUSED(c);
534
  if (usereg0) {
7 7u83 535
    if (is_opnd(t))
536
      return(0);
537
    return(!is_assable(t));
2 7u83 538
  };
7 7u83 539
  return(!is_opnd(t));
2 7u83 540
}
541
 
7 7u83 542
static int scan_for_alloca(exp);
2 7u83 543
 
544
static int scan_alloc_args
7 7u83 545
(exp s)
2 7u83 546
{
547
  if (scan_for_alloca(s))
548
    return 1;
549
  if (last(s))
550
    return 0;
551
  return scan_alloc_args(bro(s));
552
}
553
 
554
static int scan_for_alloca
7 7u83 555
(exp t)
2 7u83 556
{
557
  switch (name(t)) {
558
    case local_free_all_tag:
559
    case local_free_tag:
560
    case last_local_tag:
561
    case alloca_tag:
562
    case make_lv_tag:
563
      return 1;
564
    case case_tag:
565
      return scan_for_alloca(son(t));
566
    case labst_tag:
567
      return scan_for_alloca(bro(son(t)));
568
    case env_offset_tag:
569
    case string_tag:
570
    case name_tag:
571
      return 0;
572
    case apply_general_tag:
573
      if call_is_untidy(t)
574
	return 1;
575
      return scan_alloc_args(son(t));
576
    default:
577
      if (son(t) == nilexp)
578
        return 0;
579
      return scan_alloc_args(son(t));
580
  };
581
}
582
 
583
static int no_alloca
7 7u83 584
(exp t, int c, int usereg0)
2 7u83 585
{
586
  UNUSED(c); UNUSED(usereg0);
587
  return scan_for_alloca(t);
588
}
589
 
590
/* uses cc, requiring all to be operands */
591
static void all_opnd
7 7u83 592
(int sto, exp to, exp e, int usereg0)
2 7u83 593
{
7 7u83 594
  IGNORE cc(sto, to, 1, e, notopnd, 1, usereg0);
2 7u83 595
  return;
596
}
597
 
598
/* doit routine, not assignable */
599
static int notass
7 7u83 600
(exp t, int i, int usereg0)
2 7u83 601
{
602
  UNUSED(i); UNUSED(usereg0);
7 7u83 603
  return(!is_assable(t));
2 7u83 604
}
605
 
606
/* uses cc, requiring all to be assignable */
607
static void all_assable
7 7u83 608
(int sto, exp to, exp e)
2 7u83 609
{
7 7u83 610
  IGNORE cc(sto, to, 1, e, notass, 1, 1);
2 7u83 611
  return;
612
}
613
 
614
/* just used in the next routine */
615
static int is_direct
7 7u83 616
(exp e)
2 7u83 617
{
7 7u83 618
  unsigned char  s = name(e);
619
  return((s == name_tag && !isglob(son(e)) && !isvar(son(e))) ||
620
  (s == cont_tag && name(son(e)) == name_tag &&
621
	!isglob(son(son(e))) && isvar(son(son(e)))));
2 7u83 622
}
623
 
624
/* is indirectly addressable */
625
static int is_indable
7 7u83 626
(exp e)
2 7u83 627
{
7 7u83 628
  unsigned char  s = name(e);
2 7u83 629
  if (s == name_tag)
7 7u83 630
    return(1);
2 7u83 631
 
632
  if (s == cont_tag) {
7 7u83 633
    unsigned char  t = name(son(e));
634
    return((t == name_tag && isvar(son(son(e)))) ||
635
	(t == cont_tag && name(son(son(e))) == name_tag &&
636
	  isvar(son(son(son(e))))) ||
637
	(t == reff_tag && is_direct(son(son(e)))));
2 7u83 638
  };
639
 
7 7u83 640
  return((s == reff_tag && is_direct(son(e))) ||
2 7u83 641
 
642
      s == addptr_tag);
643
}
644
 
645
 
646
/* son must be indirectly addressable */
647
static void indable_son
7 7u83 648
(int sto, exp to, exp e)
2 7u83 649
{
7 7u83 650
  if (!is_indable(son(e))) {
2 7u83 651
    exp ec;
7 7u83 652
    cca(sto, to, 1, e);
653
    ec = contexp(sto, to);
654
    IGNORE scan2(1, ec, son(ec), 0);
2 7u83 655
  }
656
  else
7 7u83 657
    IGNORE scan2(sto, to, son(e), 0);
2 7u83 658
  return;
659
}
660
 
661
 
662
 
663
/* apply scan2 to this bro list, moving "to" along it */
664
static void scanargs
7 7u83 665
(int st, exp e, int usereg0)
2 7u83 666
{
667
  exp t = e;
668
  exp temp;
669
 
7 7u83 670
  while (temp = contexp(st, t), IGNORE scan2(st, t, temp, usereg0),
671
      temp = contexp(st, t), !last(temp)) {
672
    t = contexp(st, t);
2 7u83 673
    st = 0;
674
  };
675
  return;
676
}
677
 
678
 
679
 
680
/* doit routine for plus first arg cant be negate, others can */
681
static int plusdo
7 7u83 682
(exp t, int i, int usereg0)
2 7u83 683
{
684
  UNUSED(i);
685
  if (usereg0)
7 7u83 686
    return(0);
687
  if (name(t) == neg_tag)
688
    return(0);
689
  return(!is_opnd(t));
2 7u83 690
}
691
 
692
/* doit routine for mult */
693
static int multdo
7 7u83 694
(exp t, int i, int usereg0)
2 7u83 695
{
696
  UNUSED(i);
7 7u83 697
  return((usereg0)? 0 : !is_opnd(t));
2 7u83 698
}
699
 
700
/* doit routine for and */
701
static int anddo
7 7u83 702
(exp t, int i, int usereg0)
2 7u83 703
{
704
  UNUSED(i);
7 7u83 705
  return((usereg0)? 0 : !is_opnd(t));
2 7u83 706
}
707
 
708
/* doit routine for xor */
709
static int notado
7 7u83 710
(exp t, int i, int usereg0)
2 7u83 711
{
712
  UNUSED(i);
7 7u83 713
  return((usereg0)? 0 : !is_opnd(t));
2 7u83 714
}
715
 
716
/* change offset representation bytes to bits */
717
static void make_bitfield_offset
7 7u83 718
(exp e, exp pe, int spe, shape sha)
2 7u83 719
{
720
  exp omul;
721
  exp val8;
722
  if (name(e) == val_tag)
723
    return;
7 7u83 724
  omul = getexp(sha, bro(e), (int)(last(e)), e, nilexp, 0, 0, offset_mult_tag);
725
  val8 = getexp(slongsh, omul, 1, nilexp, nilexp, 0, 8, val_tag);
2 7u83 726
  clearlast(e);
727
  setbro(e, val8);
728
  assexp(spe, pe, omul);
729
}
730
 
731
static void scan_apply_args
7 7u83 732
(int spto, exp pto, int sato, exp ato)
2 7u83 733
{
7 7u83 734
  if (scan_alloc_args(contexp(sato, ato)))
735
    IGNORE cc(spto, pto, sato, ato, no_alloca, 1, 0);
2 7u83 736
  else
737
    IGNORE scanargs(sato, ato, 1);
738
}
739
 
740
/* avoid registers corrupted by dynamic callees */
741
static void cca_for_cees
7 7u83 742
(int sto, exp to, exp e)
2 7u83 743
{
744
  if (name(son(e)) == name_tag) {
7 7u83 745
    if (!isglob(son(son(e))))
746
      set_intnl_call(son(son(e)));
2 7u83 747
    return;
748
  }
749
  if (name(son(e)) == cont_tag && name(son(son(e))) == name_tag) {
7 7u83 750
    if (!isglob(son(son(son(e)))))
751
      set_intnl_call(son(son(son(e))));
2 7u83 752
    return;
753
  }
7 7u83 754
  cca(sto, to, 1, e);
755
  set_intnl_call(contexp(sto, to));
2 7u83 756
}
757
 
758
 
759
static int is_asm_opnd
7 7u83 760
(exp e, int ext)
2 7u83 761
{
7 7u83 762
  unsigned char n = name(e);
2 7u83 763
  if (n == name_tag) {
7 7u83 764
    setvis(son(e));
2 7u83 765
    return 1;
766
  }
767
  if (n == cont_tag && name(son(e)) == name_tag && isvar(son(son(e)))) {
7 7u83 768
    setvis(son(son(e)));
2 7u83 769
    return 1;
770
  }
7 7u83 771
  return(n == val_tag || n == real_tag || n == null_tag ||
2 7u83 772
	(n == reff_tag && name(son(e)) == name_tag));
773
}
774
 
775
static int is_asm_var
7 7u83 776
(exp e, int ext)
2 7u83 777
{
7 7u83 778
  unsigned char n = name(e);
2 7u83 779
  if (n == name_tag && isvar(son(e))) {
7 7u83 780
    setvis(son(e));
2 7u83 781
    return 1;
782
  }
783
  return 0;
784
}
785
 
786
void check_asm_seq
7 7u83 787
(exp e, int ext)
2 7u83 788
{
789
  if (name(e) == asm_tag) {
790
    if ((asm_string(e) && name(son(e)) == string_tag) ||
791
	(asm_in(e) && is_asm_opnd(son(e), ext)) ||
7 7u83 792
	(asm_var(e) && is_asm_var(son(e), ext)))
2 7u83 793
      return;
794
  }
795
  if (name(e) == seq_tag) {
796
    exp t = son(son(e));
797
    for (;;) {
7 7u83 798
      check_asm_seq(t, ext);
2 7u83 799
      if (last(t))
800
	break;
801
      t = bro(t);
802
    }
7 7u83 803
    check_asm_seq(bro(son(e)), ext);
2 7u83 804
  }
805
  else
7 7u83 806
  if (name(e)!= top_tag)
807
    failer("illegal ~asm");
2 7u83 808
  return;
809
}
810
 
811
 
812
 
813
/* main scan routine */
814
int scan2
7 7u83 815
(int sto, exp to, exp e, int usereg0)
2 7u83 816
{
7 7u83 817
  switch (name(e)) {
2 7u83 818
    case prof_tag:
819
	return 0;
820
    case cond_tag:
821
    case rep_tag:
822
    case compound_tag:
823
    case solve_tag:
824
    case nof_tag:
825
    case concatnof_tag:
826
    case ncopies_tag:
827
#ifndef NEWDIAGS
828
    case diagnose_tag:
829
#endif
830
    case caller_tag:
831
      {
832
	if (son(e) == nilexp) /* empty make_nof */
7 7u83 833
	  return(0);
834
	scanargs(1, e, 1);
835
	return(0);
2 7u83 836
      };
837
 
838
    case labst_tag:
839
      {
7 7u83 840
	IGNORE scan2(0, son(e), bro(son(e)), 1);
841
	return(0);
2 7u83 842
      };
843
    case ident_tag:
844
      {
7 7u83 845
	IGNORE scan2(0, son(e), bro(son(e)), 0);
846
	IGNORE scan2(1, e, son(e), 0);
847
	return(0);
2 7u83 848
      };
849
    case seq_tag:
850
      {
7 7u83 851
	scanargs(1, son(e), 1);
852
	IGNORE scan2(0, son(e), bro(son(e)), 1);
853
	return(0);
2 7u83 854
      };
855
 
856
    case local_free_tag:
857
    case long_jump_tag:
858
    case return_to_label_tag:
859
      {
7 7u83 860
	all_assable(sto, to, e);
861
	return(0);
2 7u83 862
      };
863
 
864
    case offset_add_tag:
865
    case offset_subtract_tag:
866
      {
7 7u83 867
	if (al2(sh(son(e))) == 1 && al2(sh(bro(son(e))))!= 1)
868
	  make_bitfield_offset(bro(son(e)), son(e), 0, sh(e));
869
	if (al2(sh(son(e)))!= 1 && al2(sh(bro(son(e)))) == 1)
870
	  make_bitfield_offset(son(e), e, 1, sh(e));
871
	IGNORE all_opnd(sto, to, e, usereg0);
2 7u83 872
	return 0;
873
	/* all arguments except possibly one must be operands */
874
      };
875
 
876
    case offset_mult_tag:
877
    case alloca_tag:
878
    case minus_tag:
879
    case neg_tag:
880
    case not_tag:
881
    case offset_pad_tag:
882
    case offset_negate_tag:
883
    case offset_max_tag:
884
    case int_to_bitf_tag:
885
    case testbit_tag:
886
    case bitf_to_int_tag:
887
    case max_tag:
888
    case min_tag:
889
    case abs_tag:
890
      {
7 7u83 891
	IGNORE all_opnd(sto, to, e, usereg0);
2 7u83 892
	return 0;
893
	/* all arguments except possibly one must be operands */
894
      };
895
    case subptr_tag:
896
    case minptr_tag:
897
    case make_stack_limit_tag:
898
      {
7 7u83 899
	IGNORE all_opnd(sto, to, e, 0);
2 7u83 900
	return 0;
901
      };
902
    case set_stack_limit_tag:
903
      {
904
	exp lim = find_stlim_var();
7 7u83 905
	setbro(lim, son(e));
906
	setson(e, lim);
907
	setname(e, ass_tag);
908
	return scan2(sto, to, e, usereg0);
2 7u83 909
      };
910
    case chvar_tag:
911
      {
7 7u83 912
	int ur = usereg0 && name(son(e))!= cont_tag;
913
	IGNORE all_opnd(sto, to, e, ur);
2 7u83 914
	return 0;
915
      };
916
 
917
    case test_tag:
918
    case absbool_tag:
919
      {
7 7u83 920
	if ((name(sh(son(e))) >= shrealhd &&
921
	      name(sh(son(e))) <= doublehd))
2 7u83 922
	  IGNORE all_opnd (sto, to, e, 0);/* all arguments must be operands */
923
	else
7 7u83 924
	  IGNORE all_opnd(sto, to, e, usereg0);
2 7u83 925
	/* all arguments except possibly one must be operands */
926
	return 0;
927
      };
928
 
929
    case mod_tag:
930
    case rem2_tag:
931
    case rem0_tag:
932
    case div1_tag:
933
    case div2_tag:
934
    case div0_tag:
935
      {
7 7u83 936
	if (name(sh(e)) == u64hd) {
2 7u83 937
	  exp * bottom = &bro(son(e));
7 7u83 938
	  if (name(*bottom) == chvar_tag && shape_size(sh(son(*bottom))) <= 32 &&
939
		name(son(*bottom))!= val_tag && !is_signed(sh(son(*bottom)))) {
940
	    if (shape_size(sh(son(*bottom))) == 32) {
941
	      setbro(son(*bottom), bro(*bottom));
2 7u83 942
	      *bottom = son(*bottom);
943
	    }
944
	    else
7 7u83 945
	      setsh(son(*bottom), ulongsh);
2 7u83 946
	  }
947
	}
7 7u83 948
	cc1(sto, to, 1, e, notopnd, 1, usereg0);
2 7u83 949
	return 0;
950
	/* all arguments except possibly the first must be operands */
951
      };
952
 
953
    case shl_tag:
954
    case shr_tag:
955
    case rotl_tag:
956
    case rotr_tag:
957
    case offset_div_tag:
958
      {
7 7u83 959
	cc1(sto, to, 1, e, notopnd, 1, usereg0);
2 7u83 960
	return 0;
961
	/* all arguments except possibly the first must be operands */
962
      };
963
 
964
    case offset_div_by_int_tag:
965
      {
7 7u83 966
	if (name(sh(bro(son(e))))!= slonghd &&  name(sh(bro(son(e))))!= ulonghd) {
967
	  exp ch = getexp((name(sh(bro(son(e)))) &1 ? slongsh : ulongsh),
2 7u83 968
		e, 1, bro(son(e)), nilexp, 0, 0, chvar_tag);
969
	  setbro(bro(son(e)), ch);
970
	  setbro(son(e), ch);
971
	};
7 7u83 972
	cc1(sto, to, 1, e, notopnd, 1, usereg0);
2 7u83 973
	return 0;
974
	/* all arguments except possibly the first must be operands */
975
      };
976
 
977
    case fplus_tag:
978
    case fminus_tag:
979
    case fmult_tag:
980
    case fdiv_tag:
981
    case fneg_tag:
982
    case fabs_tag:
983
    case chfl_tag:
984
    case float_tag:
985
    case round_tag:
986
    case movecont_tag:
987
      {
988
	IGNORE all_opnd (sto, to, e, 0);/* all arguments must be operands */
989
	return 0;
990
      };
991
    case ass_tag:
992
    case assvol_tag:
993
      {
994
	exp toc;
995
	if (name (e) == assvol_tag)/* change assvol to assign */
7 7u83 996
	  setname(e, ass_tag);
997
	IGNORE cont_arg(sto, to, e, 0);
2 7u83 998
	/* special check for references */
7 7u83 999
	if (!is_assable(bro(son(e)))) {
2 7u83 1000
	  /* second argument must be assignable */
7 7u83 1001
	  cca(sto, to, 0, son(e));
1002
	  toc = contexp(sto, to);
1003
	  IGNORE scan2(1, toc, son(toc), 1);
2 7u83 1004
	}
1005
	else
7 7u83 1006
	  IGNORE scan2(sto, to, bro(son(e)), 1);
1007
	return(0);
2 7u83 1008
      };
1009
    case apply_tag:
1010
      {
1011
	if (builtinproc(e)) {	/* son must be named global */
1012
	  if (!last(son(e)))
7 7u83 1013
	    IGNORE cc(sto, to, 0, son(e), notopnd, 1, 0);
2 7u83 1014
	  return 0;
1015
	}
1016
        if (!last(son(e)))
7 7u83 1017
	  scan_apply_args(sto, to, 0, son(e));
1018
	indable_son(sto, to, e);
1019
	return(0);
2 7u83 1020
      };
1021
    case apply_general_tag:
1022
      {
1023
	exp cees = bro(bro(son(e)));
1024
	exp p_post = cees;	/* bro(p_post) is postlude */
1025
	while (name(bro(p_post)) == ident_tag && name(son(bro(p_post))) == caller_name_tag)
1026
	  p_post = son(bro(p_post));
7 7u83 1027
	scan2(0, p_post, bro(p_post), 1);
1028
	if (son(cees)!= nilexp)
1029
	  scan_apply_args(sto, to, 1, cees);
1030
	if (no(bro(son(e)))!= 0)
1031
	  scan_apply_args(sto, to, 1, bro(son(e)));
1032
	indable_son(sto, to, e);
1033
	if ((name(cees) == make_dynamic_callee_tag && name(bro(son(cees)))!= val_tag)
2 7u83 1034
		|| (name(cees) == same_callees_tag && callee_size < 0))
1035
	  has_dy_callees = 1;
1036
	if (name(cees) == same_callees_tag)
1037
	  has_same_callees = 1;
1038
	if (name(cees) == make_dynamic_callee_tag || name(cees) == same_callees_tag)
7 7u83 1039
	  cca_for_cees(sto, to, e);
1040
	return(0);
2 7u83 1041
      };
1042
    case tail_call_tag:
1043
      {
1044
	exp cees = bro(son(e));
1045
	has_tail_call = 1;
7 7u83 1046
	if (son(cees)!= nilexp)
1047
	  IGNORE cc(sto, to, 1, cees, no_alloca, 1, 0);
1048
	indable_son(sto, to, e);
1049
	if (name(cees) == make_dynamic_callee_tag && name(bro(son(cees)))!= val_tag)
2 7u83 1050
	  has_dy_callees = 1;
1051
	if (name(cees) == same_callees_tag)
1052
	  has_same_callees = 1;
1053
	if (name(cees) == make_dynamic_callee_tag)
7 7u83 1054
	  cca_for_cees(sto, to, e);
1055
	return(0);
2 7u83 1056
      };
1057
    case goto_lv_tag:
1058
      {
7 7u83 1059
	indable_son(sto, to, e);
1060
	return(0);
2 7u83 1061
      };
1062
    case res_tag:
1063
    case untidy_return_tag:
1064
      {
1065
	if ((name(sh(son(e))) == cpdhd) &&
7 7u83 1066
	 (name(son(e))!= cont_tag ||
1067
	      name(son(son(e)))!= name_tag ||
2 7u83 1068
	      !isvar(son(son(son(e)))))) { /* gcc compatibility */
1069
	  exp ec;
7 7u83 1070
	  cca(sto, to, 1, e);
1071
	  ec = contexp(sto, to);
1072
	  IGNORE scan2(1, ec, son(ec), 0);
2 7u83 1073
	  return 0;
1074
	}
1075
	else  {
7 7u83 1076
	  IGNORE(scan2(sto, to, son(e), 1));
2 7u83 1077
	  return 0;
1078
	};
1079
      };
1080
    case case_tag:
1081
      {
1082
	exp toc;
7 7u83 1083
	if (name(son(e))!= name_tag &&
1084
	(name(son(e))!= cont_tag ||
1085
	      name(son(son(e)))!= name_tag)) {
1086
	  cca(sto, to, 1, e);
1087
	  toc = contexp(sto, to);
1088
	  IGNORE scan2(1, toc, son(toc), 0);
2 7u83 1089
	}
1090
	else
7 7u83 1091
	  IGNORE scan2(sto, to, son(e), 0);
1092
	return(0);
2 7u83 1093
      };
1094
    case plus_tag:
1095
      {
7 7u83 1096
	IGNORE cc(sto, to, 1, e, plusdo, 1, usereg0);
2 7u83 1097
	return 0;
1098
      };
1099
    case addptr_tag:
1100
      {
7 7u83 1101
	exp f = father(e);
1102
	exp new_r = getexp(sh(e), bro(e), (int)(last(e)),
2 7u83 1103
                             e, nilexp, 0,
1104
	    0, reff_tag);
7 7u83 1105
	exp * ref = refto(f, e);
1106
	setlast(e);
1107
	bro(e) = new_r;
2 7u83 1108
	*ref = new_r;
7 7u83 1109
	ap_argsc(sto, to, new_r);
1110
	return(0);
2 7u83 1111
      };
1112
    case mult_tag:
1113
      {
7 7u83 1114
	if (shape_size(sh(e)) == 64 && optop(e)) {
2 7u83 1115
	  exp * arglist = &son(e);
1116
	  for (;;) {
7 7u83 1117
	    if (name(*arglist) == chvar_tag && shape_size(sh(son(*arglist))) <= 32 &&
1118
		(is_signed(sh(e)) || !is_signed(sh(son(*arglist))))) {
1119
	      if (shape_size(sh(son(*arglist))) == 32) {
1120
		setbro(son(*arglist), bro(*arglist));
2 7u83 1121
		if (last(*arglist))
7 7u83 1122
		  setlast(son(*arglist));
2 7u83 1123
		else
7 7u83 1124
		  clearlast(son(*arglist));
2 7u83 1125
		*arglist = son(*arglist);
1126
	      }
1127
	      else
7 7u83 1128
		setsh(son(*arglist), (is_signed(sh(e))? slongsh : ulongsh));
2 7u83 1129
	    }
1130
	    if (last(*arglist))
1131
	      break;
1132
	    arglist = &bro(*arglist);
1133
	  }
1134
	}
7 7u83 1135
	IGNORE cc(sto, to, 1, e, multdo, 1, usereg0);
2 7u83 1136
	return 0;
1137
      };
1138
    case and_tag:
1139
      {
7 7u83 1140
	IGNORE cc(sto, to, 1, e, anddo, 1, usereg0);
2 7u83 1141
	return 0;
1142
      };
1143
    case or_tag:
1144
    case xor_tag:
1145
      {
7 7u83 1146
	IGNORE cc(sto, to, 1, e, notado, 1, usereg0);
2 7u83 1147
	return 0;
1148
      };
1149
    case cont_tag:
1150
    case contvol_tag:
1151
      {
7 7u83 1152
	if (name(e) == contvol_tag)
1153
	  setname(e, cont_tag);
1154
	return cont_arg(sto, to, e, usereg0);
2 7u83 1155
      };
1156
    case field_tag:
1157
      {
7 7u83 1158
	if (!is_o(name(son(e))) || name(e) == cont_tag) {
2 7u83 1159
	  exp temp;
7 7u83 1160
	  cca(sto, to, 1, e);
1161
	  temp = contexp(sto, to);
1162
	  return(scan2(1, temp, son(temp), usereg0));
2 7u83 1163
	}
1164
	else
7 7u83 1165
	  return(scan2(sto, to, son(e), usereg0));
2 7u83 1166
      };
1167
    case reff_tag:
1168
      {
7 7u83 1169
	if (name(son(e)) == addptr_tag) {
1170
	  ap_argsc(sto, to, e);
1171
	  return(0);
2 7u83 1172
	};
1173
 
7 7u83 1174
	ccp(sto, to, 1, e);
1175
	return(0);
2 7u83 1176
      };
1177
    case proc_tag:
1178
    case general_proc_tag:
1179
      {
7 7u83 1180
	IGNORE scan2(1, e, son(e), 1);
1181
	return(0);
2 7u83 1182
      };
1183
    case asm_tag:
1184
      {
7 7u83 1185
	if (props(e)!= 0)
1186
	  failer("~asm not in ~asm_sequence");
1187
	check_asm_seq(son(e), 0);
2 7u83 1188
	proc_has_asm = 1;
7 7u83 1189
	return(0);
2 7u83 1190
      };
1191
 
1192
    case name_tag:
7 7u83 1193
      if (!is_opnd(e)) {
2 7u83 1194
	return 0;
1195
      }
1196
 
1197
	/* DELIBERATE FALL THROUGH */
1198
    default:
7 7u83 1199
      return(usereg0);
2 7u83 1200
  };
1201
}