123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- /* $Id$ */
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /* I N T E R M E D I A T E C O D E
- *
- * I C _ L O O K U P . C
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <em_spec.h>
- #include "../share/types.h"
- #include "../share/debug.h"
- #include "../share/map.h"
- #include "ic.h"
- #include "ic_lookup.h"
- #include "../share/alloc.h"
- sym_p symhash[NSYMHASH];
- prc_p prochash[NPROCHASH];
- num_p numhash[NNUMHASH];
- char *lastname;
- //extern char *strcpy();
- #define newsym() (sym_p) newstruct(sym)
- #define newprc() (prc_p) newstruct(prc)
- #define newnum() (num_p) newstruct(num)
- #define oldsym(x) oldstruct(sym,x)
- #define oldprc(x) oldstruct(prc,x)
- #define oldnum(x) oldstruct(num,x)
- #define PF_FILE 2
- #define DF_FILE 2
- /* instr_lab */
- lab_id instr_lab(number)
- short number;
- {
- register num_p *npp, np;
- /* In EM assembly language, a label is an unsigned number,
- * e.g. 120 in 'BRA *120'. In IC the labels of a procedure
- * are represented by consecutive integer numbers, called
- * lab_id. The mapping takes place here.
- */
- npp = &numhash[number%NNUMHASH];
- while (*npp != (num_p) 0) {
- if ((*npp)->n_number == number) {
- return(*npp)->n_labid;
- } else {
- npp = &(*npp)->n_next;
- }
- }
- /* The label was not found in the hashtable, so
- * create a new entry for it.
- */
- *npp = np = newnum();
- np->n_number = number;
- np->n_labid = ++lastlid;
- /* Assign a new label identifier to the num struct.
- * lastlid is reset to 0 at the beginning of
- * every new EM procedure (by cleaninstrlabs).
- */
- return (np->n_labid);
- }
- /* symlookup */
- STATIC unsigned hash(string) char *string; {
- register char *p;
- register unsigned i,sum;
- for (sum=i=0,p=string;*p;i += 3)
- sum ^= (*p++)<<(i&07);
- return(sum);
- }
- dblock_p symlookup(name, status)
- char *name;
- int status;
- {
- /* Look up the name of a data block. The name can appear
- * in either a defining or applied occurrence (status is
- * DEFINING, OCCURRING resp.), or in a MES ms_ext instruction
- * as the name of a data block imported by a library module
- * (status is IMPORTING). Things get complicated,
- * because a HOL pseudo need not be preceded by a
- * data label, i.e. a hol block need not have a name.
- */
- register sym_p *spp, sp;
- register dblock_p dp;
- if (name == (char *) 0) {
- assert(status == DEFINING);
- dp = newdblock();
- } else {
- spp = &symhash[hash(name)%NSYMHASH];
- while (*spp != (sym_p) 0) {
- /* Every hashtable entry points to a list
- * of synonyms (i.e. names with the same
- * hash values). Try to find 'name' in its
- * list.
- */
- if (strcmp((*spp)->sy_name, name) == 0) {
- dp = (*spp)->sy_dblock;
- if (status != DEFINING ||
- (dp->d_flags1 & DF_EXTERNAL) == 0) {
- dp->d_flags2 |= DF_FILE;
- }
- if (dp->d_flags2 & DF_FILE) {
- lastname = (*spp)->sy_name;
- return dp;
- }
- break;
- } else {
- spp = &(*spp)->sy_next;
- }
- }
- /* The name is not found, so create a new entry for it.
- * However, if the status is IMPORTING, we just return 0,
- * indicating that we don't need this name.
- */
- if (status == IMPORTING) return (dblock_p) 0;
- sp = newsym();
- sp->sy_next = *spp;
- *spp = sp;
- sp->sy_name = (char *) newcore(strlen(name)+1);
- strcpy(sp->sy_name, name);
- lastname = sp->sy_name; /* quick hack to get at
- the name
- */
- dp = sp->sy_dblock = newdblock();
- }
- if (fdblock == (dblock_p) 0) {
- fdblock = dp;
- /* first data block */
- } else {
- ldblock->d_next = dp; /* link to last dblock */
- }
- ldblock = dp;
- dp->d_pseudo = DUNKNOWN; /* clear all fields */
- dp->d_id = ++lastdid;
- dp->d_size = 0;
- dp->d_objlist = (obj_p) 0;
- dp->d_values = (arg_p) 0;
- dp->d_next = (dblock_p) 0;
- dp->d_flags1 = 0;
- dp->d_flags2 = 0;
- if (status == OCCURRING) {
- /* This is the first occurrence of the identifier,
- * so if it is a used occurrence make the
- * identifier externally visible, else make it
- * internal.
- */
- dp->d_flags1 |= DF_EXTERNAL;
- }
- dp->d_flags2 |= DF_FILE;
- return dp;
- }
- /* getsym */
- dblock_p getsym(status)
- int status;
- {
- if (table2() != DLBX) {
- error("symbol expected");
- }
- return(symlookup(string,status));
- }
- /* getproc */
- proc_p getproc(status)
- int status;
- {
- if (table2() != sp_pnam) {
- error("proc name expected");
- }
- return(proclookup(string,status));
- }
- /* proclookup */
- proc_p proclookup(name, status)
- char *name;
- int status;
- {
- register prc_p *ppp, pp;
- register proc_p dp;
- ppp = &prochash[hash(name)%NPROCHASH];
- while (*ppp != (prc_p) 0) {
- /* Every hashtable entry points to a list
- * of synonyms (i.e. names with the same
- * hash values). Try to find 'name' in its
- * list.
- */
- if (strcmp((*ppp)->pr_name, name) == 0) {
- /* found */
- dp = (*ppp)->pr_proc;
- if (status != DEFINING ||
- (dp->p_flags1 & PF_EXTERNAL) == 0) {
- dp->p_flags2 |= PF_FILE;
- return dp;
- }
- if (dp->p_flags2 & PF_FILE) return dp;
- break;
- } else {
- ppp = &(*ppp)->pr_next;
- }
- }
- /* The name is not found, so create a new entry for it,
- * unless the status is IMPORTING, in which case we
- * return 0, indicating we don't want this proc.
- */
- if (status == IMPORTING) return (proc_p) 0;
- pp = newprc();
- pp->pr_next = *ppp;
- *ppp = pp;
- pp->pr_name = (char *) newcore(strlen(name)+1);
- strcpy(pp->pr_name, name);
- dp = pp->pr_proc = newproc();
- if (fproc == (proc_p) 0) {
- fproc = dp; /* first proc */
- } else {
- lproc->p_next = dp;
- }
- lproc = dp;
- dp->p_id = ++lastpid; /* create a unique proc_id */
- dp->p_next = (proc_p) 0;
- dp->p_flags1 = 0;
- dp->p_flags2 = 0;
- if (status == OCCURRING) {
- /* This is the first occurrence of the identifier,
- * so if it is a used occurrence the make the
- * identifier externally visible, else make it
- * internal.
- */
- dp->p_flags1 |= PF_EXTERNAL;
- }
- dp->p_flags2 |= PF_FILE;
- return dp;
- }
- /* cleaninstrlabs */
- cleaninstrlabs()
- {
- register num_p *npp, np, next;
- for (npp = numhash; npp < &numhash[NNUMHASH]; npp++) {
- for (np = *npp; np != (num_p) 0; np = next) {
- next = np->n_next;
- oldnum(np);
- }
- *npp = (num_p) 0;
- }
- /* Reset last label id (used by instr_lab). */
- lastlid = (lab_id) 0;
- }
- /* dump_procnames */
- dump_procnames(hash,n,f)
- prc_p hash[];
- int n;
- FILE *f;
- {
- /* Save the names of the EM procedures in file f.
- * Note that the Optimizer Intermediate Code does not
- * use identifiers but proc_ids, object_ids etc.
- * The names, however, can be used after optimization
- * is completed, to reconstruct Compact Assembly Language.
- * The output consists of tuples (proc_id, name).
- * This routine is called once for every input file.
- * To prevent names of external procedures being written
- * more than once, the PF_WRITTEN flag is used.
- */
- register prc_p *pp, ph;
- proc_p p;
- #define PF_WRITTEN 01
- for (pp = &hash[0]; pp < &hash[n]; pp++) {
- /* Traverse the entire hash table */
- for (ph = *pp; ph != (prc_p) 0; ph = ph->pr_next) {
- /* Traverse the list of synonyms */
- p = ph->pr_proc;
- if ((p->p_flags2 & PF_WRITTEN) == 0) {
- /* not been written yet */
- fprintf(f,"%d %s\n",p->p_id, ph->pr_name);
- p->p_flags2 |= PF_WRITTEN;
- }
- }
- }
- }
- /* cleanprocs */
- cleanprocs(hash,n,mask)
- prc_p hash[];
- int n,mask;
- {
- /* After an EM input file has been processed, the names
- * of those procedures that are internal (i.e. not visible
- * outside the file they are defined in) must be removed
- * from the procedure hash table. This is accomplished
- * by removing the 'prc struct' from its synonym list.
- * After the final input file has been processed, all
- * remaining prc structs are also removed.
- */
- register prc_p *pp, ph, x, next;
- for (pp = &hash[0]; pp < &hash[n]; pp++) {
- /* Traverse the hash table */
- x = (prc_p) 0;
- for (ph = *pp; ph != (prc_p) 0; ph = next) {
- /* Traverse the synonym list.
- * x points to the prc struct just before ph,
- * or is 0 if ph is the first struct of
- * the list.
- */
- ph->pr_proc->p_flags2 &= ~PF_FILE;
- next = ph->pr_next;
- if ((ph->pr_proc->p_flags1 & mask) == 0) {
- if (x == (prc_p) 0) {
- *pp = next;
- } else {
- x->pr_next = next;
- }
- oldprc(ph); /* delete the struct */
- } else {
- x = ph;
- }
- }
- }
- }
- /* dump_dblocknames */
- dump_dblocknames(hash,n,f)
- sym_p hash[];
- int n;
- FILE *f;
- {
- /* Save the names of the EM data blocks in file f.
- * The output consists of tuples (dblock_id, name).
- * This routine is called once for every input file.
- */
- register sym_p *sp, sh;
- dblock_p d;
- #define DF_WRITTEN 01
- for (sp = &hash[0]; sp < &hash[n]; sp++) {
- /* Traverse the entire hash table */
- for (sh = *sp; sh != (sym_p) 0; sh = sh->sy_next) {
- /* Traverse the list of synonyms */
- d = sh->sy_dblock;
- if ((d->d_flags2 & DF_WRITTEN) == 0) {
- /* not been written yet */
- fprintf(f,"%d %s\n",d->d_id, sh->sy_name);
- d->d_flags2 |= DF_WRITTEN;
- }
- }
- }
- }
- /* cleandblocks */
- cleandblocks(hash,n,mask)
- sym_p hash[];
- int n,mask;
- {
- /* After an EM input file has been processed, the names
- * of those data blocks that are internal must be removed.
- */
- register sym_p *sp, sh, x, next;
- for (sp = &hash[0]; sp < &hash[n]; sp++) {
- x = (sym_p) 0;
- for (sh = *sp; sh != (sym_p) 0; sh = next) {
- next = sh->sy_next;
- sh->sy_dblock->d_flags2 &= ~DF_FILE;
- if ((sh->sy_dblock->d_flags1 & mask) == 0) {
- if (x == (sym_p) 0) {
- *sp = next;
- } else {
- x->sy_next = next;
- }
- oldsym(sh); /* delete the struct */
- } else {
- x = sh;
- }
- }
- }
- }
|