diff --git a/util/ego/cf/cf.c b/util/ego/cf/cf.c index fe513ea8d..c36694daf 100644 --- a/util/ego/cf/cf.c +++ b/util/ego/cf/cf.c @@ -31,39 +31,37 @@ #include "cf_idom.h" #include "cf_loop.h" -#define newcfbx() (bext_p) newstruct(bext_cf) -#define oldcfbx(x) oldstruct(bext_cf,x) +#define newcfbx() (bext_p) newstruct(bext_cf) +#define oldcfbx(x) oldstruct(bext_cf, x) extern char em_flag[]; -STATIC cset lpi_set; /* set of procedures used in LPI instruction */ -STATIC cset cai_set; /* set of all procedures doing a CAI */ - +STATIC cset lpi_set; /* set of procedures used in LPI instruction */ +STATIC cset cai_set; /* set of all procedures doing a CAI */ /* The procedure getbblocks reads the EM textfile and * partitions every procedure into a number of basic blocks. */ -#define LABEL0 0 -#define LABEL 1 -#define NORMAL 2 -#define JUMP 3 -#define END 4 -#define AFTERPRO 5 -#define INIT 6 - +#define LABEL0 0 +#define LABEL 1 +#define NORMAL 2 +#define JUMP 3 +#define END 4 +#define AFTERPRO 5 +#define INIT 6 /* These global variables are used by getbblocks and nextblock. */ -STATIC bblock_p b, *bp; /* b is the current basic block, bp is +STATIC bblock_p b, *bp; /* b is the current basic block, bp is * the address where the next block has * to be linked. */ -STATIC line_p lnp, *lp; /* lnp is the current line, lp is +STATIC line_p lnp, *lp; /* lnp is the current line, lp is * the address where the next line * has to be linked. */ -STATIC short state; /* We use a finite state machine with the +STATIC short state; /* We use a finite state machine with the * following states: * LABEL0: after the first (successive) * instruction label. @@ -77,7 +75,6 @@ STATIC short state; /* We use a finite state machine with the * INIT: initial state */ - STATIC nextblock() { /* allocate a new basic block structure and @@ -94,40 +91,44 @@ STATIC nextblock() b->b_extend->bx_cf.bx_semi = 0; lp = &lnp->l_next; #ifdef TRACE - fprintf(stderr,"new basic block, id = %d\n",lastbid); + fprintf(stderr, "new basic block, id = %d\n", lastbid); #endif } - STATIC short kind(lnp) - line_p lnp; + line_p lnp; { /* determine if lnp is a label, branch, end or otherwise */ short instr; - byte flow; + byte flow; - if ((instr = INSTR(lnp)) == op_lab) return (short) LABEL; - if (instr == ps_end) return (short) END; - if (instr > sp_lmnem) return (short) NORMAL; /* pseudo */ - if ((flow = (em_flag[instr-sp_fmnem] & EM_FLO)) == FLO_C || - flow == FLO_T) return (short) JUMP; /* conditional/uncond. jump */ - return (short) NORMAL; + if ((instr = INSTR(lnp)) == op_lab) + return (short)LABEL; + if (instr == ps_end) + return (short)END; + if (instr > sp_lmnem) + return (short)NORMAL; /* pseudo */ + if ((flow = (em_flag[instr - sp_fmnem] & EM_FLO)) == FLO_C || flow == FLO_T) + return (short)JUMP; /* conditional/uncond. jump */ + return (short)NORMAL; } - STATIC line_p doread_line(p_out) - proc_p *p_out; + proc_p* p_out; { /* read a line, and check pseudos for procedure addresses */ register line_p lnp = read_line(p_out); - if (lnp && TYPE(lnp) == OPLIST && INSTR(lnp) != ps_mes) { + if (lnp && TYPE(lnp) == OPLIST && INSTR(lnp) != ps_mes) + { register arg_p arg = ARG(lnp); - - while (arg) { - if (arg->a_type == ARGPROC) { + + while (arg) + { + if (arg->a_type == ARGPROC) + { Cadd(arg->a_a.a_proc->p_id, &lpi_set); arg->a_a.a_proc->p_flags1 |= PF_LPI; } @@ -137,34 +138,36 @@ STATIC line_p doread_line(p_out) return lnp; } -STATIC bool getbblocks(fp,kind_out,n_out,g_out,l_out) - FILE *fp; - short *kind_out; - short *n_out; - bblock_p *g_out; - line_p *l_out; +STATIC bool getbblocks(fp, kind_out, n_out, g_out, l_out) + FILE* fp; +short* kind_out; +short* n_out; +bblock_p* g_out; +line_p* l_out; { - bblock_p head = (bblock_p) 0; - line_p headl = (line_p) 0; + bblock_p head = (bblock_p)0; + line_p headl = (line_p)0; - curproc = (proc_p) 0; + curproc = (proc_p)0; /* curproc will get a value when we encounter a PRO pseudo. * If there is no such pseudo, we're reading only data * declarations or messages (outside any proc.). */ curinp = fp; - lastbid = (block_id) 0; /* block identier */ - state = INIT; /* initial state */ + lastbid = (block_id)0; /* block identier */ + state = INIT; /* initial state */ bp = &head; - for (;;) { + for (;;) + { #ifdef TRACE - fprintf(stderr,"state = %d\n",state); + fprintf(stderr, "state = %d\n", state); #endif - switch(state) { + switch (state) + { case LABEL0: nextblock(); - /* Fall through !! */ + /* Fall through !! */ case LABEL: lbmap[INSTRLAB(lnp)] = b; /* The lbmap table contains for each @@ -172,21 +175,26 @@ STATIC bool getbblocks(fp,kind_out,n_out,g_out,l_out) */ lnp = doread_line(&curproc); state = kind(lnp); - if (state != END) { + if (state != END) + { *lp = lnp; lp = &lnp->l_next; } break; case NORMAL: lnp = doread_line(&curproc); - if ( (state = kind(lnp)) == LABEL) { + if ((state = kind(lnp)) == LABEL) + { /* If we come accross a label * here, it must be the beginning * of a new basic block. */ state = LABEL0; - } else { - if (state != END) { + } + else + { + if (state != END) + { *lp = lnp; lp = &lnp->l_next; } @@ -194,9 +202,10 @@ STATIC bool getbblocks(fp,kind_out,n_out,g_out,l_out) break; case JUMP: lnp = doread_line(&curproc); - /* fall through ... */ + /* fall through ... */ case AFTERPRO: - switch(state = kind(lnp)) { + switch (state = kind(lnp)) + { case LABEL: state = LABEL0; break; @@ -209,24 +218,31 @@ STATIC bool getbblocks(fp,kind_out,n_out,g_out,l_out) case END: *lp = lnp; #ifdef TRACE - fprintf(stderr,"at end of proc, %d blocks\n",lastbid); + fprintf(stderr, "at end of proc, %d blocks\n", lastbid); #endif - if (head == (bblock_p) 0) { + if (head == (bblock_p)0) + { *kind_out = LDATA; *l_out = headl; - } else { + } + else + { *kind_out = LTEXT; *g_out = head; - *n_out = (short) lastbid; + *n_out = (short)lastbid; /* number of basic blocks */ } return TRUE; case INIT: lnp = doread_line(&curproc); - if (feof(curinp)) return FALSE; - if (INSTR(lnp) == ps_pro) { + if (feof(curinp)) + return FALSE; + if (INSTR(lnp) == ps_pro) + { state = AFTERPRO; - } else { + } + else + { state = NORMAL; headl = lnp; lp = &lnp->l_next; @@ -236,9 +252,8 @@ STATIC bool getbblocks(fp,kind_out,n_out,g_out,l_out) } } - STATIC interproc_analysis(p) - proc_p p; + proc_p p; { /* Interprocedural analysis of a procedure p determines: * - all procedures called by p (the 'call graph') @@ -255,7 +270,7 @@ STATIC interproc_analysis(p) */ bblock_p b; - line_p lnp; + line_p lnp; bool inloop; /* Allocate memory for structs and sets */ @@ -265,85 +280,90 @@ STATIC interproc_analysis(p) p->p_change->c_ext = Cempty_set(olength); p->p_calling = Cempty_set(plength); - for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) { - inloop = (Lnrelems(b->b_loops) > 0); - for (lnp = b->b_start; lnp != (line_p) 0; lnp = lnp->l_next) { - /* for all instructions of p do */ - switch(INSTR(lnp)) { - case op_cal: - Cadd(PROC(lnp)->p_id, &p->p_calling); - /* add called proc to p_calling */ - if (inloop) { - CALLED_IN_LOOP(PROC(lnp)); - } - break; - case op_cai: - Cadd(p->p_id,&cai_set); - break; - case op_lpi: - Cadd(PROC(lnp)->p_id, &lpi_set); - /* All procedures that have their names used + for (b = p->p_start; b != (bblock_p)0; b = b->b_next) + { + inloop = (Lnrelems(b->b_loops) > 0); + for (lnp = b->b_start; lnp != (line_p)0; lnp = lnp->l_next) + { + /* for all instructions of p do */ + switch (INSTR(lnp)) + { + case op_cal: + Cadd(PROC(lnp)->p_id, &p->p_calling); + /* add called proc to p_calling */ + if (inloop) + { + CALLED_IN_LOOP(PROC(lnp)); + } + break; + case op_cai: + Cadd(p->p_id, &cai_set); + break; + case op_lpi: + Cadd(PROC(lnp)->p_id, &lpi_set); + /* All procedures that have their names used * in an lpi instruction, may be called via * a cai instruction. */ - PROC(lnp)->p_flags1 |= PF_LPI; - break; - case op_ste: - case op_sde: - case op_ine: - case op_dee: - case op_zre: - Cadd(OBJ(lnp)->o_id, &p->p_change->c_ext); - /* Add changed object to c_ext */ - break; - case op_lil: - case op_lof: - case op_loi: - case op_los: - case op_lar: - p->p_use->u_flags |= UF_INDIR; - /* p does a load-indirect */ - break; - case op_sil: - case op_stf: - case op_sti: - case op_sts: - case op_sar: - p->p_change->c_flags |= CF_INDIR; - /* p does a store-indirect */ - break; - case op_blm: - case op_bls: - p->p_use->u_flags |= UF_INDIR; - p->p_change->c_flags |= CF_INDIR; - /* p does both */ - break; - case op_mon: - printf("mon not yet implemented\n"); - break; - case op_lxl: - case op_lxa: - curproc->p_flags1 |= PF_ENVIRON; - break; - case op_lor: - case op_str: - if (SHORT(lnp) == 0) { - curproc->p_flags1 |= PF_ENVIRON; + PROC(lnp)->p_flags1 |= PF_LPI; + break; + case op_ste: + case op_sde: + case op_ine: + case op_dee: + case op_zre: + Cadd(OBJ(lnp)->o_id, &p->p_change->c_ext); + /* Add changed object to c_ext */ + break; + case op_lil: + case op_lof: + case op_loi: + case op_los: + case op_lar: + p->p_use->u_flags |= UF_INDIR; + /* p does a load-indirect */ + break; + case op_sil: + case op_stf: + case op_sti: + case op_sts: + case op_sar: + p->p_change->c_flags |= CF_INDIR; + /* p does a store-indirect */ + break; + case op_blm: + case op_bls: + p->p_use->u_flags |= UF_INDIR; + p->p_change->c_flags |= CF_INDIR; + /* p does both */ + break; + case op_mon: + printf("mon not yet implemented\n"); + break; + case op_lxl: + case op_lxa: + curproc->p_flags1 |= PF_ENVIRON; + break; + case op_lor: + case op_str: + if (SHORT(lnp) == 0) + { + curproc->p_flags1 |= PF_ENVIRON; + } + break; + case ps_mes: + if (aoff(ARG(lnp), 0) == ms_gto) + { + ENTERED_WITH_GTO(curproc); + } + break; } - break; - case ps_mes: - if (aoff(ARG(lnp),0) == ms_gto) { - ENTERED_WITH_GTO(curproc); - } - break; } - } } } - STATIC cf_cleanproc(p) - proc_p p; + proc_p p; { /* Remove the extended data structures of p */ @@ -351,26 +371,26 @@ STATIC cf_cleanproc(p) register Lindex pi; loop_p lp; - for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) { + for (b = p->p_start; b != (bblock_p)0; b = b->b_next) + { oldcfbx(b->b_extend); } - for (pi = Lfirst(p->p_loops); pi != (Lindex) 0; pi = Lnext(pi, - p->p_loops)) { - lp = (loop_p) Lelem(pi); + for (pi = Lfirst(p->p_loops); pi != (Lindex)0; pi = Lnext(pi, + p->p_loops)) + { + lp = (loop_p)Lelem(pi); oldcflpx(lp->lp_extend); } } +#define CH_CHANGE_INDIR(ch) ((ch->c_flags & CF_INDIR) != 0) +#define USE_INDIR(us) ((us->u_flags & UF_INDIR) != 0) +#define CALLS_UNKNOWN(p) (p->p_flags1 & (byte)PF_CALUNKNOWN) +#define ENVIRON(p) (p->p_flags1 & (byte)PF_ENVIRON) - -#define CH_CHANGE_INDIR(ch) ((ch->c_flags & CF_INDIR) != 0) -#define USE_INDIR(us) ((us->u_flags & UF_INDIR) != 0) -#define CALLS_UNKNOWN(p) (p->p_flags1 & (byte) PF_CALUNKNOWN) -#define ENVIRON(p) (p->p_flags1 & (byte) PF_ENVIRON) - - -STATIC bool add_info(q,p) - proc_p q,p; +STATIC bool add_info(q, p) + proc_p q, + p; { /* Determine the consequences for used/changed variables info * of the fact that p calls q. If e.g. q changes a variable X @@ -381,40 +401,48 @@ STATIC bool add_info(q,p) */ change_p chp, chq; - use_p usp, usq; - bool diff = FALSE; + use_p usp, usq; + bool diff = FALSE; chp = p->p_change; chq = q->p_change; usp = p->p_use; usq = q->p_use; - if (!BODY_KNOWN(q)) { + if (!BODY_KNOWN(q)) + { /* q is a procedure of which the body is not available * as EM text. */ - if (CALLS_UNKNOWN(p)) { + if (CALLS_UNKNOWN(p)) + { return FALSE; /* p already called an unknown procedure */ - } else { + } + else + { p->p_flags1 |= PF_CALUNKNOWN; return TRUE; } } - if (CALLS_UNKNOWN(q)) { + if (CALLS_UNKNOWN(q)) + { /* q calls a procedure of which the body is not available * as EM text. */ - if (!CALLS_UNKNOWN(p)) { + if (!CALLS_UNKNOWN(p)) + { p->p_flags1 |= PF_CALUNKNOWN; diff = TRUE; } } - if (IS_CALLED_IN_LOOP(p) && !IS_CALLED_IN_LOOP(q)) { + if (IS_CALLED_IN_LOOP(p) && !IS_CALLED_IN_LOOP(q)) + { CALLED_IN_LOOP(q); diff = TRUE; } - if (!Cis_subset(chq->c_ext, chp->c_ext)) { + if (!Cis_subset(chq->c_ext, chp->c_ext)) + { /* q changes global variables (objects) that * p did not (yet) change. Add all variables * changed by q to the c_ext set of p. @@ -422,21 +450,24 @@ STATIC bool add_info(q,p) Cjoin(chq->c_ext, &chp->c_ext); diff = TRUE; } - if (CH_CHANGE_INDIR(chq) && !CH_CHANGE_INDIR(chp)) { + if (CH_CHANGE_INDIR(chq) && !CH_CHANGE_INDIR(chp)) + { /* q does a change-indirect (sil etc.) * and p did not (yet). */ chp->c_flags |= CF_INDIR; diff = TRUE; } - if (USE_INDIR(usq) && !USE_INDIR(usp)) { + if (USE_INDIR(usq) && !USE_INDIR(usp)) + { /* q does a use-indirect (lil etc.) * and p dis not (yet). */ usp->u_flags |= UF_INDIR; diff = TRUE; } - if (ENVIRON(q) && !ENVIRON(p)) { + if (ENVIRON(q) && !ENVIRON(p)) + { /* q uses or changes local variables in its * environment while p does not (yet). */ @@ -446,94 +477,99 @@ STATIC bool add_info(q,p) return diff; } - - STATIC trans_clos(head) - proc_p head; + proc_p head; { /* Compute the transitive closure of the used/changed * variable information. */ - register proc_p p,q; + register proc_p p, q; Cindex i; bool changes = TRUE; - while(changes) { + while (changes) + { changes = FALSE; - for (p = head; p != (proc_p) 0; p = p->p_next) { - if (!BODY_KNOWN(p)) continue; - for (i = Cfirst(p->p_calling); i != (Cindex) 0; - i = Cnext(i,p->p_calling)) { - q = pmap[Celem(i)]; - if (add_info(q,p)) { - changes = TRUE; + for (p = head; p != (proc_p)0; p = p->p_next) + { + if (!BODY_KNOWN(p)) + continue; + for (i = Cfirst(p->p_calling); i != (Cindex)0; + i = Cnext(i, p->p_calling)) + { + q = pmap[Celem(i)]; + if (add_info(q, p)) + { + changes = TRUE; + } } - } } } } - - - indir_calls() { Cindex i; proc_p p; - for (i = Cfirst(cai_set); i != (Cindex) 0; i = Cnext(i,cai_set)) { - p = pmap[Celem(i)]; /* p does a CAI */ + for (i = Cfirst(cai_set); i != (Cindex)0; i = Cnext(i, cai_set)) + { + p = pmap[Celem(i)]; /* p does a CAI */ Cjoin(lpi_set, &p->p_calling); } Cdeleteset(lpi_set); Cdeleteset(cai_set); } - - -main(argc,argv) - int argc; - char *argv[]; +main(argc, argv) int argc; +char* argv[]; { - FILE *f, *f2, *gf2; /* The EM input, EM output, basic block output */ + FILE* f, *f2, *gf2; /* The EM input, EM output, basic block output */ bblock_p g; short n, kind; line_p l; linecount = 0; fproc = getptable(pname); /* proc table */ - fdblock = getdtable(dname); /* data block table */ + fdblock = getdtable(dname); /* data block table */ lpi_set = Cempty_set(plength); cai_set = Cempty_set(plength); - if ((f = fopen(lname,"r")) == NULL) { + if ((f = fopen(lname, "r")) == NULL) + { error("cannot open %s", lname); } - if ((f2 = fopen(lname2,"w")) == NULL) { + if ((f2 = fopen(lname2, "w")) == NULL) + { error("cannot open %s", lname2); } - if ((gf2 = fopen(bname2,"w")) == NULL) { - error("cannot open %s",bname2); + if ((gf2 = fopen(bname2, "w")) == NULL) + { + error("cannot open %s", bname2); } - while (getbblocks(f,&kind,&n,&g,&l)) { + while (getbblocks(f, &kind, &n, &g, &l)) + { /* read EM text of one unit and * (if it is a procedure) * partition it into n basic blocks. */ - if (kind == LDATA) { - putunit(LDATA,(proc_p) 0,l,gf2,f2); - } else { + if (kind == LDATA) + { + putunit(LDATA, (proc_p)0, l, gf2, f2); + } + else + { curproc->p_start = g; /* The global variable curproc points to the * current procedure. It is set by getbblocks */ control_flow(g); /* compute pred and succ */ - dominators(g,n); /* compute immediate dominators */ + dominators(g, n); /* compute immediate dominators */ loop_detection(curproc); /* compute loops */ interproc_analysis(curproc); /* Interprocedural analysis */ cf_cleanproc(curproc); - putunit(LTEXT,curproc,(line_p) 0,gf2,f2); + putunit(LTEXT, curproc, (line_p)0, gf2, f2); /* output control flow graph + text */ } } @@ -545,13 +581,15 @@ main(argc,argv) /* Compute transitive closure of used/changed * variables information for every procedure. */ - if ((f = fopen(dname2,"w")) == NULL) { - error("cannot open %s",dname2); + if ((f = fopen(dname2, "w")) == NULL) + { + error("cannot open %s", dname2); } - putdtable(fdblock,f); - if ((f = fopen(pname2,"w")) == NULL) { - error("cannot open %s",pname2); + putdtable(fdblock, f); + if ((f = fopen(pname2, "w")) == NULL) + { + error("cannot open %s", pname2); } - putptable(fproc,f,TRUE); + putptable(fproc, f, TRUE); exit(0); }