Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
2
    Copyright (c) 1993 Open Software Foundation, Inc.
3
 
4
 
5
    All Rights Reserved
6
 
7
 
8
    Permission to use, copy, modify, and distribute this software
9
    and its documentation for any purpose and without fee is hereby
10
    granted, provided that the above copyright notice appears in all
11
    copies and that both the copyright notice and this permission
12
    notice appear in supporting documentation.
13
 
14
 
15
    OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
16
    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
17
    PARTICULAR PURPOSE.
18
 
19
 
20
    IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
21
    CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22
    LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
23
    NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
24
    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
*/
26
 
27
/*
28
    		 Crown Copyright (c) 1997
29
 
30
    This TenDRA(r) Computer Program is subject to Copyright
31
    owned by the United Kingdom Secretary of State for Defence
32
    acting through the Defence Evaluation and Research Agency
33
    (DERA).  It is made available to Recipients with a
34
    royalty-free licence for its use, reproduction, transfer
35
    to other parties and amendment for any purpose not excluding
36
    product development provided that any such use et cetera
37
    shall be deemed to be acceptance of the following conditions:-
38
 
39
        (1) Its Recipients shall ensure that this Notice is
40
        reproduced upon any copies or amended versions of it;
41
 
42
        (2) Any amended version of it shall be clearly marked to
43
        show both the nature of and the organisation responsible
44
        for the relevant amendment or amendments;
45
 
46
        (3) Its onward transfer from a recipient to another
47
        party shall be deemed to be that party's acceptance of
48
        these conditions;
49
 
50
        (4) DERA gives no warranty or assurance as to its
51
        quality or suitability for any purpose and DERA accepts
52
        no liability whatsoever in relation to any use to which
53
        it may be put.
54
*/
55
 
56
 
57
 
58
/**********************************************************************
59
$Author: release $
60
$Date: 1998/02/04 15:49:08 $
61
$Revision: 1.2 $
62
$Log: regexps.c,v $
63
 * Revision 1.2  1998/02/04  15:49:08  release
64
 * Added OSF copyright message.
65
 *
66
 * Revision 1.1.1.1  1998/01/17  15:55:57  release
67
 * First version to be checked into rolling release.
68
 *
69
 * Revision 1.4  1996/11/18  15:50:28  pwe
70
 * correct alias with bitfields, and case odds
71
 *
72
 * Revision 1.3  1996/10/11  10:51:19  pwe
73
 * clear_dep_reg v current-env_tag
74
 *
75
 * Revision 1.2  1996/10/04  16:04:08  pwe
76
 * add banners and mod for PWE ownership
77
 *
78
**********************************************************************/
79
 
80
 
81
#include "config.h"
82
#include "memtdf.h"
83
#include "codegen.h"
84
#include "maxminmacs.h"		/* for absval() */
85
 
86
#include "myassert.h"
87
#include "comment.h"
88
 
89
#include "regexps.h"
90
#include "flags.h"
91
#include "check.h"
92
 
93
struct regpeept
94
{
95
  ans inans;
96
  exp keptexp;
97
  bool iscont;
98
};
99
 
100
typedef struct regpeept regpeep;
101
 
102
#define FR_OFFSET		KEPT_FREG_OFFSET	/* 32 */
103
#define	LAST_ALL_REGS		(FR_OFFSET+FR_LAST)	/* 63 */
104
 
105
regpeep regexps[LAST_ALL_REGS+1];	/* [0:31] fix pt - [32:63] floating pt */
106
 
107
static bool sim_exp PROTO_S ((exp, exp));
108
 
109
 
110
/* both either floating or fixed and same size and alignment */
111
bool keep_eq_size PROTO_N ((as,bs)) PROTO_T (shape as X shape bs)
112
{
113
  bool as_flt = is_floating(name(as));
114
  bool bs_flt = is_floating(name(bs));
115
 
116
  if (as_flt != bs_flt)
117
    return 0;			/* dissimilar float/fixed */
118
 
119
  return (shape_size(as) == shape_size(bs) && shape_align(as) == shape_align(bs));
120
}
121
 
122
 
