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
    		 Crown Copyright (c) 1998
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/**********************************************************************
32
$Author: pwe $
33
$Date: 1998/03/15 16:00:36 $
34
$Revision: 1.2 $
35
$Log: dw2_locdata.c,v $
36
 * Revision 1.2  1998/03/15  16:00:36  pwe
37
 * regtrack dwarf dagnostics added
38
 *
39
 * Revision 1.1  1998/03/11  11:03:46  pwe
40
 * DWARF optimisation info
41
 *
42
**********************************************************************/
43
 
44
#include "config.h"
45
#include "common_types.h"
46
#include "dg_types.h"
47
#include "dw2_config.h"
48
#include "dw2_basic.h"
49
#include "dw2_codes.h"
50
#include "dw2_iface.h"
51
#include "dw2_info.h"
52
#include "expmacs.h"
53
#include "tags.h"
54
#include "basicread.h"
55
#include "xalloc.h"
56
#include "externs.h"
57
#include "dg_aux.h"
58
#include "dw2_locdata.h"
59
 
60
 
61
/*	Location list information is collected for each object, held via
62
	fields of the 'obtain_value' exp (which is a hold_tag). last is set
63
	if the object is master of a new location. bro is used to hold 
64
	references to other objects that share this location (as a bro list).
65
	no is label for shared location set.
66
		pt holds other more temporary uses (via ll_item).
67
*/
68
 
69
 
70
 
71
#define	LOp_Non_Current 1
72
#define	LOp_Locked	2
73
#define	LOp_Const	3
74
#define	LOp_Shared	4
75
#define	LOp_Portion	5
76
 
77
 
78
typedef enum
79
{
80
  LL_OPTLOCK = 1,
81
  LL_CONST,
82
  LL_RET,
83
  LL_REGSHARE,
84
  LL_MASTERSHARE
85
} loclist_key;
86
 
87
typedef struct rs_s
88
{
89
  long			start;
90
  long			end;
91
  long			share;
92
  dg_name		nm;
93
  int			reg;
94
  struct rs_s *		next_share;
95
  struct rs_s *		next_loc;
96
} * regshare_item;
97
 
98
typedef struct rsl_s
99
{
100
  dg_name		alloc;
101
  int			reg;
102
  regshare_item		items;
103
  struct rsl_s *	next;
104
} * regshare_list;
105
 
106
typedef struct ll_s
107
{
108
  int			key	: 8;
109
  int			open	: 1;
110
  int			has_inner : 1;
111
  union
112
  {
113
    dg_info		d;
114
    retrec *		r;
115
    regshare_item	l;
116
  } u;
117
  struct ll_s *		next;
118
  struct ll_s *		inner;
119
} * ll_item;
120
 
121
static ll_item * ll_root
122
    PROTO_N ( (nm) )
123
    PROTO_T ( dg_name nm )
124
{
125
  exp x = nm->data.n_obj.obtain_val;
126
  exp * ref = &(pt(x));
127
  return (ll_item *)((void *)ref);
128
}
129
 
130
static ll_item new_ll_item
131
    PROTO_N ( (k, o) )
132
    PROTO_T ( loclist_key k X int o )
133
{
134
  ll_item ans = (ll_item) xmalloc (sizeof (struct ll_s));
135
  ans->key = k;
136
  ans->open = ans->has_inner = o;
137
  ans->next = (ll_item)0;
138
  ans->inner = (ll_item)0;
139
  return ans;
140
}
141
 
142
static regshare_list all_regshares = (regshare_list)0;
143
 
144
void * dw_new_regshare
145
    PROTO_N ( (nm, reg) )
146
    PROTO_T ( dg_name nm X int reg )
147
{
148
  regshare_list ans = (regshare_list) xmalloc (sizeof (struct rsl_s));
149
  ans->alloc = nm;
150
  ans->reg = reg;
151
  ans->items = (regshare_item)0;
152
  ans->next = all_regshares;
153
  all_regshares = ans;
154
  return (void *)ans;		/* actual type local to this file */
155
}
156
 
