1 /* $Id: get.c,v 1.11 1994/06/24 10:29:53 ceriel Exp $ */
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".
28 block_id lastbid; /* block identifying number */
29 lab_id lastlabid; /* last label identifier */
32 /* creating new identifying numbers, i.e. numbers that did not
33 * appear in the input.
47 curproc->p_nrlabels++;
52 #define getmark() getbyte()
55 register int l_byte, h_byte;
59 if ( h_byte>=128 ) h_byte -= 256 ;
60 return l_byte | (h_byte*256) ;
69 l |= ((unsigned) getbyte())*256 ;
70 l |= getbyte()*256L*256L ;
72 if ( h_byte>=128 ) h_byte -= 256 ;
73 return l | (h_byte*256L*256*256L) ;
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.
83 if (sizeof(int) == sizeof(short)) {
86 assert (sizeof(int) == sizeof(offset));
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.
102 assert (id > 0 && id <=lplength);
103 if (lpmap[id] == (loop_p) 0) {
104 lpmap[id] = newloop();
105 lpmap[id]->lp_id = id;
110 bblock_p getblock(id)
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.
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();
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.).
142 while (id = getshort()) {
143 Ladd( (*p) (id), &s);
151 /* Read a 'compact' set. Such a set is represented externally
152 * a row of bytes (its bitvector) preceded by its length.
158 s = Cempty_set(getshort());
159 for (i = 0; i <= DIVWL(s->v_size-1);i++) {
160 s->v_bits[i] = getint();
166 proc_p getptable(pname)
173 if ((curinp = fopen(pname,"r")) == NULL) {
174 error("cannot open %s",pname);
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 */
185 for (i = 0; i < plength; i++) {
187 error("unexpected eof %s", pname);
190 p->p_id = getshort();
191 assert(p->p_id > 0 && p->p_id <= plength);
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();
199 p->p_change = newchange();
200 p->p_change->c_ext = getcset();
201 p->p_change->c_flags = getshort();
203 p->p_use->u_flags = getshort();
204 p->p_calling = getcset();
211 OUTTRACE("have read proc table of length %d",plength);
212 return head; /* pointer to first structure of list */
219 dblock_p getdtable(dname)
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
232 dblock_p head, d = 0, *dp = &head;
235 /* dp, op an ap tell how the next dblock/obj/arg
241 if ((curinp = fopen(dname,"r")) == NULL) {
242 error("cannot open %s", dname);
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 */
252 if (feof(curinp)) break;
255 d = *dp = newdblock();
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();
266 obj = *op = newobject();
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();
277 arg = *ap = newarg(ARGOFF);
279 arg->a_a.a_offset = getoff();
285 OUTTRACE("have read data table, %d objects",olength);
293 STATIC argstring(length,abp)
299 if (abp->ab_index == NARGBYTES)
300 abp = abp->ab_next = newargb();
301 abp->ab_contents[abp->ab_index++] = getbyte();
307 STATIC arg_p readargs()
309 /* Read a list of arguments and allocate structures
310 * for them. Return a pointer to the head of the list.
313 arg_p head, arg, *ap;
319 /* every argument list is terminated by an
320 * ARGCEND byte in Intermediate Code.
323 if (t == (byte) ARGCEND) {
326 arg = *ap = newarg(t);
330 arg->a_a.a_offset = getoff();
333 arg->a_a.a_instrlab = getshort();
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.
343 arg->a_a.a_proc = pmap[getshort()];
344 /* Read a procedure identifier (p_id) */
348 argstring(length, &arg->a_a.a_string);
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);
366 line_p read_line(p_out)
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.
380 if (feof(curinp)) return (line_p) 0;
381 lnp = newline(getbyte());
383 lnp->l_instr = instr;
385 /* read the operand(s) */
387 SHORT(lnp) = getshort();
390 OFFSET(lnp) = getoff();
393 INSTRLAB(lnp) = getshort();
394 if ((instr & BMASK) == op_lab) {
395 /* defining occurrence of an
398 lmap[INSTRLAB(lnp)] = lnp;
402 OBJ(lnp) = omap[getshort()];
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.
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 */
420 ARG(lnp) = readargs();
423 assert(TYPE(lnp) == OPNO);
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.)
438 assert(ARG(lnp)->a_type == ARGOFF);
439 switch((int) aoff(ARG(lnp),0)) {
441 if (ARG(lnp)->a_next != (arg_p) 0) {
442 /* take only "mes 3" with further arguments */
443 Ladd((Lelem_t) lnp,&mesregs);
447 error("ms_err encountered");
449 error("ms_opt encountered");
451 ws = aoff(ARG(lnp),1);
452 ps = aoff(ARG(lnp),2);
459 line_p getlines(lf,n,p_out,collect_mes)
465 /* Read n lines of EM text and doubly link them.
466 * Also process messages.
469 line_p head, *pp, l, lprev;
471 curinp = lf; /* EM input file */
475 l = *pp = read_line(p_out);
479 if (collect_mes && INSTR(l) == ps_mes) {
489 bool getunit(gf,lf,kind_out,g_out,l_out,p_out,collect_mes)
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.
506 bblock_p head, *pp, b;
510 blength = getshort(); /* # basic blocks in this procedure */
511 if (feof(curinp)) return FALSE;
516 *l_out = getlines(lf,n,p_out,collect_mes);
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 */
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 */
539 lastbid = blength; /* last block_id */
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);