Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /trunk/src/installers/amd64/common/scan2.c – Rev 6

Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
6 7u83 1
/*
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
/*
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
 
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))
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
210
(int sto, exp to, int sx, exp x)
211
{
212
  exp def, ato, id, tg;
213
  def = contexp(sx, x);
214
  if (name(def)==caller_tag) {	/* position sensitive */
215
    cca(sto, to, 1, def);
216
    return;
217
  }
218
  ato = contexp(sto, to);
219
  id = getexp(sh(ato), bro(ato), (int)(last(ato)), def, nilexp,
220
      0, 1, ident_tag);
221
  tg = getexp(sh(def), bro(def), (int)(last(def)), id, nilexp,
222
      0, 0, name_tag);
223
  pt(id) = tg;
224
  clearlast(def);
225
  if (def != ato) {
226
    bro(def) = ato;
227
    bro(ato) = id;
228
    setlast(ato);
229
    assexp(sto, to, id);
230
    assexp(sx, x, tg);
231
  }
232
  else {
233
    bro(def) = tg;
234
    bro(tg) = id;
235
    setlast(tg);
236
    clearlast(def);
237
    assexp(sto, to, id);
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
267
cc(int sto, exp to, int se, exp e, int(*doit)(exp, int, int), int count,
268
   int usereg0)
269
{
270
  int unused = usereg0;	/* can still use reg0 */
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));
277
    }
278
    else {
279
      if (unused)
280
	return(scan2(se, e, ec, 1));
281
      return(scan2(sto, to, ec, unused));
282
    }
283
  }
284
  else {
285
    unused = cc(sto, to, 0, ec, doit, count + 1, unused);
286
    /* can we still use reg0? */
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));
292
    }
293
    else {
294
      if (unused)
295
	return(scan2(sto, to, ec, 1));
296
      return(scan2(sto, to, ec, unused));
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
314
cc1(int sto, exp to, int se, exp e, int(*doit)(exp, int, int), int count,
315
    int usereg0)
316
{
317
  int unused = ((count == 1)? usereg0 : 0);
318
	/* can we still use reg0? */
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);
325
      return;
326
    }
327
    else {
328
      if (unused) {
329
	IGNORE scan2(se, e, ec, 1);
330
        return;
331
      };
332
      IGNORE scan2(sto, to, ec, unused);
333
      return;
334
    }
335
  }
336
  else {
337
    cc1(sto, to, 0, ec, doit, count + 1, unused);
338
    /* can we still use reg0? */
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);
344
      return;
345
    }
346
    else {
347
      if (unused) {
348
	IGNORE scan2(se, e, ec, 1);
349
	return;
350
      };
351
      IGNORE scan2(sto, to, ec, unused);
352
      return;
353
    };
354
  };
355
}
356
 
357
 
358
/* does cca and forces the declaration to use a register */
359
static void ccp
360
(int sto, exp to, int sx, exp x)
361
{
362
  exp toc;
363
  cca(sto, to, sx, x);
364
  toc = contexp(sto, to);
365
  setusereg(toc);
366
  IGNORE scan2(1, toc, son(toc), 0);
367
  return;
368
}
369
 
370
/* is an operand */
371
static int is_opnd
372
(exp e)
373
{
374
				/* make sure (is_o && is_crc -> !is_opnd) */
375
  unsigned char  n = name(e);
376
  if (n == name_tag) {
377
    if (isvar(son(e)))
378
	return(isglob(son(e)) && !PIC_code);
379
    return(son(son(e))!= nilexp &&
380
	(!isglob(son(e)) || !PIC_code || name(sh(son(e)))!= prokhd ||
381
				(brog(son(e)) -> dec_u.dec_val.extnamed)) &&
382
	(name(son(son(e)))!= ident_tag || !isparam(son(son(e)))));
383
  }
384
  return(
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
406
(int sto, exp to, exp e)
407
{
408
  exp p, a, q;
409
  int  k;
410
  int do1 = 1;
411
 
412
  if (name(son(e)) == reff_tag)
413
    q = son(son(e));
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));
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));
425
    son(c) = r;
426
    son(q) = c;
427
  }
428
 
429
  p = son(q);
430
  a = bro(p);
