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
			    VERSION INFORMATION
61
			    ===================
62
 
63
--------------------------------------------------------------------------
64
$Header: /u/g/release/CVSROOT/Source/src/installers/680x0/common/where.c,v 1.1.1.1 1998/01/17 15:55:50 release Exp $
65
--------------------------------------------------------------------------
66
$Log: where.c,v $
67
 * Revision 1.1.1.1  1998/01/17  15:55:50  release
68
 * First version to be checked into rolling release.
69
 *
70
Revision 1.3  1997/11/09 14:07:59  ma
71
Removed issigned function.
72
 
73
Revision 1.2  1997/10/29 10:22:32  ma
74
Replaced use_alloca with has_alloca.
75
 
76
Revision 1.1.1.1  1997/10/13 12:43:01  ma
77
First version.
78
 
79
Revision 1.5  1997/10/13 08:50:19  ma
80
Made all pl_tests for general proc & exception handling pass.
81
 
82
Revision 1.4  1997/09/25 06:45:41  ma
83
All general_proc tests passed
84
 
85
Revision 1.3  1997/06/18 10:09:46  ma
86
Checking in before merging with Input Baseline changes.
87
 
88
Revision 1.2  1997/04/20 11:30:43  ma
89
Introduced gcproc.c & general_proc.[ch].
90
Added cases for apply_general_proc next to apply_proc in all files.
91
 
92
Revision 1.1.1.1  1997/03/14 07:50:21  ma
93
Imported from DRA
94
 
95
 * Revision 1.1.1.1  1996/09/20  10:57:00  john
96
 *
97
 * Revision 1.2  1996/07/05  14:30:14  john
98
 * Changes for spec 3.1
99
 *
100
 * Revision 1.1.1.1  1996/03/26  15:45:19  john
101
 *
102
 * Revision 1.3  94/02/21  16:06:54  16:06:54  ra (Robert Andrews)
103
 * Change the argument to find_reg_ind to an int.
104
 *
105
 * Revision 1.2  93/03/03  14:51:05  14:51:05  ra (Robert Andrews)
106
 * Use correct number of registers in initialization routine.
107
 *
108
 * Revision 1.1  93/02/22  17:17:05  17:17:05  ra (Robert Andrews)
109
 * Initial revision
110
 *
111
--------------------------------------------------------------------------
112
*/
113
 
114
 
115
#include "config.h"
116
#include "common_types.h"
117
#include "exp.h"
118
#include "expmacs.h"
119
#include "externs.h"
120
#include "install_fns.h"
121
#include "shapemacs.h"
122
#include "tags.h"
123
#include "fbase.h"
124
#include "flpt.h"
125
#include "mach.h"
126
#include "tests.h"
127
#include "where.h"
128
#include "coder.h"
129
#include "utility.h"
130
#include "translate.h"
131
#include "evaluate.h"
132
#define REGISTER_SIZES
133
#include "instr_aux.h"
134
#include "special_exps.h"
7 7u83 135
static int find_where(exp);
2 7u83 136
 
137
/*
138
    MACROS
139
 
140
    These are used as convenient shorthands.
141
*/
142
 
7 7u83 143
#define  new_exp(A, B, C, D)	getexp(A, nilexp, 0, B, nilexp, L0, C, D)
144
#define  ptrsh		 	ptr_shape(slongsh)
2 7u83 145
 
146
 
147
/*
148
    WHAT SORT OF REGISTER SHOULD WE PUT SOMETHING OF A GIVEN SHAPE IN?
149
 
150
    The shape sha is examined and the appropriate register type -
151
    Dreg, Areg or Freg is returned.
152
*/
153
 
154
int shtype
7 7u83 155
(shape sha)
2 7u83 156
{
7 7u83 157
    char n = name(sha);
158
    if (n >= scharhd && n <= ulonghd) return(Dreg);
159
    if (n >= shrealhd && n <= doublehd) return(Freg);
160
    if (n != bitfhd && n != nofhd && n != cpdhd) return(Areg);
161
    return(shape_size(sha) <= 32 ? Dreg : Areg);
2 7u83 162
}
163
 