157
void dw_add_regshare
158
    PROTO_N ( (w, nm, start, end) )
159
    PROTO_T ( void * w X dg_name nm X long start X long end )
160
{
161
  regshare_list holder = (regshare_list)w;
162
  regshare_item item = (regshare_item) xmalloc (sizeof (struct rs_s));
163
  item->start = start;
164
  item->end = end;
165
  item->share = 0;
166
  item->nm = nm;
167
  item->next_share = holder->items;
168
  item->next_loc = (regshare_item)0;
169
  holder->items = item;
170
  return;
171
}
172
 
173
 
174
obj_list * local_objects = (obj_list *)0;
175
 
176
static void check_taggable
177
    PROTO_N ( (nm) )
178
    PROTO_T ( dg_name nm )
179
{
180
  if (!nm->mor || !nm->mor->this_tag)
181
    IGNORE f_dg_tag_name (gen_tg_tag (), nm);
182
  return;
183
}
184
 
185
 
186
void set_locdata
187
    PROTO_N ( (this_obl) )
188
    PROTO_T ( obj_list this_obl )
189
{
190
  dg_name this_nm = this_obl.obj;
191
  while (this_nm) {
192
    if (this_nm->key == DGN_OBJECT) {
193
      exp x = this_nm->data.n_obj.obtain_val;
194
      exp id;
195
      if (x && (id = dw_has_location (son(x)), id)) {
196
	if (isglob(id)) {
197
	  dg_name master = brog(id)->dec_u.dec_val.diag_info;
198
	  if (!master)
199
	    master = brog(id)->dec_u.dec_val.diag_info = this_nm;
200
	  if (master == this_nm) {
201
	    setlast (x);
202
	    no(x) = next_dwarf_label ();
203
	  }
204
	  else {
205
	    exp y = master->data.n_obj.obtain_val;
206
	    setbro (x, bro(y));
207
	    setbro (y, (exp)((void *)this_nm));
208
	    no(x) = no(y);
209
	    check_taggable (master);
210
	    check_taggable (this_nm);
211
	  }
212
	}
213
	else {
214
	  int found = 0;
215
	  obj_list * obl = local_objects;
216
	  while (obl && !found) {
217
	    dg_name nm = obl->obj;
218
	    while (nm) {
219
	      if (nm->key == DGN_OBJECT) {
220
		exp y = nm->data.n_obj.obtain_val;
221
		if (y && last(y) && dw_has_location (son(y)) == id) {
222
		  setbro (x, bro(y));
223
		  setbro (y, (exp)((void *)this_nm));
224
		  no(x) = no(y);
225
		  check_taggable (nm);
226
		  check_taggable (this_nm);
227
		  found = 1;
228
		  break;
229
		}
230
	      }
231
	      if (!obl->islist)
232
		break;
233
	      nm = nm->next;
234
	    }
235
	    obl = obl->next;
236
	  }
237
	  if (!found) {
238
	    setlast (x);
239
	    no(x) = next_dwarf_label ();
240
	    dw_allocated (this_nm, id);
241
	  }
242
	}
243
      }
244
      else
245
	no(x) = 0;
246
    }
247
    if (!this_obl.islist)
248
      break;
249
    this_nm = this_nm->next;
250
  }
251
}
252
 
253
 
254
void close_locdata
255
    PROTO_N ( (this_obl) )
256
    PROTO_T ( obj_list this_obl )
257
{
258
  dg_name this_nm = this_obl.obj;
259
  while (this_nm) {
260
    if (this_nm->key == DGN_OBJECT) {
261
      exp x = this_nm->data.n_obj.obtain_val;
262
      if (x && last(x))
263
	dw_deallocated (this_nm);
264
    }
265
    if (!this_obl.islist)
266
      break;
267
    this_nm = this_nm->next;
268
  }
269
}
270
 