431
 
432
  if (name(p) == name_tag && isvar(son(p)) && isglob(son(p)))
433
    do1 = 0;
434
 
435
  if (do1)
436
    ccp(1, e, 1, q);
437
 
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)));
441
  else
442
    ccp(1, e, 0, son(q));
443
 
444
  if (do1) {
445
    cca(sto, to, 1, son(e));
446
    cca(sto, to, 1, bro(son(son(e))));
447
  }
448
  else
449
    cca(sto, to, 1, son(e));
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
470
(int sto, exp to, exp e, int usereg0)
471
{
472
  unsigned char  n = name(son(e));
473
 
474
 
475
    if (n == name_tag && isvar(son(son(e))))
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) {
484
      exp s = son(son(e));
485
      if (name(s) == name_tag) {
486
	if (isusereg(son(s)))
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
 
497
      if (name(s) == addptr_tag) {
498
	ap_argsc(sto, to, e);
499
	return 0;
500
      }
501
    };
502
 
503
 
504
    if (n == addptr_tag) {
505
      ap_argsc(sto, to, e);
506
      return 0;
507
    };
508
 
509
  if (n == reff_tag)
510
    ccp(1, e, 1, son(e));
511
  else
512
    ccp(1, e, 1, e);
513
 
514
  cca(sto, to, 1, son(e));
515
 
516
  return 0;
517
}
518
 
519
 
520
/* is assignable */
521
static int is_assable
522
(exp e)
523
{
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)));
527
}
528
 
529
/* doit routine, is not an operand */
530
static int notopnd
531
(exp t, int c, int usereg0)
532
{
533
  UNUSED(c);
534
  if (usereg0) {
535
    if (is_opnd(t))
536
      return(0);
537
    return(!is_assable(t));
538
  };
539
  return(!is_opnd(t));
540
}
541
 
542
static int scan_for_alloca(exp);
543
 
544
static int scan_alloc_args
545
(exp s)
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
555
(exp t)
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
584
(exp t, int c, int usereg0)
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
592
(int sto, exp to, exp e, int usereg0)
593
{
594
  IGNORE cc(sto, to, 1, e, notopnd, 1, usereg0);
595
  return;
596
}
597
 
598
/* doit routine, not assignable */
599
static int notass
600
(exp t, int i, int usereg0)
601
{
602
  UNUSED(i); UNUSED(usereg0);
603
  return(!is_assable(t));
604
}
605
 
606
/* uses cc, requiring all to be assignable */
607
static void all_assable
608
(int sto, exp to, exp e)
609
{
610
  IGNORE cc(sto, to, 1, e, notass, 1, 1);
611
  return;
612
}
613
 
614
/* just used in the next routine */
615
static int is_direct
616
(exp e)
617
{
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)))));
622
}
623
 
624
/* is indirectly addressable */
625
static int is_indable
626
(exp e)
627
{
628
  unsigned char  s = name(e);
629
  if (s == name_tag)
630
    return(1);
631
 
632
  if (s == cont_tag) {
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)))));
638
  };
639
 
640
  return((s == reff_tag && is_direct(son(e))) ||
641
 
642
      s == addptr_tag);
643
}
644
 
645
 
646
/* son must be indirectly addressable */
647
static void indable_son
648
(int sto, exp to, exp e)
649
{
650
  if (!is_indable(son(e))) {
651
    exp ec;
652
    cca(sto, to, 1, e);
653
    ec = contexp(sto, to);
654
    IGNORE scan2(1, ec, son(ec), 0);
655
  }
656
  else
657
    IGNORE scan2(sto, to, son(e), 0);
658
  return;
659
}
660
 
661
 
662
 