164
 
165
/*
166
    REGISTERS USED IN OPERAND
167
 
168
    This is a bitmask of all the registers used in an operand.  It is
169
    built up by find_where.
170
*/
171
 
7 7u83 172
static bitpattern where_regmsk;
2 7u83 173
 
174
 
175
/*
176
    FIND ADDRESSING TYPE OF A REGISTER INDIRECT WITH DISPLACEMENT
177
 
178
    The addressing type of a register indirect operand with register
179
    mask rgs is returned.  This is RegInd if rgs corresponds to an
180
    A-register, and Other otherwise.
181
*/
182
 
183
static int find_reg_ind
7 7u83 184
(int r)
2 7u83 185
{
7 7u83 186
    bitpattern rgs = (bitpattern)r;
187
    where_regmsk |= rgs;
2 7u83 188
    /* If rgs corresponds to an A register, we have an effective address */
7 7u83 189
    if (rgs & areg_msk) return(RegInd);
190
    return(Other);
2 7u83 191
}
192
 
193
 
194
/*
195
    FIND ADDRESSING TYPE OF AN INDEX OPERAND
196
 
197
    The addressing type of the operand given by e1 indexed by e2 times
198
    some constant is returned.
199
*/
200
 
201
static int find_ind
7 7u83 202
(exp e1, exp e2)
2 7u83 203
{
7 7u83 204
    int f1 = find_where(e1);
205
    int f2 = find_where(e2);
206
    if (f1 == Other) return(Other);
207
    if (f2 == Dreg || f2 == Areg) return(EffAddr);
208
    return(Other);
2 7u83 209
}
210
 
211
 
212
/*
213
    FIND ADDRESSING TYPE OF AN OPERAND
214
 
215
    The addressing type of the operand e is returned.  Meanwhile the
216
    bitmask of all the registers used in e is built up in where_regmsk.
217
    This routine should be compared with operand.
218
*/
219
 