123
static bool sim_explist PROTO_N ((al,bl)) PROTO_T (exp al X exp bl)
124
{
125
  if (al == nilexp && bl == nilexp)
126
    return (1);
127
  if (al == nilexp || bl == nilexp)
128
    return (0);
129
  if (!sim_exp(al, bl))
130
    return (0);
131
  if (last(al) && last(bl))
132
    return (1);
133
  if (last(al) || last(bl))
134
    return (0);
135
  return (sim_explist(bro(al), bro(bl)));
136
}
137
 
138
 
139
static bool sim_exp PROTO_N ((a,b)) PROTO_T (exp a X exp b)
140
{
141
 
142
  /*
143
   * basically eq_exp except equal shapes requirement is weakened to equal
144
   * sizes and alignments
145
   */
146
  if (name(a) == name(b))
147
  {
148
    if (name(a) == name_tag)
149
    {
150
      /* See if both are name_tags for same ident
151
	 with same offsets and same size and alignment */
152
      return (son(a) == son(b) && no(a) == no(b) &&
153
	      keep_eq_size(sh(a), sh(b)));
154
    }
155
    /* If it is not is_a 
156
       OR 
157
       if they are not the same size and alignment and same
158
     register type 
159
     */
160
    if (!is_a(name(a)) || !keep_eq_size(sh(a), sh(b)))
161
    {
162
      return (0);
163
    }
164
    if(name(a)==float_tag)
165
    {
166
      return eq_exp(son(a),son(b));
167
      /* float_tag is special since we could have e.g float (-1 slongsh) float (-1 ulongsh) */
168
    }
169
 
170
    return (no(a) == no(b) && sim_explist(son(a), son(b)));
171
  }
172
  return (0);
173
}
174
 
175
 
176
void clear_all PROTO_Z ()
177
{
178
  /* forget all register<->exp associations */
179
  int i;
180
 
181
  for (i = 0; i <= LAST_ALL_REGS; i++)
182
  {
183
    regexps[i].keptexp = nilexp;
184
    setregalt(regexps[i].inans, 0);
185
  }
186
}
187
 
188
 
189
void clear_reg PROTO_N ((i)) PROTO_T (int i)
190
{
191
  /* forget reg i - exp association */
192
  i = absval(i);
193
  if (i >= 0 && i <= LAST_ALL_REGS)
194
  {
195
    regexps[i].keptexp = nilexp;
196
    setregalt(regexps[i].inans, 0);
197
  }
198
}
199
 
200
 
201
/* find if e has already been evaluated into a register low_reg..hi_reg 
202
 
203
   Register tracking:
204
   The array regexps[] is an array of regpeep structures
205
   The elements of the structure regpeep are :
206
 
207
   ans inans;     This helps specify where the exp came from 
208
   exp keptexp;   The exp 
209
   bool iscont;   This specifies whether or not
210
 
211
   */