271
 
272
dg_name find_equiv_object
273
    PROTO_N ( (e, isc) )
274
    PROTO_T ( exp e X int isc )
275
{
276
  obj_list * obl = local_objects;
277
  while (obl) {
278
    dg_name nm = obl->obj;
279
    while (nm) {
280
      if (nm->key == DGN_OBJECT) {
281
	exp x = nm->data.n_obj.obtain_val;
282
	if (isc) {
283
	  if (x && name(son(x)) == cont_tag && 
284
		dw_loc_equivalence (e, son(son(x))))
285
	    return nm;
286
	}
287
	else {
288
	  if (x && dw_loc_equivalence (e, son(x)))
289
	    return nm;
290
	}
291
      }
292
      if (!obl->islist)
293
	break;
294
      nm = nm->next;
295
    }
296
    obl = obl->next;
297
  }
298
  return (dg_name)0;
299
}
300
 
301
 
302
 
303
static dg_name find_simple_object
304
    PROTO_N ( (e) )
305
    PROTO_T ( exp e )
306
{				/* e is name_tag for required object */
307
  obj_list * obl = local_objects;
308
  while (obl) {
309
    dg_name nm = obl->obj;
310
    while (nm) {
311
      if (nm->key == DGN_OBJECT) {
312
	exp x = nm->data.n_obj.obtain_val;
313
	while (x && (name(x) == hold_tag || name(x) == cont_tag || 
314
		name(x) == reff_tag))
315
	  x = son(x);
316
	if ((x) && name(x) == name_tag && son(x) == son(e) &&
317
		(no(x) <= no(e)) && 
318
		(no(x) + shape_size(sh(x))) >= (no(e) + shape_size(sh(e)) ))
319
	  return nm;
320
      }
321
      if (!obl->islist)
322
	break;
323
      nm = nm->next;
324
    }
325
    obl = obl->next;
326
  }
327
  return (dg_name)0;
328
}
329
 
330
 
331
void set_optim_objects
332
    PROTO_N ( (optim, start) )
333
    PROTO_T ( dg_info optim X int start )
334
{
335
  objset * obj = optim->data.i_optim.objs;
336
  while (obj) {
337
    dg_name nm = obj->tg->p.nam;
338
    if (start) {
339
      ll_item * l = ll_root (nm);
340
      while (*l) {
341
	if ((*l)->open)
342
	  l = &((*l)->inner);
343
	else
344
	  l = &((*l)->next);
345
      }
346
      *l = new_ll_item (LL_OPTLOCK, 1);
347
      (*l)->u.d = optim;
348
    }
349
    else {
350
      ll_item l = * ll_root (nm);
351
      while (l->key != LL_OPTLOCK || l->u.d != optim) {
352
	if ((l)->open)
353
	  l = l->inner;
354
	else
355
	  l = l->next;
356
      }
357
      l->open = 0;
358
    }
359
    obj = obj->next;
360
  }
361
  return;
362
}
363
 
364
 
365
void set_remval_object
366
    PROTO_N ( (rmv) )
367
    PROTO_T ( dg_info rmv )
368
{
369
  dg_name nm = find_simple_object (son (rmv->data.i_remval.var));
370
  if (nm) {
371
    ll_item * l = ll_root (nm);
372
    while (*l) {
373
      if ((*l)->open)
374
	l = &((*l)->inner);
375
      else
376
	l = &((*l)->next);
377
    }
378
    *l = new_ll_item (LL_CONST, 0);
379
    (*l)->u.d = rmv;
380
  }
381
  return;
382
}
383
 
384
 
385
void set_obj_rets
386
    PROTO_N ( (rec) )
387
    PROTO_T ( retrec * rec )