220
static int find_where
7 7u83 221
(exp e)
2 7u83 222
{
7 7u83 223
    bitpattern rm;
224
    switch (name(e)) {
2 7u83 225
 
7 7u83 226
	case val_tag:
227
	case null_tag:
228
	    return(Value);
2 7u83 229
 
7 7u83 230
	case real_tag:
231
	case string_tag:
232
	case res_tag:
233
	    return(External);
2 7u83 234
 
7 7u83 235
	case regpair_tag:
236
	    return(RegPair);
2 7u83 237
 
7 7u83 238
	case apply_general_tag:
239
	case tail_call_tag:
240
	case apply_tag:
241
	    return(EffAddr);
2 7u83 242
 
7 7u83 243
	case field_tag:
244
	    return(find_where(son(e)));
2 7u83 245
 
7 7u83 246
	case ident_tag:
247
	case labst_tag: {
248
	    switch (ptno(e)) {
2 7u83 249
#ifndef tdf3
7 7u83 250
                case par2_pl:
251
                case par3_pl:
2 7u83 252
#endif
253
 
7 7u83 254
		case par_pl: return(Parameter);
255
		case var_pl: return(Variable);
256
		case reg_pl: {
257
		    rm = (bitpattern)no(e);
258
		    where_regmsk |= rm;
2 7u83 259
		    /* A register, but what type? */
7 7u83 260
		    if (rm & dreg_msk) return(Dreg);
261
		    if (rm & areg_msk) return(Areg);
262
		    return(Freg);
2 7u83 263
		}
264
	    }
7 7u83 265
	    break;
2 7u83 266
	}
267
 
7 7u83 268
	case name_tag: {
269
	    exp id = son(e);
2 7u83 270
#if 0
7 7u83 271
	    if ((name(sh(e)) == prokhd) &&
272
	      ((son(id) == nilexp) || (name(son(id)) == proc_tag) ||
273
		(name(son(id)) == general_proc_tag))) {
2 7u83 274
	      exp proc_cont = getexp(sh(e),nilexp,0,e,nilexp,0,
275
				     0,cont_tag);
276
	      /*return find_where(proc_cont);*/
277
	      e = proc_cont;
278
	      /*return EffAddr;*/
279
	      id = son(e);
280
/*	      return find_where(e);*/
281
	    }
282
#endif
283
 
7 7u83 284
	    if (isglob(id)) return(External);
285
	    switch (ptno(id)) {
2 7u83 286
#ifndef tdf3
7 7u83 287
		case par2_pl:
288
		case par3_pl:
2 7u83 289
#endif
290
 
7 7u83 291
		case par_pl:
292
		case var_pl: return(EffAddr);
293
		case reg_pl: {
294
		    rm = (bitpattern)no(id);
295
		    where_regmsk |= rm;
2 7u83 296
		    /* A register, but what type? */
7 7u83 297
		    if (rm & dreg_msk) return(Dreg);
298
		    if (rm & areg_msk) return(Areg);
299
		    return(Freg);
2 7u83 300
		}
301
	    }
7 7u83 302
	    break;
2 7u83 303
	}
304
 
7 7u83 305
	case cont_tag:
306
	case ass_tag: {
307
	    exp r = son(e);
308
	    switch (name(r)) {
2 7u83 309
 
7 7u83 310
		case name_tag: {
311
		    exp id = son(r);
312
		    long pt_id = ptno(id);
313
		    if (isvar(id)) return(find_where(r));
314
		    if (isglob(id)) {
315
			if (name(sh(e)) == prokhd) return(External);
316
			return(Other);
2 7u83 317
		    }
7 7u83 318
		    switch (pt_id) {
2 7u83 319
#ifndef tdf3
7 7u83 320
                        case par2_pl:
321
                        case par3_pl:
2 7u83 322
#endif
323
 
7 7u83 324
			case par_pl:
325
			case var_pl: return(EffAddr);
326
			case reg_pl: return(find_reg_ind(no(id)));
2 7u83 327
		    }
7 7u83 328
		    break;
2 7u83 329
		}
330
 
7 7u83 331
		case cont_tag: {
332
		    exp rr = son(r);
333
		    if (name(rr) == name_tag) {
334
			exp id = son(rr);
335
			if (!isvar(id))break;
336
			if (isglob(id)) return(Other);
337
			switch (ptno(id)) {
2 7u83 338
#ifndef tdf3
7 7u83 339
                            case par2_pl:
340
                            case par3_pl:
2 7u83 341
#endif
342
 
7 7u83 343
			    case par_pl:
344
			    case var_pl: return(EffAddr);
345
			    case reg_pl: {
346
				return(find_reg_ind(no(id)));
2 7u83 347
			    }
348
			}
349
		    }
7 7u83 350
		    break;
2 7u83 351
		}
352
 
7 7u83 353
		case reff_tag: {
354
		    exp rr = son(r);
355
		    switch (name(rr)) {
2 7u83 356
 
7 7u83 357
			case name_tag: {
358
			    exp id = son(rr);
359
			    if (ptno(id) == reg_pl) {
360
				return(find_reg_ind(no(id)));
2 7u83 361
			    }
7 7u83 362
			    return(Other);
2 7u83 363
			}
364
 
7 7u83 365
			case cont_tag: {
366
			    exp id = son(son(rr));
367
			    if (ptno(id) == reg_pl) {
368
				return(find_reg_ind(no(id)));
2 7u83 369
			    }
7 7u83 370
			    return(Other);
2 7u83 371
			}
372
 
7 7u83 373
			case addptr_tag: return(find_where(rr));
2 7u83 374
		    }
7 7u83 375
		    break;
2 7u83 376
		}
377
 
7 7u83 378
		case addptr_tag: {
379
		    exp rr = son(r);
380
		    exp eb = bro(rr);
381
		    exp ec = simple_exp(cont_tag);
382
		    son(ec) = rr;
383
		    switch (name(eb)) {
384
			case name_tag:
385
			case cont_tag: return(find_ind(eb, ec));
386
			case offset_mult_tag: {
387
			    return(find_ind(son(eb), ec));
2 7u83 388
			}
389
		    }
7 7u83 390
		    break;
2 7u83 391
		}
392
	    }
7 7u83 393
	    break;
2 7u83 394
	}
395
 
7 7u83 396
	case reff_tag:
397
	case dummy_tag: {
398
	    exp r = son(e);
399
	    switch (name(r)) {
2 7u83 400
 
7 7u83 401
		case ident_tag: {
402
		    if (ptno(r) == reg_pl) {
403
			return(find_reg_ind(no(r)));
2 7u83 404
		    }
7 7u83 405
		    break;
2 7u83 406
		}
407
 
7 7u83 408
		case name_tag: {
409
		    exp id = son(r);
410
		    if (isglob(id)) return(External);
411
		    if (ptno(r) == reg_pl) {
412
			return(find_reg_ind(no(id)));
2 7u83 413
		    }
7 7u83 414
		    break;
2 7u83 415
		}
416
 
7 7u83 417
		case cont_tag:
418
		case ass_tag: {
419
		    exp id = son(son(r));
420
		    if (isglob(id)) return(External);
421
		    if (ptno(r) == reg_pl) {
422
			return(find_reg_ind(no(id)));
2 7u83 423
		    }
7 7u83 424
		    break;
2 7u83 425
		}
426
 
7 7u83 427
		case addptr_tag: return(find_where(r));
2 7u83 428
	    }
7 7u83 429
	    break;
2 7u83 430
	}
431
 
7 7u83 432
	case addptr_tag: {
433
	    exp r = son(e);
434
	    exp eb = bro(r);
435
	    exp ec = simple_exp(cont_tag);
436
	    son(ec) = r;
437
	    switch (name(eb)) {
438
		case name_tag:
439
		case cont_tag: return(find_ind(eb, ec));
440
		case offset_mult_tag: {
441
		    return(find_ind(son(eb), ec));
2 7u83 442
		}
443
	    }
7 7u83 444
	    break;
2 7u83 445
	}
446
 
7 7u83 447
	case diagnose_tag: {
448
	    exp r = son(e);
449
	    return(find_where(r));
2 7u83 450
	}
451
    }
452
    /* Allow all other operands through */
7 7u83 453
    return(Other);
2 7u83 454
}
455
 
