Pristine Ack-5.5
[Ack-5.5.git] / util / ego / ca / ca.c
1 /* $Id: ca.c,v 1.12 1994/06/24 10:19:37 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  *  C O M P A C T   A S S E M B L Y   L A N G U A G E   G E N E R A T I O N
8  *
9  */
10
11
12 #include <stdio.h>
13 #include <em_pseu.h>
14 #include <em_mes.h>
15 #include "../share/types.h"
16 #include "ca.h"
17 #include "../share/debug.h"
18 #include "../share/global.h"
19 #include "../share/lset.h"
20 #include "../share/files.h"
21 #include "../share/map.h"
22 #include "../share/alloc.h"
23 #include "../share/get.h"
24 #include "ca_put.h"
25
26
27 /* This phase transforms the Intermediate Code of the global optimizer
28  * to 'standard' compact assembly language, which will be processed
29  * by the code generator.
30  */
31
32
33 short   dlength;
34 dblock_p *dmap;
35
36 char **dnames, **pnames;  /* Dynamically allocated arrays of strings.
37                          * pnames[i] contains a pointer to the name
38                          * of the procedure  with proc_id i.
39                          */
40
41
42
43 STATIC line_p get_ca_lines(lf,p_out)
44         FILE *lf;
45         proc_p *p_out;
46 {
47         /* Read lines of EM text and link them.
48          * Register messages are outputted immediately after the PRO.
49          */
50
51         line_p head, *pp, l;
52         line_p headm, *mp;
53         arg_p a;
54
55         curinp = lf; /* EM input file */
56         pp = &head;
57         mp = &headm;
58         headm = (line_p) 0;
59         while (TRUE) {
60                 l = read_line(p_out);
61                 if (feof(curinp)) break;
62                 assert (l != (line_p) 0);
63                 if (INSTR(l) == ps_end && INSTR(head) != ps_pro) {
64                         /* Delete end pseudo after data-unit */
65                         oldline(l);
66                         break;
67                 }
68                 if (INSTR(l) == ps_mes && l->l_a.la_arg->a_a.a_offset == ms_reg) {
69                         /* l is a register message */
70                         if (l->l_a.la_arg->a_next == (arg_p) 0) {
71                                 /* register message without arguments */
72                                 oldline(l);
73                         } else {
74                                 *mp = l;
75                                 mp = &l->l_next;
76                         }
77                 } else {
78                         *pp = l;
79                         pp = &l->l_next;
80                 }
81                 if (INSTR(l) == ps_end) {
82                         break;
83                 }
84         }
85         *pp = (line_p) 0;
86         if (head != (line_p) 0 && INSTR(head) == ps_pro) {
87                 /* append register message without arguments to list */
88                 l = newline(OPLIST);
89                 l->l_instr = ps_mes;
90                 a = ARG(l) = newarg(ARGOFF);
91                 a->a_a.a_offset = ms_reg;
92                 *mp = l;
93                 l->l_next = head->l_next;
94                 head->l_next = headm;
95         } else {
96                 assert(headm == (line_p) 0);
97         }
98         return head;
99 }
100
101 STATIC int makedmap(dbl)
102         dblock_p dbl;
103 {
104         /* construct the dmap table */
105
106         dblock_p d;
107         int cnt;
108
109         /* determine the length of the table */
110
111         cnt = 0;
112         for (d = dbl; d != (dblock_p) 0; d = d->d_next) cnt++;
113         dmap = (dblock_p *) newmap(cnt);
114         for (d = dbl; d != (dblock_p) 0; d = d->d_next) {
115                 assert(d->d_id <= cnt);
116                 dmap[d->d_id] = d;
117         }
118         return cnt;
119 }
120
121
122
123 STATIC getdnames(dumpd)
124         FILE *dumpd;
125 {
126         /* Read the names of the datalabels from
127          * the dump file.
128          */
129
130         char str[IDL+1];
131         int id;
132
133         dnames = (char **) newmap(dlength);
134         for (;;) {
135                 if (fscanf(dumpd,"%d    %s",&id,str) == EOF) return;
136                 assert(id <= dlength);
137                 dnames[id] = (char *) newcore(strlen(str)+1);
138                 strcpy(dnames[id], str);
139         }
140 }
141
142 STATIC getpnames(dumpp)
143         FILE *dumpp;
144 {
145         /* Read the names of the procedures from
146          * the dump file.
147          */
148
149         char str[IDL+1];
150         int id;
151
152         pnames = (char **) newmap(plength);
153         for (;;) {
154                 if (fscanf(dumpp,"%d    %s",&id,str) == EOF) return;
155                 assert(id <= plength);
156                 pnames[id] = (char *) newcore(strlen(str)+1);
157                 strcpy(pnames[id], str);
158         }
159 }
160
161
162
163 STATIC new_name(s)
164         char **s;
165 {
166         static int nn = 0;
167         char buf[20];
168         int len = strlen(*s);
169
170         oldcore(*s, len+1);
171         buf[0] = '_';
172         buf[1] = 'I';
173         buf[2] = 'I';
174         sprintf(&buf[3],"%d",nn);
175         nn++;
176         *s = (char *) newcore(strlen(buf)+1);
177         strcpy(*s, buf);
178 }
179
180
181
182 STATIC uniq_names()
183 {
184         /* The names of all internal procedures and data blocks
185          * are made different. As the optimizer combines several
186          * modules into one, there may be name conflicts between
187          * procedures or data blocks that were internal in
188          * different source modules.
189          */
190
191         proc_p p;
192         dblock_p d;
193
194         for (p = fproc; p != (proc_p) 0; p = p->p_next) {
195                 if (!(p->p_flags1 & PF_EXTERNAL)) {
196                         new_name(&(pnames[p->p_id]));
197                 }
198         }
199         for (d = fdblock; d != (dblock_p) 0; d = d->d_next) {
200                 if (!(d->d_flags1 & DF_EXTERNAL) && dnames[d->d_id]) {
201                         new_name(&(dnames[d->d_id]));
202                 }
203         }
204 }
205
206
207 main(argc,argv)
208         int argc;
209         char *argv[];
210 {
211         /* CA does not output proctable etc. files. Instead, its
212          * pname2 and dname2 arguments contain the names of the
213          * dump files created by IC.
214          */
215         FILE *f, *f2;     /* The EM input and output. */
216         FILE *df, *pf;    /* The dump files */
217         line_p lnp;
218
219         fproc = getptable(pname); /* proc table */
220         fdblock = getdtable(dname);  /* data block table */
221         dlength = makedmap(fdblock); /* allocate dmap table */
222         df = openfile(dname2,"r");
223         getdnames(df);
224         fclose(df);
225         pf = openfile(pname2,"r");
226         getpnames(pf);
227         fclose(pf);
228         uniq_names();
229         f = openfile(lname,"r");
230         f2 = stdout;
231         cputmagic(f2); /* write magic number */
232         while ((lnp = get_ca_lines(f,&curproc)) != (line_p) 0) {
233                 cputlines(lnp,f2);
234         }
235         fclose(f);
236         fclose(f2);
237         exit(0);
238 }