663
/* apply scan2 to this bro list, moving "to" along it */
664
static void scanargs
665
(int st, exp e, int usereg0)
666
{
667
  exp t = e;
668
  exp temp;
669
 
670
  while (temp = contexp(st, t), IGNORE scan2(st, t, temp, usereg0),
671
      temp = contexp(st, t), !last(temp)) {
672
    t = contexp(st, t);
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
682
(exp t, int i, int usereg0)
683
{
684
  UNUSED(i);
685
  if (usereg0)
686
    return(0);
687
  if (name(t) == neg_tag)
688
    return(0);
689
  return(!is_opnd(t));
690
}
691
 
692
/* doit routine for mult */
693
static int multdo
694
(exp t, int i, int usereg0)
695
{
696
  UNUSED(i);
697
  return((usereg0)? 0 : !is_opnd(t));
698
}
699
 
700
/* doit routine for and */
701
static int anddo
702
(exp t, int i, int usereg0)
703
{
704
  UNUSED(i);
705
  return((usereg0)? 0 : !is_opnd(t));
706
}
707
 
708
/* doit routine for xor */
709
static int notado
710
(exp t, int i, int usereg0)
711
{
712
  UNUSED(i);
713
  return((usereg0)? 0 : !is_opnd(t));
714
}
715
 
716
/* change offset representation bytes to bits */
717
static void make_bitfield_offset
718
(exp e, exp pe, int spe, shape sha)
719
{
720
  exp omul;
721
  exp val8;
722
  if (name(e) == val_tag)
723
    return;
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);
726
  clearlast(e);
727
  setbro(e, val8);
728
  assexp(spe, pe, omul);
729
}
730
 
731
static void scan_apply_args
732
(int spto, exp pto, int sato, exp ato)
733
{
734
  if (scan_alloc_args(contexp(sato, ato)))
735
    IGNORE cc(spto, pto, sato, ato, no_alloca, 1, 0);
736
  else
737
    IGNORE scanargs(sato, ato, 1);
738
}
739
 
740
/* avoid registers corrupted by dynamic callees */
741
static void cca_for_cees
742
(int sto, exp to, exp e)
743
{
744
  if (name(son(e)) == name_tag) {
745
    if (!isglob(son(son(e))))
746
      set_intnl_call(son(son(e)));
747
    return;
748
  }
749
  if (name(son(e)) == cont_tag && name(son(son(e))) == name_tag) {
750
    if (!isglob(son(son(son(e)))))
751
      set_intnl_call(son(son(son(e))));
752
    return;
753
  }
754
  cca(sto, to, 1, e);
755
  set_intnl_call(contexp(sto, to));
756
}
757
 
758
 
759
static int is_asm_opnd
760
(exp e, int ext)
761
{
762
  unsigned char n = name(e);
763
  if (n == name_tag) {
764
    setvis(son(e));
765
    return 1;
766
  }
767
  if (n == cont_tag && name(son(e)) == name_tag && isvar(son(son(e)))) {
768
    setvis(son(son(e)));
769
    return 1;
770
  }
771
  return(n == val_tag || n == real_tag || n == null_tag ||
772
	(n == reff_tag && name(son(e)) == name_tag));
773
}
774
 
775
static int is_asm_var
776
(exp e, int ext)
777
{
778
  unsigned char n = name(e);
779
  if (n == name_tag && isvar(son(e))) {
780
    setvis(son(e));
781
    return 1;
782
  }
783
  return 0;
784
}
785
 
786
void check_asm_seq
787
(exp e, int ext)
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)) ||
792
	(asm_var(e) && is_asm_var(son(e), ext)))
793
      return;
794
  }
795
  if (name(e) == seq_tag) {
796
    exp t = son(son(e));
797
    for (;;) {
798
      check_asm_seq(t, ext);
799
      if (last(t))
800
	break;
801
      t = bro(t);
802
    }
803
    check_asm_seq(bro(son(e)), ext);
804
  }
805
  else
806
  if (name(e)!= top_tag)
807
    failer("illegal ~asm");
808
  return;
809
}
810
 
811
 
812
 