456
 
457
/*
458
    CREATE A WHERE
459
 
460
    A where is created from an expression e and an offset d.  The routine
461
    find_where is used to calculate the wh_is and wh_regs fields.
462
*/
463
 
464
where mw
7 7u83 465
(exp e, long d)
2 7u83 466
{
7 7u83 467
  where w;
2 7u83 468
#if 0
469
 
7 7u83 470
  if ((name(e) ==name_tag && name(sh(e)) == prokhd) &&
471
      !(((son(son(e)) == nilexp || name(son(son(e))) == proc_tag ||
2 7u83 472
	  name(son(son(e))) == apply_tag ||
473
	  name(son(son(e))) == apply_general_tag)))) {
474
    exp proc_cont = getexp(sh(e),nilexp,0,e,nilexp,0,0,cont_tag);
475
    e = proc_cont;
476
  }
477
#endif
7 7u83 478
  w.wh_exp = e;
479
  w.wh_off = d;
480
  where_regmsk = 0;
481
  w.wh_is = find_where(e);
482
  w.wh_regs = where_regmsk;
483
  return(w);
2 7u83 484
}
485
 
486
 
487
/*
488
    CREATE A WHERE REPRESENTING A NUMBER
489
 
490
    A where is created corresponding to the integer constant d.
491
*/
492
 