212
static ans iskept_regrange PROTO_N ((e,low_reg,hi_reg)) PROTO_T (exp e X int low_reg X int hi_reg)
213
{
214
  int i;
215
  ans aa;
216
  setregalt(aa, 0);		/* nilans until we know better */
217
 
218
  /* reg tracking of unions unsafe, as views of location can differ */
219
  /* +++ improve this */
220
  if (name(sh(e)) == cpdhd)
221
  {
222
    return aa;
223
  }
224
 
225
 
226
  for (i = low_reg; i <= hi_reg; i++)
227
  {
228
    exp ke = regexps[i].keptexp;
229
 
230
    if (ke != nilexp)
231
    {
232
      /* There is an association with register i */
233
      bool isc = regexps[i].iscont;
234
 
235
      ASSERT(!IS_R_TMP(i));	/* should not track R_TMP */
236
 
237
      if (
238
	  ((!isc && sim_exp(ke, e)) ||
239
	   (name(e) == cont_tag && isc && keep_eq_size(sh(ke), sh(e))
240
	    && sim_exp(ke, son(e)) && al1(sh(son(e))) == al1(sh(ke)))
241
	   )
242
	)
243
      {
244
	aa = (regexps[i].inans);
245
 
246
	FULLCOMMENT4("iskept found 1: reg=%d isc=%d name(e)=%d name(son(e))=%d",
247
		     i, isc, name(e), name(son(e)));
248
	COMMENT1("iskept found: no = %d",no(e));
249
 
250
 
251
	switch (aa.discrim)
252
	{
253
	case notinreg:
254
	  {
255
	    if (!aa.val.instoreans.adval)
256
	    {
257
 
258
	      /*
259
	       * the expression is given indirectly - it may have also been
260
	       * loaded into a register
261
	       */
262
	      continue;
263
	    }
264
	    /* else ... */
265
	  }
266
	default:
267
	  return aa;
268
	}
269
      }
270
      else if (name(ke) == cont_tag && !isc)
271
      {
272
	ans aq;
273
 
274
	aq = regexps[i].inans;
275
 
276
	if (aq.discrim == notinreg)
277
	{
278
	  instore is;
279
 
280
	  is = insalt(aq);
281
	  if (!is.adval && is.b.offset == 0 && IS_FIXREG(is.b.base)
282
	      && sim_exp(son(ke), e))
283
	  {
284
 
285
	    /*
286
	     * the contents of req expression is here as a reg-offset
287
	     */
288
	    is.adval = 1;
289
	    setinsalt(aq, is);
290
 
291
	    FULLCOMMENT4("iskept found 2: reg=%d isc=%d name(e)=%d name(son(e))=%d",
292
			 i, isc, name(e), name(son(e)));
293
 
294
	    return aq;
295
	  }
296
	}
297
      }
298
      else if (name(ke) == reff_tag && !isc)
299
      {
300
	ans aq;
301
 
302
	aq = regexps[i].inans;
303
	if (aq.discrim == notinreg)
304
	{
305
	  instore is;
306
 
307
	  is = insalt(aq);
308
	  if (is.adval && is.b.offset == (no(ke) / 8)
309
	      && IS_FIXREG(is.b.base)
310
	      && sim_exp(son(ke), e))
311
	  {
312
 
313
	    /*
314
	     * a ref select of req expression is here as a reg-offset
315
	     */
316
	    is.adval = 1;
317
	    is.b.offset = 0;
318
	    setinsalt(aq, is);
319
 
320
	    FULLCOMMENT4("iskept found 3: reg=%d isc=%d name(e)=%d name(son(e))=%d",
321
			 i, isc, name(e), name(son(e)));
322
 
323
	    return aq;
324
	  }
325
	}
326
      }
327
    }
328
  }
329
  return aa;
330
}
331
 
332
 
333
/* find if e has already been evaluated into register 'reg' */
334
ans iskept_inreg PROTO_N ((e,reg)) PROTO_T (exp e X int reg)
335
{
336
  return iskept_regrange(e, reg, reg);
337
}
338
 
339
 
340
/* find if e has already been evaluated into a fixed point register */
341
ans iskept_reg PROTO_N ((e)) PROTO_T (exp e)
342
{
343
  return iskept_regrange(e, 0, R_LAST);
344
}
345
 
346
 
347
/* find if e has already been evaluated into a floating point register */
348
ans iskept_freg PROTO_N ((e)) PROTO_T (exp e)
349
{
350
  return iskept_regrange(e, FR_OFFSET, LAST_ALL_REGS);
351
}
352
 
353
 
354
/* find if e has already been evaluated into any register */
355
ans iskept PROTO_N ((e)) PROTO_T (exp e)
356
{
357
  return iskept_regrange(e, 0, LAST_ALL_REGS);
358
}
359
 
360
 
361
/* return reg if 'a' can is in fixed reg */
362
int ans_reg PROTO_N ((aa)) PROTO_T (ans aa)
363
{
364
  if (aa.discrim == inreg && regalt(aa) != 0)
365
  {
366
    /* the same expression has already been evaluated into a reg */
367
    return regalt(aa);
368
  }
369
 
370
  if (aa.discrim == notinreg)
371
  {
372
    instore is; is = insalt(aa);	/* no init to avoid IBM cc bug */
373
 
374
    if (is.adval && is.b.offset == 0)
375
    {
376
      /* the same expression has already been evaluated into a reg */
377
      return is.b.base;
378
    }
379
  }
380
 
381
  return R_NO_REG;
382
}
383
 
384
 