388
{
389
  obj_list * obl = local_objects;
390
  while (obl) {
391
    dg_name nm = obl->obj;
392
    while (nm) {
393
      if (nm->key == DGN_OBJECT) {
394
	exp x = nm->data.n_obj.obtain_val;
395
	while (x && (name(x) == hold_tag || name(x) == cont_tag || 
396
		name(x) == reff_tag))
397
	  x = son(x);
398
	if ((x) && name(x) == name_tag && !isdiscarded(x) && 
399
					!isglob(son(x))) {
400
	  ll_item * l = ll_root (nm);
401
	  while (*l) {
402
	  if ((*l)->open)
403
	    l = &((*l)->inner);
404
	  else
405
	    l = &((*l)->next);
406
	  }
407
	  *l = new_ll_item (LL_RET, 0);
408
	  (*l)->u.r = rec;
409
	}
410
      }
411
      if (!obl->islist)
412
	break;
413
      nm = nm->next;
414
    }
415
    obl = obl->next;
416
  }
417
  return;
418
}
419
 
420
 
421
static ll_item find_ll_item
422
    PROTO_N ( (nm, k, force) )
423
    PROTO_T ( dg_name nm X loclist_key k X int force )
424
{
425
  ll_item * ll = ll_root (nm);
426
  ll_item l = *ll;
427
  while (l && l->key != k)
428
    l = l->next;
429
  if (!l && force) {
430
    l = new_ll_item (k, 0);
431
    l->u.l = (regshare_item)0;
432
    l->next = *ll;
433
    *ll = l;
434
  }
435
  return l;
436
}
437
 
438
static void out_regshare_set
439
    PROTO_N ( (it) )
440
    PROTO_T ( regshare_item it )
441
{
442
  regshare_item this = it;
443
  while (this) {
444
    dg_name nm = this->nm;
445
    if (nm) {
446
      regshare_item look = it;
447
      while (look->nm != nm)	/* avoid duplicates */
448
	look = look->next_share;
449
      if (look == this)
450
	dw_at_ext_address (nm->mor->this_tag);
451
    }
452
    this = this->next_share;  
453
  }
454
  return;
455
}
456
 
457
 
458
 
459
void init_dw_locdata
460
    PROTO_Z ()
461
{
462
  all_regshares = (regshare_list)0;
463
  local_objects = (obj_list *)0;
464
  dw_all_deallocated ();
465
  return;
466
}
467
 
468
void complete_dw_locdata
469
    PROTO_Z ()
470
{
471
  regshare_list top_l = all_regshares;
472
  while (top_l) {
473
    dg_name master = top_l->alloc;
474
    int reg = top_l->reg;
475
    regshare_item regitem = top_l->items;
476
    dg_name nm;
477
    if (master) {
478
      while (regitem) {
479
	nm = master;
480
	do {
481
	  if (regitem->nm == nm) {
482
	    regitem->nm = (dg_name)0;
483
	    break;
484
	  }
485
	  nm = (dg_name)((void *)bro(nm->data.n_obj.obtain_val));
486
	} while (nm);
487
	if (!nm) {	/* regitem not in allocation shareset */
488
	  ll_item l = find_ll_item (master, LL_MASTERSHARE, 1);
489
	  if (!l->u.l)
490
	    l->u.l = regitem;	/* start of extra share list for master */
491
	  regitem->share = no(master->data.n_obj.obtain_val);
492
	  regitem->reg = reg;
493
	  l = find_ll_item (regitem->nm, LL_REGSHARE, 1);
494
	  regitem->next_loc = l->u.l;
495
	  l->u.l = regitem;
496
	  check_taggable (regitem->nm);
497
	  check_taggable (master);
498
	}
499
	regitem = regitem->next_share;
500
      }
501
    }
502
    else {
503
      long share = 0;
504
      master = nm = (dg_name)0;
505
      while (regitem) {
506
	if (!master)
507
	  master = regitem->nm;
508
	if (!nm)
509
	  nm = regitem->nm;
510
	if (nm != master) {
511
	  share = next_dwarf_label ();
512
	  break;
513
	}
514
	regitem = regitem->next_share;
515
      }
516
      regitem = top_l->items;
517
      while (regitem) {
518
	ll_item l = find_ll_item (regitem->nm, LL_REGSHARE, 1);
519
	regitem->share = share;
520
	if (share)
521
	  check_taggable (regitem->nm);
522
	regitem->reg = reg;
523
	regitem->next_loc = l->u.l;
524
	l->u.l = regitem;
525
        regitem = regitem->next_share;
526
      }
527
      if (share) {
528
	enter_section ("debug_loc");
529
	out_dwf_label (share, 1);
530
	out_regshare_set (top_l->items);
531
	exit_section ();
532
      }
533
    }
534
    top_l = top_l->next;
535
  }
536
  return;
537
}
538
 