493
where mnw
7 7u83 494
(long d)
2 7u83 495
{
7 7u83 496
    where w;
497
    w.wh_exp = zeroe;
498
    w.wh_off = d;
499
    w.wh_is = Value;
500
    w.wh_regs = 0;
501
    return(w);
2 7u83 502
}
503
 
504
 
505
/*
506
    CREATE A WHERE REPRESENTING A FLOATING POINT NUMBER
507
 
508
    A where is created corresponding to the floating point number with
509
    sign sg (+1, 0 or -1), digits v and exponent e.
510
*/
511
 
512
where mfw
7 7u83 513
#if (FBASE == 10)
514
(int sg, char *v, int e)
2 7u83 515
#else
7 7u83 516
(int sg, long *v, int e)
2 7u83 517
#endif
518
{
7 7u83 519
    where w;
520
    int i, lv;
521
    long lab = next_lab();
522
    exp fe, ft = simple_exp(internal_tag);
523
    long fm = new_flpt();
524
    flt *f = &flptnos[fm];
525
    f->sign = sg;
526
    f->exp = e;
527
#if (FBASE == 10)
528
    lv = strlen(v);
529
    for (i = 0; i < lv; i++)f->mant[i] = v[i] - '0';
2 7u83 530
#else
7 7u83 531
    i = 0;
532
    while (v[i]!= -1) {
533
	f->mant[i] = v[i];
534
	i++;
2 7u83 535
    }
7 7u83 536
    lv = i;
2 7u83 537
#endif
7 7u83 538
    for (i = lv; i < MANT_SIZE; i++)f->mant[i] = 0;
539
    fe = new_exp(realsh, nilexp, fm, real_tag);
540
    make_constant(lab, fe);
541
    no(ft) = lab;
542
    w.wh_exp = ft;
543
    w.wh_off = 0;
544
    w.wh_is = Value;
545
    w.wh_regs = 0;
546
    return(w);
2 7u83 547
}
548
 
549
 
550
/*
551
    CONSTRUCT A REGISTER PAIR
552
 
553
    A where is created corresponding to the register pair a:b.  Both
554
    a and b must represent registers.
555
*/
556
 
557
where regpair
7 7u83 558
(where a, where b)
2 7u83 559
{
7 7u83 560
    where w;
561
    exp ea = a.wh_exp;
562
    exp eb = b.wh_exp;
563
    w.wh_exp = getexp(realsh, eb, 0, ea, nilexp, 0, 0, regpair_tag);
564
    w.wh_off = 0;
565
    w.wh_is = RegPair;
566
    where_regmsk = 0;
567
    if (find_where(ea)!= Dreg || find_where(eb)!= Dreg) {
568
	error("Illegal register pair");
2 7u83 569
    }
7 7u83 570
    w.wh_regs = where_regmsk;
571
    return(w);
2 7u83 572
}
573
 
574
 
575
/*
576
    CONSTANT WHERE'S
577
 
578
    These represent commonly used numerical constants and registers.
579
    zero is the integer 0.  RW[] is the array of all registers.  A6_4
580
    represents a position on the stack.  A0_p, A1_p, SP_p and A6_4_p
581
    represent pointers.  D0_D1 is a register pair.
582
*/
583
 
7 7u83 584
where zero;
585
where fzero;
586
where RW[NO_OF_REGS];
587
where A6_4, A0_p, A1_p, SP_p, A6_4_p, D0_D1;
588
where dummy_double_dest;
2 7u83 589
where firstlocal;
590
 
591
 
592
/*
593
    CONSTANT EXP'S
594
 
595
    These expressions are the wh_exp fields of the where's above.
596
*/
597
 