385
/* set up exp - address association */
386
void keepexp PROTO_N ((e,loc)) PROTO_T (exp e X ans loc)
387
{
388
  int pos=0;
389
 
390
  switch (loc.discrim)
391
  {
392
  case insomereg:
393
  case insomefreg:
394
    {
395
      fail("Keep ? reg");
396
    }
397
  case inreg:
398
    {
399
      pos = regalt(loc);
400
      break;
401
    }
402
  case infreg:
403
    {
404
      pos = fregalt(loc).fr + FR_OFFSET;
405
      break;
406
    }
407
  case notinreg:
408
    {
409
      pos = insalt(loc).b.base;
410
      if (!IS_FIXREG(pos))
411
	return;
412
    }
413
 
414
  }
415
 
416
  ASSERT(pos >= 0 && pos <= LAST_ALL_REGS);
417
 
418
  if (IS_R_TMP(pos))
419
    return;			/* don't track R_TMP which is used outside
420
				 * tracking scheme */
421
 
422
  regexps[pos].keptexp = e;
423
  regexps[pos].inans = loc;
424
  regexps[pos].iscont = 0;
425
  COMMENT2("keepexp : reg %d kept name is %d",pos,name(e));
426
}
427
 
428
 
429
/* set up cont(e)-reg association */
430
/* if 0=<reg<=31  this means a fixed point register
431
   if 31<reg<=63  this means a float point register single precision
432
   if -63<=reg<-31 this means a float point register double precision
433
   */
434
void keepcont PROTO_N ((e,reg)) PROTO_T (exp e X int reg)
435
{
436
  freg fr;
437
  int z = absval(reg);
438
 
439
  if (z >= FR_OFFSET)
440
  {
441
    fr.dble = (reg < 0);
442
    fr.fr = z - FR_OFFSET;
443
    setfregalt(regexps[z].inans, fr);
444
  }
445
  else
446
  {
447
    instore is;
448
 
449
    if (IS_R_TMP(z))
450
      return;			/* don't track R_TMP which is used outside
451
				 * tracking scheme */
452
 
453
    is.b.base = reg;
454
    is.b.offset = 0;
455
    is.adval = 1;
456
    setinsalt(regexps[z].inans, is);
457
  }
458
 
459
  ASSERT(z >= 0 && z <= LAST_ALL_REGS);
460
  regexps[z].keptexp = e;
461
  regexps[z].iscont = 1;
462
  COMMENT2("keepcont : reg %d kept name is %d",z,name(e));
463
 
464
}
465
 
466
 
467
/* keepreg keeps the exp e */
468
/* if 0=<reg<=31  this means a fixed point register
469
   if 31<reg<=63  this means a float point register single precision
470
   if -63<=reg<-31 this means a float point register double precision
471
   */
472
void keepreg PROTO_N ((e,reg)) PROTO_T (exp e X int reg)
473
{
474
  freg fr;
475
  int z = absval(reg);
476
 
477
  if (z >= FR_OFFSET)
478
  {
479
    /* It is a float register */
480
    /* HACK: if reg <0 then it is double 
481
       otherwise it is single precision */
482
    fr.dble = (reg < 0);
483
    fr.fr = z - FR_OFFSET;
484
    setfregalt(regexps[z].inans, fr);
485
  }
486
  else
487
  {
488
    instore is;
489
    if (IS_R_TMP(z))
490
    {
491
      return;			/* don't track R_TMP which is used outside
492
				 * tracking scheme */
493
    }
494
    is.b.base = reg;
495
    is.b.offset = 0;
496
    is.adval = 1;
497
    setinsalt(regexps[z].inans, is);
498
  }
499
 
500
  ASSERT(z >= 0 && z <= LAST_ALL_REGS);
501
  regexps[z].keptexp = e;
502
  regexps[z].iscont = 0;
503
  COMMENT3("keepreg : reg %d kept name is %d no %d",z,name(e),no(e));
504
}
505
 
506
bool couldeffect PROTO_S ((exp , exp ));
507
 
