Pristine Ack-5.5
[Ack-5.5.git] / util / ego / share / put.c
1 /* $Id: put.c,v 1.9 1994/06/24 10:30:48 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 /* P U T . C */
7
8 #include <stdio.h>
9 #include <em_pseu.h>
10 #include <em_spec.h>
11 #include "types.h"
12 #include "global.h"
13 #include "debug.h"
14 #include "def.h"
15 #include "map.h"
16 #include "lset.h"
17 #include "alloc.h"
18 #include "put.h"
19
20 FILE *curoutp;
21
22
23 /* The output can be either 'typed' or 'untyped'. Typed data
24  * consists of a value preceded by a byte specifying what kind
25  * of value it is (e.g. 2 bytes constant, 4 bytes constant,
26  * proc-id, lab-id, string etc.). Untyped data consists
27  * of the value only. We use typed data for the EM text and
28  * untyped data for all other files.
29  */
30
31 /* putlines */
32
33 STATIC putstr();
34 STATIC outlab();
35 STATIC outobject();
36
37 STATIC putargs(ap)
38         register arg_p ap;
39 {
40         while (ap != (arg_p) 0) {
41                 outbyte((byte) ap->a_type & BMASK);
42                 switch(ap->a_type) {
43                         case ARGOFF:
44                                 outoff(ap->a_a.a_offset);
45                                 break;
46                         case ARGINSTRLAB:
47                                 outlab(ap->a_a.a_instrlab);
48                                 break;
49                         case ARGOBJECT:
50                                 outobject(ap->a_a.a_obj);
51                                 break;
52                         case ARGPROC:
53                                 outproc(ap->a_a.a_proc);
54                                 break;
55                         case ARGSTRING:
56                                 putstr(&ap->a_a.a_string);
57                                 break;
58                         case ARGICN:
59                         case ARGUCN:
60                         case ARGFCN:
61                                 outshort(ap->a_a.a_con.ac_length);
62                                 putstr(&ap->a_a.a_con.ac_con);
63                                 break;
64                 }
65                 ap = ap->a_next;
66         }
67         outbyte((byte) ARGCEND);
68 }
69
70
71
72 STATIC putstr(abp) register argb_p abp; {
73         register argb_p tbp;
74         register length;
75
76         length = 0;
77         tbp = abp;
78         while (tbp!= (argb_p) 0) {
79                 length += tbp->ab_index;
80                 tbp = tbp->ab_next;
81         }
82         outshort(length);
83         while (abp != (argb_p) 0) {
84                 for (length=0;length<abp->ab_index;length++)
85                         outbyte( (byte) abp->ab_contents[length] );
86                 abp = abp->ab_next;
87         }
88 }
89
90
91 outoff(off) offset off; {
92
93         outshort( (short) (off&0177777L) );
94         outshort( (short) (off>>16) );
95 }
96
97
98 outshort(i) short i; {
99
100         outbyte( (byte) (i&BMASK) );
101         outbyte( (byte) (i>>8) );
102 }
103
104
105 STATIC outint(i)
106         int i;
107 {
108         /* Write an integer to the output file. This routine is
109          * only used when outputting a bitvector-set. We expect  an
110          * integer to be either a short or a long.
111          */
112
113         if (sizeof(int) == sizeof(short)) {
114                 outshort(i);
115         } else {
116                 assert (sizeof(int) == sizeof(offset));
117                 outoff((offset) i);
118         }
119 }
120
121 STATIC outlab(lid) lab_id lid; {
122         outshort((short) lid);
123 }
124
125
126 STATIC outobject(obj) obj_p obj; {
127         outshort((short) obj->o_id);
128 }
129
130
131 outproc(p) proc_p p; {
132         outshort((short) p->p_id);
133 }
134
135
136 short putlines(l,lf)
137         line_p l;
138         FILE *lf;
139 {
140         /* Output the list of em instructions headed by l.
141          * Return the number of instruction written.
142          */
143
144         register line_p lnp;
145         line_p next;
146         short instr;
147         short count= 0;
148
149         curoutp = lf;   /* Set f to the EM-text output file */
150         for (lnp = l; lnp != (line_p) 0; lnp = next) {
151                 VL(lnp);
152                 count++;
153                 next = lnp->l_next;
154                 instr = INSTR(lnp);
155                 outbyte((byte) instr);
156                 outbyte((byte) TYPE(lnp));
157                 switch(TYPE(lnp)) {
158                         case OPSHORT:
159                                 outshort(SHORT(lnp));
160                                 break;
161                         case OPOFFSET:
162                                 outoff(OFFSET(lnp));
163                                 break;
164                         case OPINSTRLAB:
165                                 outlab(INSTRLAB(lnp));
166                                 break;
167                         case OPOBJECT:
168                                 outobject(OBJ(lnp));
169                                 break;
170                         case OPPROC:
171                                 outproc(PROC(lnp));
172                                 break;
173                         case OPLIST:
174                                 putargs(ARG(lnp));
175                                 break;
176                 }
177                 oldline(lnp);
178         }
179         return count;
180 }
181
182
183
184
185
186 /* putdtable */
187
188 #define outmark(m)      outbyte((byte) m)
189
190
191 STATIC putobjects(obj)
192         register obj_p obj;
193 {
194         while (obj != (obj_p) 0) {
195                 outmark(MARK_OBJ);
196                 outshort(obj->o_id);
197                 outoff(obj->o_size);
198                 outoff(obj->o_off);
199                 obj = obj->o_next;
200         }
201 }
202
203
204
205 STATIC putvalues(arg)
206         register arg_p arg;
207 {
208         while (arg != (arg_p) 0) {
209                 assert(arg->a_type == ARGOFF);
210                 outmark(MARK_ARG);
211                 outoff(arg->a_a.a_offset);
212                 arg = arg->a_next;
213         }
214 }
215 putdtable(head,df)
216         dblock_p head;
217         FILE *df;
218 {
219         /* Write the datablock table to the data block file df. */
220
221         register dblock_p dbl;
222         register obj_p obj;
223         dblock_p next;
224         register short n = 0;
225
226         curoutp = df;       /* set f to the data block output file */
227         /* Count the number of objects */
228         for (dbl = head; dbl != (dblock_p) 0; dbl = dbl->d_next) {
229                 for (obj = dbl->d_objlist; obj != (obj_p) 0;
230                                                 obj = obj->o_next) {
231                         n++;
232                 }
233         }
234         outshort(n);  /* The table is preceded by #objects . */
235         for (dbl = head; dbl != (dblock_p) 0; dbl = next) {
236                 next = dbl->d_next;
237                 outmark(MARK_DBLOCK);
238                 outshort(dbl->d_id);
239                 outbyte(dbl->d_pseudo);
240                 outoff(dbl->d_size);
241                 outshort(dbl->d_fragmnr);
242                 outbyte(dbl->d_flags1);
243                 putobjects(dbl->d_objlist);
244                 putvalues(dbl->d_values);
245                 olddblock(dbl);
246         }
247         fclose(curoutp);
248         if (omap != (obj_p *) 0) {
249                 oldmap((short **) omap,olength);  /* release memory for omap */
250         }
251 }
252
253
254
255 /* putptable */
256
257
258
259 STATIC outcset(s)
260         cset s;
261 {
262         /* A 'compact' set is represented externally as a row of words
263          * (its bitvector) preceded by its length.
264          */
265
266         register short i;
267
268         outshort(s->v_size);
269         for (i = 0; i <= DIVWL(s->v_size - 1); i++) {
270                 outint(s->v_bits[i]);
271         }
272 }
273
274
275
276 putptable(head,pf,all)
277         proc_p head;
278         FILE   *pf;
279         bool   all;
280 {
281         register proc_p p;
282         proc_p next;
283         register short n = 0;
284         /* Write the proc table */
285
286         curoutp = pf;
287         /* Determine the number of procs */
288         for (p = head; p != (proc_p) 0; p = p->p_next) {
289                 n++;
290         }
291         outshort(n);  /* The table is preceded by its length. */
292         outshort ((all?1:0)); /* if all=false, only some of the attributes
293                                  are written. */
294         for (p = head; p != (proc_p) 0; p = next) {
295                 next = p->p_next;
296                 outshort(p->p_id);
297                 outbyte(p->p_flags1);
298                 if (p->p_flags1 & PF_BODYSEEN) {
299                         /* If we have no access to the EM text of the
300                          * body of a procedure, we have no information
301                          * about it whatsoever, so there is nothing
302                          * to output in that case.
303                          */
304                         outshort(p->p_nrlabels);
305                         outoff(p->p_localbytes);
306                         outoff(p->p_nrformals);
307                         if (all) {
308                                 outcset(p->p_change->c_ext);
309                                 outshort(p->p_change->c_flags);
310                                 outshort(p->p_use->u_flags);
311                                 outcset(p->p_calling);
312                                 Cdeleteset(p->p_change->c_ext);
313                                 oldchange(p->p_change);
314                                 olduse(p->p_use);
315                                 Cdeleteset(p->p_calling);
316                         }
317                 }
318                 oldproc(p);
319         }
320         fclose(curoutp);
321         if (pmap != (proc_p *) 0) {
322                 oldmap((short **) pmap,plength);  /* release memory for pmap */
323         }
324 }
325
326
327
328 /* putunit */
329
330 STATIC outloop(l)
331         loop_p l;
332 {
333         outshort((short) l->lp_id);
334 }
335
336
337 STATIC outblock(b)
338         bblock_p b;
339 {
340         if (b == (bblock_p) 0) {
341                 outshort((short) 0);
342         } else {
343                 outshort((short) b->b_id);
344         }
345 }
346
347
348 STATIC outid(e,p)
349         Lelem_t e;
350         int (*p) ();
351 {
352         /* Auxiliary routine used by outlset. */
353
354         /* NOSTRICT */
355         (*p) (e);
356 }
357
358
359 STATIC outlset(s,p)
360         lset s;
361         int (*p) ();
362 {
363         /* A 'long' set is represented externally as a
364          * a sequence of elements terminated by a 0 word.
365          * The procedural parameter p is a routine that
366          * prints an id (proc_id, obj_id etc.).
367          */
368
369         register Lindex i;
370
371         for (i = Lfirst(s); i != (Lindex) 0; i = Lnext(i,s)) {
372                 outid(Lelem(i),p);
373         }
374         outshort((short) 0);
375 }
376
377
378
379 putunit(kind,p,l,gf,lf)
380         short    kind;
381         proc_p   p;
382         line_p   l;
383         FILE     *gf, *lf;
384 {
385         register bblock_p b;
386         register short n = 0;
387         Lindex   pi;
388         loop_p   lp;
389
390         curoutp = gf;
391         if (kind == LDATA) {
392                 outshort(0); /* No basic blocks */
393                 n = putlines(l,lf);
394                 curoutp = gf;
395                 outshort(n);
396                 return;
397         }
398         /* Determine the number of basic blocks */
399         for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
400                 n++;
401         }
402         outshort(n); /* # basic blocks */
403         outshort(Lnrelems(p->p_loops));  /* # loops */
404         for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
405                 n = putlines(b->b_start,lf);
406                 curoutp = gf;
407                 outblock(b);  /* put its block_id */
408                 outshort(n);  /* #instructions of the block */
409                 outlset(b->b_succ, outblock); /* put succ set */
410                 outlset(b->b_pred, outblock); /* put pred set */
411                 outblock(b->b_idom); /* put id of immediate dominator */
412                 outlset(b->b_loops, outloop); /* put loop set */
413                 outshort(b->b_flags);
414         }
415         /* The Control Flow Graph of every procedure is followed
416          * by a description of the loops of the procedure.
417          * Every loop contains an id, an entry block and a level.
418          */
419         for (pi = Lfirst(p->p_loops); pi != (Lindex) 0;
420                                          pi = Lnext(pi,p->p_loops)) {
421                 lp = (loop_p) Lelem(pi);
422                 outloop(lp);    /* id */
423                 outshort(lp->lp_level); /* nesting level */
424                 outblock(lp->lp_entry); /* loop entry block */
425                 outblock(lp->lp_end);
426                 oldloop(lp);
427         }
428         Ldeleteset(p->p_loops);
429         /* We will now release the memory of the basic blocks.
430          * Note that it would be incorrect to release a basic block
431          * after it has been written, because there may be references
432          * to it from other (later) blocks.
433          */
434         for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
435                 Ldeleteset(b->b_loops);
436                 Ldeleteset(b->b_succ);
437                 Ldeleteset(b->b_pred);
438                 oldbblock(b);
439         }
440         /* Release the memory for the lmap, lbmap, bmap, lpmap tables */
441         if (lmap != (line_p *) 0) oldmap((short **) lmap,llength);
442         if (lbmap != (bblock_p *) 0) oldmap((short **) lbmap,llength);
443         if (bmap != (bblock_p *) 0)  oldmap((short **) bmap,blength);
444         if (lpmap != (loop_p *) 0) oldmap((short **) lpmap,lplength);
445         curoutp = lf;
446 }