Pristine Ack-5.5
[Ack-5.5.git] / util / ego / ic / ic_aux.c
1 /* $Id: ic_aux.c,v 1.7 1994/06/24 10:24:06 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 /*  I N T E R M E D I A T E   C O D E
7  *
8  *  I C _ A U X . C
9  */
10
11
12
13 #include <em_pseu.h>
14 #include <em_spec.h>
15 #include <em_mnem.h>
16 #include "../share/types.h"
17 #include "../share/global.h"
18 #include "../share/debug.h"
19 #include "../share/def.h"
20 #include "../share/aux.h"
21 #include "ic.h"
22 #include "ic_io.h"
23 #include "ic_lookup.h"
24 #include "../share/alloc.h"
25 #include "ic_aux.h"
26
27
28
29 /* opr_size */
30
31 offset opr_size(instr)
32         short instr;
33 {
34         switch(instr) {
35                 case op_loe:
36                 case op_ste:
37                 case op_ine:
38                 case op_dee:
39                 case op_zre:
40                         return (offset) ws;
41                 case op_lde:
42                 case op_sde:
43                         return (offset) 2*ws;
44                 case op_lae:
45                 case op_fil:
46                 case op_gto:
47                         return (offset) UNKNOWN_SIZE;
48                 default:
49                         error("illegal operand of opr_size: %d", instr);
50         }
51         /* NOTREACHED */
52 }
53
54
55
56 /* dblockdef */
57
58 STATIC offset argsize(arg)
59         arg_p arg;
60 {
61         /* Compute the size (in bytes) that the given initializer
62          * will occupy.
63          */
64
65         offset s;
66         argb_p argb;
67
68         switch(arg->a_type) {
69                 case ARGOFF:
70                         /* See if value fits in a short */
71                         if ((short) arg->a_a.a_offset == arg->a_a.a_offset) {
72                                 return ws;
73                         } else {
74                                 return 2*ws;
75                         }
76                 case ARGINSTRLAB:
77                 case ARGOBJECT:
78                 case ARGPROC:
79                         return ps;  /* pointer size */
80                 case ARGSTRING:
81                         /* strings are partitioned into pieces */
82                         s = 0;
83                         for (argb = &arg->a_a.a_string; argb != (argb_p) 0;
84                            argb = argb->ab_next) {
85                                 s += argb->ab_index;
86                         }
87                         return s;
88                 case ARGICN:
89                 case ARGUCN:
90                 case ARGFCN:
91                         return arg->a_a.a_con.ac_length;
92                 default:
93                         assert(FALSE);
94                 }
95                 /* NOTREACHED */
96 }
97
98
99 STATIC offset blocksize(pseudo,args)
100         byte  pseudo;
101         arg_p args;
102 {
103         /* Determine the number of bytes of a datablock */
104
105         arg_p   arg;
106         offset  sum;
107
108         switch(pseudo) {
109            case DHOL:
110            case DBSS:
111                 if (args->a_type != ARGOFF) {
112                         error("offset expected");
113                 }
114                 return args->a_a.a_offset;
115            case DCON:
116            case DROM:
117                 sum = 0;
118                 for (arg = args; arg != (arg_p) 0; arg = arg->a_next) {
119                         /* Add the sizes of all initializers */
120                         sum += argsize(arg);
121                 }
122                 return sum;
123            default:
124                 assert(FALSE);
125         }
126         /* NOTREACHED */
127 }
128
129
130 STATIC arg_p copy_arg(arg)
131         arg_p arg;
132 {
133         /* Copy one argument */
134
135         arg_p new;
136
137         assert(arg->a_type == ARGOFF);
138         new = newarg(ARGOFF);
139         new->a_a.a_offset = arg->a_a.a_offset;
140         return new;
141 }
142
143
144
145 STATIC arg_p copy_rom(args)
146         arg_p args;
147 {
148         /* Make a copy of the values of a rom,
149          * provided that the rom contains only integer values,
150          */
151
152         arg_p arg, arg2, argh;
153
154         for (arg = args; arg != (arg_p) 0; arg = arg->a_next) {
155                 if (arg->a_type != ARGOFF) {
156                         return (arg_p) 0;
157                 }
158         }
159         /* Now make the copy */
160         arg2 = argh = copy_arg(args);
161         for (arg = args->a_next; arg != (arg_p) 0; arg = arg->a_next) {
162                 arg2->a_next = copy_arg(arg);
163                 arg2 = arg2->a_next;
164         }
165         return argh;
166 }
167
168
169
170 dblockdef(db,n,lnp)
171         dblock_p db;
172         int      n;
173         line_p   lnp;
174 {
175         /* Process a data block defining occurrence */
176
177         byte m;
178
179         switch(n) {
180                 case ps_hol:
181                         m = DHOL;
182                         break;
183                 case ps_bss:
184                         m = DBSS;
185                         break;
186                 case ps_con:
187                         m = DCON;
188                         break;
189                 case ps_rom:
190                         m = DROM;
191                         break;
192                 default:
193                         assert(FALSE);
194         }
195         db->d_pseudo = m;
196         db->d_size = blocksize(m, ARG(lnp));
197         if (m == DROM) {
198                 /* We keep the values of a rom block in the data block
199                  * table if the values consist of integers only.
200                  */
201                 db->d_values = copy_rom(ARG(lnp));
202         }
203 }
204
205
206
207 /* combine */
208
209 combine(db,l1,l2,pseu)
210         dblock_p db;
211         line_p   l1,l2;
212         byte pseu;
213 {
214         /* Combine two successive ROMs/CONs (without a data label
215          * in between into a single ROM. E.g.:
216          *    xyz
217          *     rom 3,6,9,12
218          *     rom 7,0,2
219          * is changed into:
220          *    xyz
221          *     rom 3,6,9,12,7,0,2
222          */
223
224         arg_p v;
225
226         db->d_size += blocksize(pseu,ARG(l2));
227         /* db is the data block that was already assigned to the
228          * first rom/con. The second one is not assigned a new
229          * data block of course, as the two are combined into
230          * one instruction.
231          */
232         if (pseu == DROM && db->d_values != (arg_p) 0) {
233                 /* The values contained in a ROM are only copied
234                  * to the data block if they may be useful to us
235                  * (e.g. they certainly may not be strings). In our
236                  * case it means that both ROMs must have useful
237                  * arguments.
238                  */
239                 for (v = db->d_values; v->a_next != (arg_p) 0; v = v->a_next);
240                 /* The first rom contained useful arguments. v now points to
241                  * its last argument. Append the arguments of the second
242                  * rom to this list. If the second rom has arguments that are
243                  * not useful, throw away the entire list (we want to copy
244                  * everything or nothing).
245                  */
246                 if ((v->a_next = copy_rom(ARG(l2))) == (arg_p) 0) {
247                         oldargs(db->d_values);
248                         db->d_values = (arg_p) 0;
249                 }
250         }
251         for (v = ARG(l1); v->a_next != (arg_p) 0; v = v->a_next);
252         /* combine the arguments of both instructions. */
253         v->a_next = ARG(l2);
254         ARG(l2) = (arg_p) 0;
255 }
256
257
258
259 /* arglist */
260
261 STATIC arg_string(length,abp)
262         offset  length;
263         register argb_p abp;
264 {
265
266         while (length--) {
267                 if (abp->ab_index == NARGBYTES)
268                         abp = abp->ab_next = newargb();
269                 abp->ab_contents[abp->ab_index++] = readchar();
270         }
271 }
272
273
274 line_p arglist(n)
275         int n;
276 {
277         line_p  lnp;
278         register arg_p ap,*app;
279         bool moretocome;
280         offset length;
281
282
283         /*
284          * creates an arglist with n elements
285          * if n == 0 the arglist is variable and terminated by sp_cend
286          */
287
288         lnp = newline(OPLIST);
289         app = &ARG(lnp);
290         moretocome = TRUE;
291         do {
292                 switch(table2()) {
293                 default:
294                         error("unknown byte in arglist");
295                 case CSTX1:
296                         tabval2 = (offset) tabval;
297                 case CSTX2:
298                         *app = ap = newarg(ARGOFF);
299                         ap->a_a.a_offset = tabval2;
300                         app = &ap->a_next;
301                         break;
302                 case ILBX:
303                         *app = ap = newarg(ARGINSTRLAB);
304                         ap->a_a.a_instrlab = instr_lab((short) tabval);
305                         app = &ap->a_next;
306                         break;
307                 case DLBX:
308                         *app = ap = newarg(ARGOBJECT);
309                         ap->a_a.a_obj = object(string,(offset) 0, (offset) 0);
310                         /* The size of the object is unknown */
311                         app = &ap->a_next;
312                         break;
313                 case sp_pnam:
314                         *app = ap = newarg(ARGPROC);
315                         ap->a_a.a_proc = proclookup(string,OCCURRING);
316                         app = &ap->a_next;
317                         break;
318                 case VALX1:
319                         tabval2 = (offset) tabval;
320                 case VALX2:
321                         *app = ap = newarg(ARGOBJECT);
322                         ap->a_a.a_obj = object(string, tabval2, (offset) 0);
323                         app = &ap->a_next;
324                         break;
325                 case sp_scon:
326                         *app = ap = newarg(ARGSTRING);
327                         length = get_off();
328                         arg_string(length,&ap->a_a.a_string);
329                         app = &ap->a_next;
330                         break;
331                 case sp_icon:
332                         *app = ap = newarg(ARGICN);
333                         goto casecon;
334                 case sp_ucon:
335                         *app = ap = newarg(ARGUCN);
336                         goto casecon;
337                 case sp_fcon:
338                         *app = ap = newarg(ARGFCN);
339                 casecon:
340                         length = get_int();
341                         ap->a_a.a_con.ac_length = (short) length;
342                         arg_string(get_off(),&ap->a_a.a_con.ac_con);
343                         app = &ap->a_next;
344                         break;
345                 case sp_cend:
346                         moretocome = FALSE;
347                 }
348                 if (n && (--n) == 0)
349                         moretocome = FALSE;
350         } while (moretocome);
351         return(lnp);
352 }
353
354
355
356 /* is_datalabel */
357
358 bool is_datalabel(l)
359         line_p l;
360 {
361         VL(l);
362         return (l->l_instr == (byte) ps_sym);
363 }
364
365
366
367 /* block_of_lab */
368
369 dblock_p block_of_lab(ident)
370         char *ident;
371 {
372         dblock_p dbl;
373
374         /* Find the datablock with the given name.
375          * Used for defining occurrences.
376          */
377
378         dbl = symlookup(ident,DEFINING);
379         VD(dbl);
380         if (dbl->d_pseudo != DUNKNOWN) {
381                 error("identifier %s redeclared", ident);
382         }
383         return dbl;
384 }
385
386
387
388 /* object */
389
390 STATIC obj_p make_object(dbl,off,size)
391         dblock_p dbl;
392         offset   off;
393         offset   size;
394 {
395         /* Allocate an obj struct with the given attributes
396          * (if it did not exist already).
397          * Return a pointer to the found or newly created object struct.
398          */
399
400         obj_p obj, prev, new;
401
402         /* See if the object was already present in the object list
403          *  of the given datablock. If it is not yet present, find
404          * the right place to insert the new object. Note that
405          * the objects are sorted by offset.
406          */
407         prev = (obj_p) 0;
408         for (obj = dbl->d_objlist; obj != (obj_p) 0; obj = obj->o_next) {
409                 if (obj->o_off >= off) {
410                         break;
411                 }
412                 prev = obj;
413         }
414         /* Note that the data block may contain several objects
415          * with the required offset; we also want the size to
416          * be the right one.
417          */
418         while (obj != (obj_p) 0 && obj->o_off == off) {
419                 if (obj->o_size == UNKNOWN_SIZE) {
420                         obj->o_size = size;
421                         return obj;
422                 } else {
423                         if (size == UNKNOWN_SIZE || obj->o_size == size) {
424                                 return obj;
425                                 /* This is the right one */
426                         } else {
427                                 prev = obj;
428                                 obj = obj->o_next;
429                         }
430                 }
431         }
432         /* Allocate a new object */
433         new = newobject();
434         new->o_id     = ++lastoid;      /* create a unique object id */
435         new->o_off    = off;
436         new->o_size   = size;
437         new->o_dblock = dbl;
438         /* Insert the new object */
439         if (prev == (obj_p) 0) {
440                 dbl->d_objlist = new;
441         } else {
442                 prev->o_next = new;
443         }
444         new->o_next = obj;
445         return new;
446 }
447
448
449
450 obj_p object(ident,off,size)
451         char *ident;
452         offset off;
453         offset size;
454 {
455         dblock_p dbl;
456
457         /* Create an object struct (if it did not yet exist)
458          * for the object with the given size and offset
459          * within the datablock of the given name.
460          */
461
462         dbl = (ident == (char *) 0 ? hol0_db : symlookup(ident, OCCURRING));
463         VD(dbl);
464         return(make_object(dbl,off,size));
465 }