Pristine Ack-5.5
[Ack-5.5.git] / util / ego / share / get.c
1 /* $Id: get.c,v 1.11 1994/06/24 10:29:53 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 /* S H A R E D   F I L E
7  *
8  * G E T . C
9  */
10
11 #include <stdio.h>
12 #include <em_spec.h>
13 #include <em_mnem.h>
14 #include <em_pseu.h>
15 #include <em_mes.h>
16 #include "types.h"
17 #include "def.h"
18 #include "debug.h"
19 #include "global.h"
20 #include "lset.h"
21 #include "cset.h"
22 #include "get.h"
23 #include "alloc.h"
24 #include "map.h"
25 #include "aux.h"
26
27 FILE *curinp;
28 block_id lastbid;       /* block identifying number */
29 lab_id   lastlabid;     /* last label identifier */
30
31
32 /* creating new identifying numbers, i.e. numbers that did not
33  * appear in the input.
34  */
35
36 bblock_p freshblock()
37 {
38         bblock_p b;
39         b = newbblock();
40         b->b_id = ++lastbid;
41         return b;
42 }
43
44
45 lab_id freshlabel()
46 {
47         curproc->p_nrlabels++;
48         return ++lastlabid;
49 }
50
51
52 #define getmark()       getbyte()
53
54 short getshort() {
55         register int l_byte, h_byte;
56
57         l_byte = getbyte();
58         h_byte = getbyte();
59         if ( h_byte>=128 ) h_byte -= 256 ;
60         return l_byte | (h_byte*256) ;
61 }
62
63
64 offset getoff() {
65         register long l;
66         register int h_byte;
67
68         l = getbyte();
69         l |= ((unsigned) getbyte())*256 ;
70         l |= getbyte()*256L*256L ;
71         h_byte = getbyte() ;
72         if ( h_byte>=128 ) h_byte -= 256 ;
73         return l | (h_byte*256L*256*256L) ;
74 }
75
76 STATIC int getint()
77 {
78         /* Read an integer from the input file. This routine is
79          * only used when reading a bitvector-set. We expect  an
80          * integer to be either a short or a long.
81          */
82
83         if (sizeof(int) == sizeof(short)) {
84                 return getshort();
85         } else {
86                 assert (sizeof(int) == sizeof(offset));
87                 return getoff();
88         }
89 }
90
91 /* getptable */
92
93 loop_p getloop(id)
94         loop_id id;
95 {
96         /* Map a loop identifier onto a loop struct.
97          * If no struct was alocated yet for this identifier then
98          * allocate one now and update the loop-map table.
99          */
100
101
102         assert (id > 0 && id <=lplength);
103         if (lpmap[id] == (loop_p) 0) {
104                 lpmap[id] = newloop();
105                 lpmap[id]->lp_id = id;
106         }
107         return (lpmap[id]);
108 }
109
110 bblock_p getblock(id)
111         block_id id;
112 {
113         /* Map a basic block identifier onto a block struct
114          * If no struct was alocated yet for this identifier then
115          * allocate one now and update the block-map table.
116          */
117
118
119         assert (id >= 0 && id <=blength);
120         if (id == 0) return (bblock_p) 0;
121         if (bmap[id] == (bblock_p) 0) {
122                 bmap[id] = newbblock();
123                 bmap[id]->b_id = id;
124         }
125         return (bmap[id]);
126 }
127
128
129 lset getlset(p)
130         char *((*p) ());
131 {
132         /* Read a 'long' set. Such a set is represented externally
133          * as a sequence of identifying numbers terminated by a 0.
134          * The procedural parameter p maps such a number onto a
135          * pointer to a struct (bblock_p, loop_p etc.).
136          */
137
138         lset s;
139         int id;
140
141         s = Lempty_set();
142         while (id = getshort()) {
143                 Ladd( (*p) (id), &s);
144         }
145         return s;
146 }
147
148
149 cset getcset()
150 {
151         /* Read a 'compact' set. Such a set is represented externally
152          * a row of bytes (its bitvector) preceded by its length.
153          */
154
155         cset s;
156         register short i;
157
158         s = Cempty_set(getshort());
159         for (i = 0; i <= DIVWL(s->v_size-1);i++) {
160                 s->v_bits[i] = getint();
161         }
162         return s;
163 }
164
165
166 proc_p getptable(pname)
167         char *pname;
168 {
169         short i;
170         proc_p head, p, *pp;
171         short all;
172
173         if ((curinp = fopen(pname,"r")) == NULL) {
174                 error("cannot open %s",pname);
175         }
176
177         plength = getshort();  /* table is preceded by its length */
178         assert(plength >= 0);
179         assert(plength < 1000);  /* See if its a reasonable number */
180         pmap = (proc_p *) newmap(plength);   /* allocate the pmap table */
181
182         all = getshort();
183         head = (proc_p) 0;
184         pp = &head;
185         for (i = 0; i < plength; i++) {
186                 if (feof(curinp)) {
187                         error("unexpected eof %s", pname);
188                 }
189                 p = newproc();
190                 p->p_id = getshort();
191                 assert(p->p_id > 0 && p->p_id <= plength);
192                 pmap[p->p_id] = p;
193                 p->p_flags1 = getbyte();
194                 if (p->p_flags1 & PF_BODYSEEN) {
195                         p->p_nrlabels = getshort();
196                         p->p_localbytes = getoff();
197                         p->p_nrformals = getoff();
198                         if (all) {
199                                 p->p_change = newchange();
200                                 p->p_change->c_ext = getcset();
201                                 p->p_change->c_flags = getshort();
202                                 p->p_use = newuse();
203                                 p->p_use->u_flags = getshort();
204                                 p->p_calling = getcset();
205                         }
206                 }
207                 *pp = p;
208                 pp = &(p->p_next);
209         }
210         fclose(curinp);
211         OUTTRACE("have read proc table of length %d",plength);
212         return head;    /* pointer to first structure of list */
213 }
214
215
216
217 /* getdtable */
218
219 dblock_p getdtable(dname)
220         char *dname;
221 {
222         /* Read the data block table. Every data block may
223          * have a list of objects and a list of values (arguments),
224          * each of which is also represented by a structure.
225          * So the input file contains a mixture of dblock,
226          * obj and arg records, each one having its own
227          * attributes. A mark indicates which one comes next.
228          * We assume that the syntactic structure of the input
229          * is correct.
230          */
231
232         dblock_p head, d = 0, *dp = &head;
233         obj_p    obj, *op = 0;
234         arg_p    arg, *ap = 0;
235         /* dp, op an ap tell how the next dblock/obj/arg
236          * has to be linked.
237          */
238         int n;
239
240         head = (dblock_p) 0;
241         if ((curinp = fopen(dname,"r")) == NULL) {
242                 error("cannot open %s", dname);
243         }
244         olength = getshort();
245         assert(olength >= 0);
246         assert(olength < 5000);  /* See if its a reasonable number */
247         /* total number of objects */
248         omap = (obj_p *) newmap(olength);  /* allocate omap table */
249
250         while (TRUE) {
251                 n = getmark();
252                 if (feof(curinp)) break;
253                 switch(n) {
254                         case MARK_DBLOCK:
255                                 d = *dp = newdblock();
256                                 op = &d->d_objlist;
257                                 ap = &d->d_values;
258                                 dp = &d->d_next;
259                                 d->d_id = getshort();
260                                 d->d_pseudo = getbyte();
261                                 d->d_size = getoff();
262                                 d->d_fragmnr = getshort();
263                                 d->d_flags1 = getbyte();
264                                 break;
265                         case MARK_OBJ:
266                                 obj = *op = newobject();
267                                 op = &obj->o_next;
268                                 obj->o_dblock = d;
269                                 obj->o_id = getshort();
270                                 assert(obj->o_id >0);
271                                 assert(obj->o_id <= olength);
272                                 omap[obj->o_id] = obj;
273                                 obj->o_size = getoff();
274                                 obj->o_off = getoff();
275                                 break;
276                         case MARK_ARG:
277                                 arg = *ap = newarg(ARGOFF);
278                                 ap = &arg->a_next;
279                                 arg->a_a.a_offset = getoff();
280                                 break;
281                         default:
282                                 assert(FALSE);
283                 }
284         }
285         OUTTRACE("have read data table, %d objects",olength);
286         return head;
287 }
288
289
290
291 /* getbblocks */
292
293 STATIC argstring(length,abp)
294         short  length;
295         register argb_p abp;
296 {
297
298         while (length--) {
299                 if (abp->ab_index == NARGBYTES)
300                         abp = abp->ab_next = newargb();
301                 abp->ab_contents[abp->ab_index++] = getbyte();
302         }
303 }
304
305
306
307 STATIC arg_p readargs()
308 {
309         /* Read a list of arguments and allocate structures
310          * for them. Return a pointer to the head of the list.
311          */
312
313         arg_p head, arg, *ap;
314         byte  t;
315         short length;
316
317         ap = &head;
318         for (;;) {
319                 /* every argument list is terminated by an
320                  * ARGCEND byte in Intermediate Code.
321                  */
322                 t = getbyte();
323                 if (t == (byte) ARGCEND) {
324                         return head;
325                 }
326                 arg = *ap = newarg(t);
327                 ap = &arg->a_next;
328                 switch((short) t) {
329                         case ARGOFF:
330                                 arg->a_a.a_offset = getoff();
331                                 break;
332                         case ARGINSTRLAB:
333                                 arg->a_a.a_instrlab = getshort();
334                                 break;
335                         case ARGOBJECT:
336                                 arg->a_a.a_obj = omap[getshort()];
337                                 /* Read an object identifier (o_id)
338                                  * and use the omap table to obtain
339                                  * a pointer to the rigth obj struct.
340                                  */
341                                 break;
342                         case ARGPROC:
343                                 arg->a_a.a_proc = pmap[getshort()];
344                                 /* Read a procedure identifier (p_id) */
345                                 break;
346                         case ARGSTRING:
347                                 length = getshort();
348                                 argstring(length, &arg->a_a.a_string);
349                                 break;
350                         case ARGICN:
351                         case ARGUCN:
352                         case ARGFCN:
353                                 length = getshort();
354                                 arg->a_a.a_con.ac_length = length;
355                                 /* size of the constant */
356                                 argstring(getshort(),
357                                           &arg->a_a.a_con.ac_con);
358                                 break;
359                         default:
360                                 assert(FALSE);
361                 }
362         }
363 }
364
365
366 line_p read_line(p_out)
367         proc_p *p_out;
368 {
369         /* Read a line of EM code (i.e. one instruction)
370          * and its arguments (if any).
371          * In Intermediate Code, the first byte is the
372          * instruction code and the second byte denotes the kind
373          * of operand(s) that follow.
374          */
375
376         line_p lnp;
377         byte   instr;
378
379         instr = getbyte();
380         if (feof(curinp)) return (line_p) 0;
381         lnp = newline(getbyte());
382         linecount++;
383         lnp->l_instr = instr;
384         switch(TYPE(lnp)) {
385                 /* read the operand(s) */
386                 case OPSHORT:
387                         SHORT(lnp) = getshort();
388                         break;
389                 case OPOFFSET:
390                         OFFSET(lnp) = getoff();
391                         break;
392                 case OPINSTRLAB:
393                         INSTRLAB(lnp) = getshort();
394                         if ((instr & BMASK) == op_lab) {
395                                 /* defining occurrence of an
396                                  * instruction label.
397                                  */
398                                 lmap[INSTRLAB(lnp)] = lnp;
399                         }
400                         break;
401                 case OPOBJECT:
402                         OBJ(lnp) = omap[getshort()];
403                         break;
404                 case OPPROC:
405                         PROC(lnp) = pmap[getshort()];
406                         if ((instr & BMASK) == ps_pro) {
407                                 /* enter new procedure: allocate a
408                                  * label map and a label-block map table.
409                                  */
410                                 *p_out = PROC(lnp);
411                                 llength = (*p_out)->p_nrlabels;
412                                 lmap = (line_p *) newmap(llength);
413                                 /* maps lab_id to line structure */
414                                 lbmap = (bblock_p *) newmap(llength);
415                                 /* maps lab_id to bblock structure */
416                                 lastlabid = llength;
417                         }
418                         break;
419                 case OPLIST:
420                         ARG(lnp) = readargs();
421                         break;
422                 default:
423                         assert(TYPE(lnp) == OPNO);
424         }
425         return lnp;
426 }
427
428
429 message(lnp)
430         line_p lnp;
431 {
432         /* See if  lnp is some useful message.
433          * (e.g. a message telling that a certain local variable
434          * will never be referenced indirectly, so it may be put
435          * in a register. If so, add it to the mesregs set.)
436          */
437
438         assert(ARG(lnp)->a_type == ARGOFF);
439         switch((int) aoff(ARG(lnp),0)) {
440                 case ms_reg:
441                         if (ARG(lnp)->a_next != (arg_p) 0) {
442                                 /* take only "mes 3" with further arguments */
443                                 Ladd((Lelem_t) lnp,&mesregs);
444                         }
445                         break;
446                 case ms_err:
447                         error("ms_err encountered");
448                 case ms_opt:
449                         error("ms_opt encountered");
450                 case ms_emx:
451                         ws = aoff(ARG(lnp),1);
452                         ps = aoff(ARG(lnp),2);
453                         break;
454         }
455 }
456
457
458
459 line_p getlines(lf,n,p_out,collect_mes)
460         FILE *lf;
461         int n;
462         proc_p *p_out;
463         bool collect_mes;
464 {
465         /* Read n lines of EM text and doubly link them.
466          * Also process messages.
467          */
468
469         line_p head, *pp, l, lprev;
470
471         curinp = lf; /* EM input file */
472         pp = &head;
473         lprev = (line_p) 0;
474         while (n--) {
475                 l = *pp = read_line(p_out);
476                 PREV(l) = lprev;
477                 pp = &l->l_next;
478                 lprev = l;
479                 if (collect_mes && INSTR(l) == ps_mes) {
480                         message(l);
481                 }
482         }
483         *pp = (line_p) 0;
484         return head;
485 }
486
487
488
489 bool getunit(gf,lf,kind_out,g_out,l_out,p_out,collect_mes)
490         FILE   *gf,*lf;
491         short  *kind_out;
492         bblock_p *g_out;
493         line_p *l_out;
494         proc_p *p_out;
495         bool   collect_mes;
496 {
497         /* Read control flow graph (gf) and EM text (lf) of the next procedure.
498          * A pointer to the proctable entry of the read procedure is
499          * returned via p_out.
500          * This routine also constructs the bmap and lpmap tables.
501          * Note that we allocate structs for basic blocks and loops
502          * at their first reference rather than at when we read them.
503          */
504
505         int n,i;
506         bblock_p head, *pp, b;
507         loop_p lp;
508
509         curinp = gf;
510         blength = getshort(); /* # basic blocks in this procedure */
511         if (feof(curinp)) return FALSE;
512         if (blength == 0) {
513                 /* data unit */
514                 *kind_out = LDATA;
515                 n = getshort();
516                 *l_out = getlines(lf,n,p_out,collect_mes);
517                 return TRUE;
518         }
519         *kind_out = LTEXT;
520         bmap = (bblock_p *) newmap(blength); /* maps block_id on bblock_p */
521         lplength = getshort(); /* # loops in this procedure */
522         lpmap = (loop_p *) newmap(lplength); /* maps loop_id on loop_p */
523
524         /* Read the basic blocks and the EM text */
525         pp = &head; /* we use a pointer-to-a-pointer to link the structs */
526         for (i = 0; i < blength; i++) {
527                 b = getblock(getshort());
528                 n = getshort();  /* #instructions in the block */
529                 b->b_succ = getlset(getblock);
530                 b->b_pred = getlset(getblock);
531                 b->b_idom = getblock(getshort());
532                 b->b_loops = getlset(getloop);
533                 b->b_flags = getshort();
534                 b->b_start = getlines(lf,n,p_out,collect_mes);  /* read EM text */
535                 *pp = b;
536                 pp = &b->b_next;
537                 curinp = gf;
538         }
539         lastbid = blength; /* last block_id */
540
541         /* read the information about loops */
542         curproc->p_loops = Lempty_set();
543         for (i = 0; i < lplength; i++) {
544                 lp = getloop(getshort());
545                 lp->lp_level = getshort(); /* nesting level */
546                 lp->lp_entry = getblock(getshort()); /* entry block of the loop */
547                 lp->lp_end = getblock(getshort()); /* tail of back edge of loop */
548                 Ladd((Lelem_t)lp,&curproc->p_loops);
549         }
550         *g_out = head;
551         return TRUE;
552 }