7 7u83 598
exp zeroe;
599
static exp fzeroe;
600
static exp RE[NO_OF_REGS];
601
static exp E_long, E_float, E_ptr, E_A6_4;
2 7u83 602
static exp firstlocalid;
603
 
604
/*
605
    SET UP CONSTANTS WHERE'S
606
 
607
    The constant where's are initialized.
608
*/
609
 
610
void init_wheres
7 7u83 611
(void)
2 7u83 612
{
7 7u83 613
    int i;
2 7u83 614
 
615
    /* Set up the exps corresponding to 0 */
7 7u83 616
    zeroe = new_exp(botsh, nilexp, 0, val_tag);
617
    fzeroe = new_exp(realsh, nilexp, fzero_no, real_tag);
2 7u83 618
 
619
    /* Set up the corresponding wheres */
7 7u83 620
    zero = zw(zeroe);
621
    fzero = zw(fzeroe);
2 7u83 622
 
623
    /* Create some dummy exp's */
7 7u83 624
    E_long = new_exp(slongsh, nilexp, 0, val_tag);
625
    E_float = new_exp(realsh, nilexp, 0, real_tag);
626
    E_ptr = new_exp(ptrsh, E_long, 0, cont_tag);
627
    E_A6_4 = new_exp(botsh, E_ptr, 0, ident_tag);
628
    ptno(E_A6_4) = var_pl;
2 7u83 629
 
630
    /* Set up the exp's corresponding to the utility registers */
7 7u83 631
    for (i = 0; i < NO_OF_REGS; i++) {
632
	exp t = E_float;
633
	if (is_dreg(i))t = E_long;
634
	if (is_areg(i))t = E_ptr;
635
	RE[i] = new_exp(botsh, t, regmsk(i), ident_tag);
636
	ptno(RE[i]) = reg_pl;
637
	RW[i] = zw(new_exp(slongsh, RE[i], 0, name_tag));
2 7u83 638
    }
639
 
640
    /* Set up some pointer where's */
7 7u83 641
    A0_p = zw(new_exp(ptrsh, A0.wh_exp, 0, cont_tag));
642
    A1_p = zw(new_exp(ptrsh, A1.wh_exp, 0, cont_tag));
643
    SP_p = zw(new_exp(ptrsh, SP.wh_exp, 0, cont_tag));
644
    A6_4 = zw(new_exp(slongsh, E_A6_4, -32, name_tag));
645
    A6_4_p = zw(new_exp(ptrsh, A6_4.wh_exp, 0, cont_tag));
2 7u83 646
 
647
    /* Set up the register pair D0:D1 */
7 7u83 648
    D0_D1 = regpair(D0, D1);
2 7u83 649
 
7 7u83 650
    dummy_double_dest = zw(get_dummy_double_dest());
2 7u83 651
 
7 7u83 652
    firstlocalid = new_exp(f_bottom, E_long, 0, ident_tag);
2 7u83 653
    ptno(firstlocalid) = var_pl;
7 7u83 654
    firstlocal = zw(new_exp(slongsh, firstlocalid, -32, name_tag));
2 7u83 655
}
656
 
657
 
658
/*
659
    ARE TWO WHERE'S EQUAL?
660
 
661
    This is actually an auxiliary routine.  eq_where ( a, b ) is a macro
662
    defined to be eq_where_a ( a, b, 1 ).  It returns 1 if the where's
663
    a and b are equal, but 0 otherwise.
664
*/
665
 