508
/* could 'e' be 'lhs' */
509
bool couldbe PROTO_N ((e,lhs)) PROTO_T (exp e X exp lhs )/* is var name_tag exp or 0 meaning cont */
510
{
511
  int ne = name(e);
512
  exp s = son(e);
513
 
514
  if (ne == name_tag)
515
  {
516
    if (lhs != 0 && s == son(lhs))
517
    {
518
      return 1;
519
    }
520
    if (isvar(s))
521
    {
522
      return (lhs == 0 && ( isglob(s) || isvis(s) ) );
523
    }
524
    if (IS_A_PROC(s))
525
      return (lhs == 0);
526
    if (son(s) == nilexp)
527
      return 1;
528
    return couldbe(son(s), lhs);
529
  }
530
  if (ne == cont_tag)
531
  {
532
    if (lhs != 0 && name(s) == name_tag && son(s) != nilexp)
533
    {
534
      return (son(s) == son(lhs) || isvis(son(lhs)) || isvis(son(s)));
535
    }
536
    return 1;
537
  }
538
  if (ne == reff_tag || ne == field_tag)
539
  {
540
    return couldbe(s, lhs);
541
  }
542
  if (ne == addptr_tag || ne == subptr_tag)
543
  {
544
    return (couldbe(s, lhs) || couldeffect(bro(s), lhs));
545
  }
546
 
547
  return 1;
548
 
549
}
550
 
551
 
552
/* could alteration to z effect e? */
553
bool couldeffect PROTO_N ((e,z)) PROTO_T (exp e X exp z )/* a name or zero */ 
554
{
555
  int ne = name(e);
556
 
557
  if (ne == cont_tag)
558
  {
559
    return couldbe(son(e), z);
560
  }
561
  if (ne == name_tag)
562
  {
563
    if (isvar(son(e)))
564
      return (z == 0 && isvis(son(e)));
565
    if (IS_A_PROC(son(e)))
566
      return 0;
567
    if (son(son(e)) == nilexp)
568
      return 1 /* could it happen? */ ;
569
 
570
    return couldeffect(son(son(e)), z);
571
 
572
  }
573
  if (ne < plus_tag || ne == contvol_tag)
574
    return 1;
575
 
576
  e = son(e);
577
 
578
  while (e != nilexp)
579
  {
580
    if (couldeffect(e, z))
581
      return 1;
582
    if (last(e))
583
      return 0;
584
    e = bro(e);
585
  }
586
  return 0;
587
}
588
 
589
 
590
/* does e depend on z */
591
bool dependson PROTO_N ((e,isc,z)) PROTO_T (exp e X bool isc X exp z)
592
{
593
  if (e == nilexp)
594
  {
595
    return 0;
596
  }
597
  for (;;)
598
  {
599
    if (name(z) == reff_tag || name(z) == addptr_tag ||
600
	name(z) == subptr_tag)
601
    {
602
      z = son(z);
603
    }
604
 
605
    if (name(z) != name_tag)
606
    {
607
      if (name(z) != cont_tag)
608
	return 1;
609
      z = 0;
610
      break;
611
    }
612
 
613
    if (isvar(son(z)))
614
      break;
615
    if (IS_A_PROC(son(z)))
616
    {
617
      z = 0;
618
      break;
619
    }
620
    if (son(son(z)) == nilexp)
621
      return 1;			/* can it happen? */
622
    z = son(son(z));
623
  }
624
 
625
  /* z is now unambiguous variable name or 0 meaning some contents */
626
 
627
  return ((isc) ? couldbe(e, z) : couldeffect(e, z));
628
}
629
 
630
 
631
/* remove association of any register which depends on lhs */
632
void clear_dep_reg PROTO_N ((lhs)) PROTO_T (exp lhs)
633
{
634
  int i;
635
 
636
  for (i = 0; i <= LAST_ALL_REGS; i++)
637
  {
638
    if (regexps[i].keptexp != nilexp)
639
    {
640
      switch(name(regexps[i].keptexp))
641
      {
642
      case val_tag:
643
      case null_tag:
644
      case real_tag:
645
      case string_tag:
646
      case name_tag:
647
      case current_env_tag:
648
	{
649
	  if (!regexps[i].iscont)
650
	  {
651
	    /* constant value, cannot be changed by assign */
652
	    continue;
653
	  }
654
	}
655
	/*FALLTHROUGH*/
656
 
657
      default:
658
	{
659
          if (dependson(regexps[i].keptexp, regexps[i].iscont, lhs))
660
          {
661
            FULLCOMMENT2("clear_dep_reg: reg=%d iscont=%d", i, regexps[i].iscont);
662
            regexps[i].keptexp = nilexp;
663
            setregalt(regexps[i].inans, 0);
664
          }
665
	}
666
      }
667
    }
668
  }
669
}