813
/* main scan routine */
814
int scan2
815
(int sto, exp to, exp e, int usereg0)
816
{
817
  switch (name(e)) {
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 */
833
	  return(0);
834
	scanargs(1, e, 1);
835
	return(0);
836
      };
837
 
838
    case labst_tag:
839
      {
840
	IGNORE scan2(0, son(e), bro(son(e)), 1);
841
	return(0);
842
      };
843
    case ident_tag:
844
      {
845
	IGNORE scan2(0, son(e), bro(son(e)), 0);
846
	IGNORE scan2(1, e, son(e), 0);
847
	return(0);
848
      };
849
    case seq_tag:
850
      {
851
	scanargs(1, son(e), 1);
852
	IGNORE scan2(0, son(e), bro(son(e)), 1);
853
	return(0);
854
      };
855
 
856
    case local_free_tag:
857
    case long_jump_tag:
858
    case return_to_label_tag:
859
      {
860
	all_assable(sto, to, e);
861
	return(0);
862
      };
863
 
864
    case offset_add_tag:
865
    case offset_subtract_tag:
866
      {
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);
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
      {
891
	IGNORE all_opnd(sto, to, e, usereg0);
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
      {
899
	IGNORE all_opnd(sto, to, e, 0);
900
	return 0;
901
      };
902
    case set_stack_limit_tag:
903
      {
904
	exp lim = find_stlim_var();
905
	setbro(lim, son(e));
906
	setson(e, lim);
907
	setname(e, ass_tag);
908
	return scan2(sto, to, e, usereg0);
909
      };
910
    case chvar_tag:
911
      {
912
	int ur = usereg0 && name(son(e))!= cont_tag;
913
	IGNORE all_opnd(sto, to, e, ur);
914
	return 0;
915
      };
916
 
917
    case test_tag:
918
    case absbool_tag:
919
      {
920
	if ((name(sh(son(e))) >= shrealhd &&
921
	      name(sh(son(e))) <= doublehd))
922
	  IGNORE all_opnd (sto, to, e, 0);/* all arguments must be operands */
923
	else
924
	  IGNORE all_opnd(sto, to, e, usereg0);
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
      {
936
	if (name(sh(e)) == u64hd) {
937
	  exp * bottom = &bro(son(e));
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));
942
	      *bottom = son(*bottom);
943
	    }
944
	    else
945
	      setsh(son(*bottom), ulongsh);
946
	  }
947
	}
948
	cc1(sto, to, 1, e, notopnd, 1, usereg0);
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
      {
959
	cc1(sto, to, 1, e, notopnd, 1, usereg0);
960
	return 0;
961
	/* all arguments except possibly the first must be operands */
962
      };
963
 
964
    case offset_div_by_int_tag:
965
      {
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),
968
		e, 1, bro(son(e)), nilexp, 0, 0, chvar_tag);
969
	  setbro(bro(son(e)), ch);
970
	  setbro(son(e), ch);
971
	};
972
	cc1(sto, to, 1, e, notopnd, 1, usereg0);
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 */
996
	  setname(e, ass_tag);
997
	IGNORE cont_arg(sto, to, e, 0);
998
	/* special check for references */
999
	if (!is_assable(bro(son(e)))) {
1000
	  /* second argument must be assignable */
1001
	  cca(sto, to, 0, son(e));
1002
	  toc = contexp(sto, to);
1003
	  IGNORE scan2(1, toc, son(toc), 1);
1004
	}
1005
	else
1006
	  IGNORE scan2(sto, to, bro(son(e)), 1);
1007
	return(0);
1008
      };
1009
    case apply_tag:
1010
      {
1011
	if (builtinproc(e)) {	/* son must be named global */
1012
	  if (!last(son(e)))
1013
	    IGNORE cc(sto, to, 0, son(e), notopnd, 1, 0);
1014
	  return 0;
1015
	}
1016
        if (!last(son(e)))
1017
	  scan_apply_args(sto, to, 0, son(e));
1018
	indable_son(sto, to, e);
1019
	return(0);
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));
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)
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)
1039
	  cca_for_cees(sto, to, e);
1040
	return(0);
1041
      };
1042
    case tail_call_tag:
1043
      {
1044
	exp cees = bro(son(e));
1045
	has_tail_call = 1;
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)
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)
1054
	  cca_for_cees(sto, to, e);
1055
	return(0);
1056
      };
1057
    case goto_lv_tag:
1058
      {
1059
	indable_son(sto, to, e);
1060
	return(0);
1061
      };
1062
    case res_tag:
1063
    case untidy_return_tag:
1064
      {
1065
	if ((name(sh(son(e))) == cpdhd) &&
1066
	    (name(son(e))!= cont_tag ||
1067
	      name(son(son(e)))!= name_tag ||
1068
	      !isvar(son(son(son(e)))))) { /* gcc compatibility */
1069
	  exp ec;
1070
	  cca(sto, to, 1, e);
1071
	  ec = contexp(sto, to);
1072
	  IGNORE scan2(1, ec, son(ec), 0);
1073
	  return 0;
1074
	}
1075
	else  {
1076
	  IGNORE(scan2(sto, to, son(e), 1));
1077
	  return 0;
1078
	};
1079
      };
1080
    case case_tag:
1081
      {
1082
	exp toc;
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);
1089
	}
1090
	else
1091
	  IGNORE scan2(sto, to, son(e), 0);
1092
	return(0);
1093
      };
1094
    case plus_tag:
1095
      {
1096
	IGNORE cc(sto, to, 1, e, plusdo, 1, usereg0);
1097
	return 0;
1098
      };
1099
    case addptr_tag:
1100
      {
1101
	exp f = father(e);
1102
	exp new_r = getexp(sh(e), bro(e), (int)(last(e)),
1103
                             e, nilexp, 0,
1104
	    0, reff_tag);
1105
	exp * ref = refto(f, e);
1106
	setlast(e);
1107
	bro(e) = new_r;
1108
	*ref = new_r;
1109
	ap_argsc(sto, to, new_r);
1110
	return(0);
1111
      };
1112
    case mult_tag:
1113
      {
1114
	if (shape_size(sh(e)) == 64 && optop(e)) {
1115
	  exp * arglist = &son(e);
1116
	  for (;;) {
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));
1121
		if (last(*arglist))
1122
		  setlast(son(*arglist));
1123
		else
1124
		  clearlast(son(*arglist));
1125
		*arglist = son(*arglist);
1126
	      }
1127
	      else
1128
		setsh(son(*arglist), (is_signed(sh(e))? slongsh : ulongsh));
1129
	    }
1130
	    if (last(*arglist))
1131
	      break;
1132
	    arglist = &bro(*arglist);
1133
	  }
1134
	}
1135
	IGNORE cc(sto, to, 1, e, multdo, 1, usereg0);
1136
	return 0;
1137
      };
1138
    case and_tag:
1139
      {
1140
	IGNORE cc(sto, to, 1, e, anddo, 1, usereg0);
1141
	return 0;
1142
      };
1143
    case or_tag:
1144
    case xor_tag:
1145
      {
1146
	IGNORE cc(sto, to, 1, e, notado, 1, usereg0);
1147
	return 0;
1148
      };
1149
    case cont_tag:
1150
    case contvol_tag:
1151
      {
1152
	if (name(e) == contvol_tag)
1153
	  setname(e, cont_tag);
1154
	return cont_arg(sto, to, e, usereg0);
1155
      };
1156
    case field_tag:
1157
      {
1158
	if (!is_o(name(son(e))) || name(e) == cont_tag) {
1159
	  exp temp;
1160
	  cca(sto, to, 1, e);
1161
	  temp = contexp(sto, to);
1162
	  return(scan2(1, temp, son(temp), usereg0));
1163
	}
1164
	else
1165
	  return(scan2(sto, to, son(e), usereg0));
1166
      };
1167
    case reff_tag:
1168
      {
1169
	if (name(son(e)) == addptr_tag) {
1170
	  ap_argsc(sto, to, e);
1171
	  return(0);
1172
	};
1173
 
1174
	ccp(sto, to, 1, e);
1175
	return(0);
1176
      };
1177
    case proc_tag:
1178
    case general_proc_tag:
1179
      {
1180
	IGNORE scan2(1, e, son(e), 1);
1181
	return(0);
1182
      };
1183
    case asm_tag:
1184
      {
1185
	if (props(e)!= 0)
1186
	  failer("~asm not in ~asm_sequence");
1187
	check_asm_seq(son(e), 0);
1188
	proc_has_asm = 1;
1189
	return(0);
1190
      };
1191
 
1192
    case name_tag:
1193
      if (!is_opnd(e)) {
1194
	return 0;
1195
      }
1196
 
1197
	/* DELIBERATE FALL THROUGH */
1198
    default:
1199
      return(usereg0);
1200
  };
1201
}