539
 
540
 
541
static int obj_decide
542
    PROTO_N ( (l) )
543
    PROTO_T ( ll_item l )
544
{
545
  int ans = 0, x;
546
  while (l && ans < 2) {
547
    switch (l->key) {
548
      case LL_OPTLOCK:
549
      case LL_CONST:
550
      case LL_MASTERSHARE:
551
	return 2;
552
      case LL_RET: {
553
	if (!ans)
554
	  ans = 1;
555
	break;
556
      }
557
      case LL_REGSHARE: {
558
	regshare_item rs = l->u.l;
559
	while (rs && ans<2) {
560
	  if (rs->share)
561
	    ans = 2;
562
	  else
563
	  if (!ans)
564
	    ans = 1;
565
	  rs = rs->next_loc;
566
	}
567
	break;
568
      }
569
    }
570
    if (l->has_inner && (x = obj_decide (l->inner), x > ans))
571
      ans = x;
572
    l = l->next;
573
  }
574
  return ans;
575
}
576
 
577
int decide_ll_type
578
    PROTO_N ( (x) )
579
    PROTO_T ( exp x )
580
{			/* 1 if need location list, 2 if extension list */
581
  ll_item l = (ll_item)((void *)(pt(x)));
582
  if ((last(x) && bro(x)) || (!last(x) && no(x)))
583
				/* main location is shared */
584
    return 2;
585
  else
586
    return obj_decide (l);
587
}
588
 
589
 
590
static long startlab;
591
static int ll_ok;
592
static exp obval;
593
 
594
static void loclist_portion
595
    PROTO_N ( (l) )
596
    PROTO_T ( ll_item l )
597
{
598
  while (l) {
599
    switch (l->key) {
600
      case LL_CONST: {
601
	ll_ok = 0;
602
	break;
603
      }
604
      case LL_RET: {
605
	long endlab = l->u.r->lab;
606
	if (ll_ok && endlab != startlab) {
607
	  out_loc_range (startlab, endlab, 0);
608
	  dw2_locate_exp (obval, 0, 1);
609
	}
610
	startlab = l->u.r->over;
611
	break;
612
      }
613
      case LL_REGSHARE: {
614
	regshare_item rs = l->u.l;
615
	while (rs) {
616
	  out_loc_range (rs->start, rs->end, 1);
617
	  out16 (); 
618
	  if (rs->reg < 32) {
619
	    outn ((long)1); outnl();
620
	    out8 (); outn ((long)(DW_OP_reg0 + rs->reg));
621
	  }
622
	  else {
623
	    outn ((long)(1 + uleb128_length((unsigned long)rs->reg)));
624
	    outnl(); out8 ();
625
	    outn ((long)DW_OP_regx); outs (", ");
626
	    uleb128((unsigned long)rs->reg);
627
	  }
628
	  outnl();
629
	  rs = rs->next_loc;
630
	}
631
      }
632
      default:
633
	break;
634
    }
635
    if (l->has_inner)
636
      loclist_portion (l->inner);
637
    l = l->next;
638
  }
639
  return;
640
}
641
 
