Pristine Ack-5.5
[Ack-5.5.git] / util / ego / share / locals.c
1 /* $Id: locals.c,v 1.10 1994/06/24 10:30:18 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  */
6 /*
7  *  L O C A L S . C
8  */
9
10 #include <stdio.h>
11 #include <em_mnem.h>
12 #include <em_spec.h>
13 #include <em_pseu.h>
14 #include <em_mes.h>
15 #include "types.h"
16 #include "debug.h"
17 #include "global.h"
18 #include "lset.h"
19 #include "cset.h"
20 #include "def.h"
21 #include "get.h"
22 #include "aux.h"
23 #include "alloc.h"
24 #include "locals.h"
25
26
27 extern short nrglobals;
28
29 short nrlocals;
30 local_p *locals;  /* dynamic array */
31
32 STATIC localvar(off,size,locs,reg,score)
33         offset off;
34         short  size;
35         local_p *locs;
36         bool reg;
37         offset score;
38 {
39         /* process a reference to a local variable.
40          * A local is characterized by a (offset,size) pair.
41          * We first collect all locals in a list, sorted
42          * by offset. Later we will construct a table
43          * out of this list.
44          */
45
46         local_p lc, x, *prevp;
47
48         prevp = locs;
49         for (lc = *locs; lc != (local_p) 0; lc = lc->lc_next) {
50                 if (lc->lc_off == off && lc->lc_size == size) {
51                         if (reg) {
52                                 REGVAR(lc); /* register variable */
53                                 lc->lc_score = score;
54                         }
55                         return; /* local already present */
56                 }
57                 if (lc->lc_off > off) break;
58                 prevp = &lc->lc_next;
59         }
60         /* the local was not seen before; create an entry
61          * for it in the list.
62          */
63         x = *prevp = newlocal();
64         x->lc_off = off;
65         x->lc_size = size;
66         x->lc_next = lc;
67         if (reg) {
68                 REGVAR(x);
69                 x->lc_score = score;
70         }
71 }
72
73
74
75 STATIC check_message(l,locs)
76         line_p l;
77         local_p *locs;
78 {
79         /* See if l is a register message */
80
81         arg_p arg;
82
83         arg = ARG(l);
84         if (aoff(arg,0) == ms_reg && arg->a_next != (arg_p) 0) {
85                 localvar(aoff(arg,1), (short) aoff(arg,2), locs, TRUE,
86                           aoff(arg,4));
87         }
88 }
89
90
91
92
93 STATIC check_local_use(l,locs)
94         line_p l;
95         local_p *locs;
96 {
97         short sz;
98
99         switch(INSTR(l)) {
100                 case op_lol:
101                 case op_stl:
102                 case op_inl:
103                 case op_del:
104                 case op_zrl:
105                         sz = ws;
106                         break;
107                 case op_ldl:
108                 case op_sdl:
109                         sz = 2 * ws;
110                         break;
111                 case op_lil:
112                 case op_sil:
113                         sz = ps;
114                         break;
115                 case ps_mes:
116                         check_message(l,locs);
117                         /* fall through .. */
118                 default:
119                         return;
120         }
121         if (l->l_next && INSTR(l->l_next) == op_nop) {
122                 /* volatile */
123                 return;
124         }
125         localvar(off_set(l),sz,locs,FALSE,(offset) 0);
126 }
127
128
129 make_localtab(p)
130         proc_p p;
131 {
132         /* Make a table of local variables.
133          * This table is used to associate a
134          * unique number with a local. If two
135          * locals overlap (e.g. LDL 4 and LDL 2)
136          * none of them is considered any further,
137          * i.e. we don't compute ud-info for them.
138          */
139
140         local_p prev = 0, next, lc;
141         local_p locallist = (local_p) 0;
142         short cnt = 0;
143         offset x, ill_zone = 0;
144         register bblock_p b;
145         register line_p   l;
146
147         /* first make a list of all locals used */
148         for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
149                 for (l = b->b_start; l != (line_p) 0; l = l->l_next) {
150                         check_local_use(l,&locallist);
151                 }
152         }
153         /* Now remove overlapping locals, count useful ones on the fly */
154         for (lc = locallist; lc != (local_p) 0; lc = lc->lc_next) {
155                 if (ill_zone != 0 && lc->lc_off < ill_zone) {
156                         /* this local overlaps with a previous one */
157                         BADLC(lc);
158                         if (!IS_BADLC(prev)) {
159                                 BADLC(prev);
160                                 cnt--;
161                         }
162                 } else {
163                         cnt++;
164                 }
165                 x = lc->lc_off + lc->lc_size;
166                 if (ill_zone == 0 || x > ill_zone) {
167                         ill_zone = x;
168                 }
169                 prev = lc;
170         }
171         /* Now we know how many local variables there are */
172         nrlocals = cnt;
173         locals = (local_p *) newmap(cnt);
174         cnt = 1;
175         for (lc = locallist; lc != (local_p) 0; lc = next) {
176                 next = lc->lc_next;
177                 if (IS_BADLC(lc)) {
178                         oldlocal(lc);
179                 } else {
180                         locals[cnt++] = lc;
181                         lc->lc_next = (local_p) 0;
182                 }
183         }
184         assert (cnt == nrlocals+1);
185 }
186
187
188
189 find_local(off,nr_out,found_out)
190         offset off;
191         short  *nr_out;
192         bool   *found_out;
193 {
194         /* Try to find the local variable at the given
195          * offset. Return its local-number.
196          */
197
198         short v;
199
200         for (v = 1; v <= nrlocals; v++) {
201                 if (locals[v]->lc_off > off) break;
202                 if (locals[v]->lc_off == off) {
203                         *found_out = TRUE;
204                         *nr_out = v;
205                         return;
206                 }
207         }
208         *found_out = FALSE;
209 }
210
211
212
213
214 var_nr(l,nr_out,found_out)
215         line_p l;
216         short  *nr_out;
217         bool   *found_out;
218 {
219         /* Determine the number of the variable referenced
220          * by EM instruction l.
221          */
222
223         offset off = 0;
224         short nr;
225
226         switch(TYPE(l)) {
227                 case OPOBJECT:
228                         /* global variable */
229                         if (OBJ(l)->o_globnr == 0) {
230                                 /* We don't maintain ud-info for this var */
231                                 *found_out = FALSE;
232                         } else {
233                                 *nr_out = GLOB_TO_VARNR(OBJ(l)->o_globnr);
234                                 *found_out = TRUE;
235                         }
236                         return;
237                 case OPSHORT:
238                         off = (offset) SHORT(l);
239                         break;
240                 case OPOFFSET:
241                         off = OFFSET(l);
242                         break;
243                 default:
244                         assert(FALSE);
245         }
246         /* Its's a local variable */
247         find_local(off,&nr,found_out);
248         if (*found_out) {
249                 *nr_out = LOC_TO_VARNR(nr);
250         }
251 }