666
bool eq_where_a
7 7u83 667
(where wa, where wb, int first)
2 7u83 668
{
7 7u83 669
    where sa, sb;
670
    exp a = wa.wh_exp;
671
    exp b = wb.wh_exp;
672
    char na = name(a);
673
    char nb = name(b);
2 7u83 674
 
7 7u83 675
    if (wa.wh_off != wb.wh_off) return(0);
676
    if (a == b) return(1);
2 7u83 677
 
7 7u83 678
    if (na == nb) {
2 7u83 679
 
7 7u83 680
	switch (na) {
2 7u83 681
 
7 7u83 682
	    case val_tag: {
683
		return(no(a) == no(b)? 1 : 0);
2 7u83 684
	    }
685
 
7 7u83 686
	    case ident_tag: {
687
		if (no(a)!= no(b)) return(0);
688
		return(ptno(a) == ptno(b)? 1 : 0);
2 7u83 689
	    }
690
 
7 7u83 691
	    case name_tag:
692
	    case field_tag:
693
	    case reff_tag: {
694
		if (no(a)!= no(b)) return(0);
695
		sa.wh_exp = son(a);
696
		sa.wh_off = 0;
697
		sb.wh_exp = son(b);
698
		sb.wh_off = 0;
699
		return(eq_where_a(sa, sb, 0));
2 7u83 700
	    }
701
 
7 7u83 702
	    case cont_tag: {
703
		sa.wh_exp = son(a);
704
		sa.wh_off = 0;
705
		sb.wh_exp = son(b);
706
		sb.wh_off = 0;
707
		return(eq_where_a(sa, sb, 0));
2 7u83 708
	    }
709
 
7 7u83 710
	    case real_tag: {
711
		int i;
712
		bool z = 1;
713
		flt fa, fb;
714
		fa = flptnos[no(a)];
715
		fb = flptnos[no(b)];
2 7u83 716
 
7 7u83 717
		for (i = 0; i < MANT_SIZE; i++) {
718
		    if (fa.mant[i]!= fb.mant[i]) return(0);
719
		    if (fa.mant[i])z = 0;
2 7u83 720
		}
721
 
7 7u83 722
		if (z) return(1);
723
		if (fa.exp != fb.exp) return(0);
724
		if (fa.sign != fb.sign) return(0);
725
		return(1);
2 7u83 726
	    }
727
	}
7 7u83 728
	return(0);
2 7u83 729
    }
730
 
7 7u83 731
    if (first && na == name_tag && nb == ident_tag) {
732
	if (no(a)) return(0);
733
	sa.wh_exp = son(a);
734
	sa.wh_off = 0;
735
	return(eq_where_a(sa, wb, 0));
2 7u83 736
    }
737
 
7 7u83 738
    if (first && nb == name_tag && na == ident_tag) {
739
	if (no(b)) return(0);
740
	sb.wh_exp = son(b);
741
	sb.wh_off = 0;
742
	return(eq_where_a(wa, sb, 0));
2 7u83 743
    }
744
 
7 7u83 745
    if ((na == cont_tag || na == ass_tag) &&
746
	 name(son(a)) == name_tag &&
747
	 isvar(son(son(a))) &&
748
	(nb == ident_tag || nb == name_tag)) {
749
	if (no(son(a))) return(0);
750
	sa.wh_exp = son(son(a));
751
	sa.wh_off = 0;
752
	return(eq_where_a(sa, wb, 0));
2 7u83 753
    }
754
 
7 7u83 755
    if ((nb == cont_tag || nb == ass_tag) &&
756
	 name(son(b)) == name_tag &&
757
	 isvar(son(son(b))) &&
758
	(na == ident_tag || na == name_tag)) {
759
	if (no(son(b))) return(0);
760
	sb.wh_exp = son(son(b));
761
	sb.wh_off = 0;
762
	return(eq_where_a(wa, sb, 0));
2 7u83 763
    }
764
 
765
 
7 7u83 766
    if ((na == ass_tag && nb == cont_tag) ||
767
	(nb == ass_tag && na == cont_tag)) {
768
	sa.wh_exp = son(a);
769
	sa.wh_off = 0;
770
	sb.wh_exp = son(b);
771
	sb.wh_off = 0;
772
	return(eq_where_a(sa, sb, 0));
2 7u83 773
    }
774
 
7 7u83 775
    return(0);
2 7u83 776
}