/* $Header$ */ /* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ /* * 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 * */ #include #include "../share/types.h" #include "ca.h" #include "../share/debug.h" #include "../share/global.h" #include "../share/lset.h" #include "../share/files.h" #include "../share/map.h" #include "../share/alloc.h" #include "../share/get.h" #include "../../../h/em_pseu.h" #include "../../../h/em_mes.h" #include "ca_put.h" /* This phase transforms the Intermediate Code of the global optimizer * to 'standard' compact assembly language, which will be processed * by the code generator. */ short dlength; dblock_p *dmap; char **dnames, **pnames; /* Dynamically allocated arrays of strings. * pnames[i] contains a pointer to the name * of the procedure with proc_id i. */ STATIC char **newnametab(tablen,namelen) short tablen,namelen; { register char **np, **tab; tab = (char **) newmap(tablen); for (np = &tab[1]; np <= &tab[tablen]; np++) { *np = (char *) newcore(namelen); } return tab; } STATIC line_p get_ca_lines(lf,p_out) FILE *lf; proc_p *p_out; { /* Read lines of EM text and link them. * Register messages are outputted immediately after the PRO. */ line_p head, *pp, l; line_p headm, *mp; arg_p a; curinp = lf; /* EM input file */ pp = &head; mp = &headm; headm = (line_p) 0; while (TRUE) { l = read_line(p_out); if (feof(curinp)) break; assert (l != (line_p) 0); if (INSTR(l) == ps_end && INSTR(head) != ps_pro) { /* Delete end pseudo after data-unit */ oldline(l); break; } if (INSTR(l) == ps_mes && l->l_a.la_arg->a_a.a_offset == ms_reg) { /* l is a register message */ if (l->l_a.la_arg->a_next == (arg_p) 0) { /* register message without arguments */ oldline(l); } else { *mp = l; mp = &l->l_next; } } else { *pp = l; pp = &l->l_next; } if (INSTR(l) == ps_end) { break; } } *pp = (line_p) 0; if (head != (line_p) 0 && INSTR(head) == ps_pro) { /* append register message without arguments to list */ l = newline(OPLIST); l->l_instr = ps_mes; a = ARG(l) = newarg(ARGOFF); a->a_a.a_offset = ms_reg; *mp = l; l->l_next = head->l_next; head->l_next = headm; } else { assert(headm == (line_p) 0); } return head; } STATIC int makedmap(dbl) dblock_p dbl; { /* construct the dmap table */ dblock_p d; int cnt; /* determine the length of the table */ cnt = 0; for (d = dbl; d != (dblock_p) 0; d = d->d_next) cnt++; dmap = (dblock_p *) newmap(cnt); for (d = dbl; d != (dblock_p) 0; d = d->d_next) { assert(d->d_id) <= cnt; dmap[d->d_id] = d; } return cnt; } STATIC getdnames(dumpd) FILE *dumpd; { /* Read the names of the datalabels from * the dump file. */ char str[IDL+1]; char *s; int id; register int i; dnames = (char **) newnametab(dlength,IDL); for (;;) { if (fscanf(dumpd,"%d %s",&id,str) == EOF) return; assert(id <= dlength); s = dnames[id]; for (i = 0; i < IDL; i++) { *s++ = str[i]; } } } STATIC getpnames(dumpp) FILE *dumpp; { /* Read the names of the procedures from * the dump file. */ char str[IDL+1]; char *s; int id; register int i; pnames = (char **) newnametab(plength,IDL); for (;;) { if (fscanf(dumpp,"%d %s",&id,str) == EOF) return; assert(id <= plength); s = pnames[id]; for (i = 0; i < IDL; i++) { *s++ = str[i]; } } } STATIC bool name_exists(name,endp,endd) char *name; proc_p endp; dblock_p endd; { /* Search the proctable (from fproc to endp) * and the data block table (from fdblock to endd) * to see if the name is already in use. */ proc_p p; dblock_p d; for (p = fproc; p != endp; p = p->p_next) { if (strncmp(name,pnames[p->p_id],IDL) == 0) return TRUE; } for (d = fdblock; d != endd; d = d->d_next) { if (strncmp(name,dnames[d->d_id],IDL) == 0) return TRUE; } return FALSE; } static int nn = 0; STATIC new_name(s) char *s; { s[0] = '_'; s[1] = 'I'; s[2] = 'I'; sprintf(&s[3],"%d",nn); nn++; } STATIC uniq_names() { /* The names of all internal procedures and data blocks * are made different. As the optimizer combines several * modules into one, there may be name conflicts between * procedures or data blocks that were internal in * different source modules. */ proc_p p; dblock_p d; for (p = fproc; p != (proc_p) 0; p = p->p_next) { if (!(p->p_flags1 & PF_EXTERNAL) && name_exists(pnames[p->p_id],p,fdblock)) { new_name(pnames[p->p_id]); } } for (d = fdblock; d != (dblock_p) 0; d = d->d_next) { if (!(d->d_flags1 & DF_EXTERNAL) && name_exists(dnames[d->d_id],(proc_p) 0,d) ) { new_name(dnames[d->d_id]); } } } main(argc,argv) int argc; char *argv[]; { /* CA does not output proctable etc. files. Instead, its * pname2 and dname2 arguments contain the names of the * dump files created by IC. */ FILE *f, *f2; /* The EM input and output. */ FILE *df, *pf; /* The dump files */ line_p lnp; fproc = getptable(pname); /* proc table */ fdblock = getdtable(dname); /* data block table */ dlength = makedmap(fdblock); /* allocate dmap table */ df = openfile(dname2,"r"); getdnames(df); fclose(df); pf = openfile(pname2,"r"); getpnames(pf); fclose(pf); uniq_names(); f = openfile(lname,"r"); f2 = stdout; cputmagic(f2); /* write magic number */ while ((lnp = get_ca_lines(f,&curproc)) != (line_p) 0) { cputlines(lnp,f2); } fclose(f); fclose(f2); exit(0); }