642
void out_obj_loclist
643
    PROTO_N ( (l1, l2, x) )
644
    PROTO_T ( long l1 X long l2 X exp x )
645
{
646
  ll_item l = (ll_item)((void *)(pt(x)));
647
  startlab = l1;
648
  ll_ok = 1;
649
  obval = son(x);
650
  loclist_portion (l);
651
  if (ll_ok && l2 != startlab) {
652
    out_loc_range (startlab, l2, 0);
653
    dw2_locate_exp (obval, 0, 1);
654
  }
655
  return;
656
}
657
 
658
 
659
static void extlist_portion
660
    PROTO_N ( (l) )
661
    PROTO_T ( ll_item l )
662
{
663
  while (l) {
664
    switch (l->key) {
665
      case LL_CONST: {
666
	long here = l->u.d->data.i_remval.lo_pc;
667
	if (ll_ok && here != startlab) {
668
	  out_loc_range (startlab, here, 0);
669
	  dw_at_data (1, LOp_Const);
670
	  dw_out_const (obval);
671
	}
672
	startlab = here;
673
	ll_ok = 1;
674
	obval = l->u.d->data.i_remval.val;
675
	break;
676
      }
677
      case LL_OPTLOCK: {
678
	out_loc_range (l->u.d->data.i_optim.lo_pc,
679
			l->u.d->data.i_optim.hi_pc, 0);
680
	dw_at_data (1, LOp_Locked);
681
	dw_at_data (1, l->u.d->data.i_optim.reason);
682
	break;
683
      }
684
      case LL_REGSHARE: {
685
	regshare_item rs = l->u.l;
686
	while (rs) {
687
	  if (rs->share) {
688
	    out_loc_range (rs->start, rs->end, 1);
689
	    dw_at_data (1, LOp_Shared);
690
	    dw_at_address (rs->share);
691
	  }
692
	  rs = rs->next_loc;
693
	}
694
      }
695
      default:
696
	break;
697
    }
698
    if (l->has_inner)
699
      loclist_portion (l->inner);
700
    l = l->next;
701
  }
702
  return;
703
}
704
 
705
void out_obj_extloclist
706
    PROTO_N ( (l1, l2, x) )
707
    PROTO_T ( long l1 X long l2 X exp x )
708
{
709
  ll_item l = (ll_item)((void *)(pt(x)));
710
  if ((last(x) && bro(x)) || (!last(x) && no(x))) {
711
				/* main location is shared */
712
    out_loc_range (l1, l2, 0);
713
    dw_at_data (1, LOp_Shared);
714
    dw_at_address (no(x));
715
  }
716
  startlab = l1;
717
  ll_ok = 0;
718
  if (l)
719
    extlist_portion (l);
720
  if (ll_ok && l2 != startlab) {
721
    out_loc_range (startlab, l2, 0);
722
    dw_at_data (1, LOp_Const);
723
    dw_out_const (obval);
724
  }
725
  return;
726
}
727
 
728
void out_obj_shared_set
729
    PROTO_N ( (dn) )
730
    PROTO_T ( dg_name dn )
731
{
732
  exp x = dn->data.n_obj.obtain_val;
733
  ll_item l = find_ll_item (dn, LL_MASTERSHARE, 0);
734
  if (last(x) && (bro(x) || l)) {
735
    out_dwf_label (no(x), 1);
736
    dw_at_ext_address (dn->mor->this_tag);
737
    while (bro(x)) {
738
      dg_name nm = (dg_name)((void *)bro(x));
739
      dw_at_ext_address (nm->mor->this_tag);
740
      x = nm->data.n_obj.obtain_val;
741
    }
742
    if (l)
743
      out_regshare_set (l->u.l);
744
    out32(); outs("0"); outnl_comment ("share list end");
745
  }
746
  return;
747
}
748