/* $Header$ */ /* * (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 L I N E S U B S T I T U T I O N * * I L _ A U X . C */ #include #include "../share/types.h" #include "il.h" #include "../share/debug.h" #include "../share/get.h" #include "../share/put.h" #include "../share/alloc.h" #include "../share/global.h" #include "../share/lset.h" #include "../share/map.h" #include "../../../h/em_spec.h" #include "../../../h/em_mnem.h" #include "../../../h/em_pseu.h" #include "il_aux.h" int tsize(type) int type; { /* Determine the size of a variable of the * given type. */ switch(type) { case SINGLE: return ws; case DOUBLE: return 2*ws; case POINTER: return ps; default: assert(FALSE); } /* NOTREACHED */ } line_p duplicate(lnp) line_p lnp; { /* Make a duplicate of an EM instruction. * Pseudos may not be passed as argument. */ line_p l; l = newline(TYPE(lnp)); l->l_instr = INSTR(lnp); switch(TYPE(l)) { case OPNO: break; case OPSHORT: SHORT(l) = SHORT(lnp); break; case OPOFFSET: OFFSET(l) = OFFSET(lnp); break; case OPINSTRLAB: INSTRLAB(l) = INSTRLAB(lnp); break; case OPOBJECT: OBJ(l) = OBJ(lnp); break; case OPPROC: PROC(l) = PROC(lnp); break; default: assert(FALSE); /* cannot copy pseudo */ } return l; } line_p copy_expr(l1) line_p l1; { /* copy the expression */ line_p head, tail, l, lnp; head = (line_p) 0; for (lnp = l1; lnp != (line_p) 0; lnp = lnp->l_next) { l = duplicate(lnp); if (head == (line_p) 0) { head = tail = l; PREV(l) = (line_p) 0; } else { tail->l_next = l; PREV(l) = tail; tail = l; } } return head; } rem_call(c) call_p c; { actual_p act, nexta; call_p nc,nextc; line_p l, nextl; for (act = c->cl_actuals; act != (actual_p) 0; act = nexta) { nexta = act->ac_next; for (l = act->ac_exp; l != (line_p) 0; l = nextl) { nextl = l->l_next; oldline(l); } oldactual(act); } nc = c->cl_car; oldcall(c); for (; nc != (call_p) 0; nc = nextc) { /* Take care of nested calls */ nextc = nc->cl_cdr; rem_call(nc); } } /* rem_graph */ STATIC short remlines(l) line_p l; { register line_p lnp; line_p next; for (lnp = l; lnp != (line_p) 0; lnp = next) { next = lnp->l_next; oldline(lnp); } } remunit(kind,p,l) short kind; proc_p p; line_p l; { register bblock_p b; bblock_p next; Lindex pi; if (kind == LDATA) { remlines(l); return; } for (b = p->p_start; b != (bblock_p) 0; b = next) { next = b->b_next; remlines(b->b_start); Ldeleteset(b->b_loops); Ldeleteset(b->b_succ); Ldeleteset(b->b_pred); oldbblock(b); } for (pi = Lfirst(p->p_loops); pi != (Lindex) 0; pi = Lnext(pi,p->p_loops)) { oldloop(Lelem(pi)); } Ldeleteset(p->p_loops); oldmap(lmap,llength); oldmap(lbmap,llength); oldmap(bmap,blength); oldmap(lpmap,lplength); } remcc(head) calcnt_p head; { calcnt_p cc, next; for (cc = head; cc != (calcnt_p) 0; cc = next) { next = cc->cc_next; oldcalcnt(cc); } } /* Extra I/O routines */ call_p getcall(cf) FILE *cf; { /* read a call from the call-file */ call_p c; proc_p voided; actual_p act,*app; short n,m; curinp = cf; c = newcall(); n = getshort(); /* void nesting level */ if (feof(curinp)) return (call_p) 0; c->cl_caller = pmap[getshort()]; c->cl_id = getshort(); c->cl_proc = pmap[getshort()]; c->cl_looplevel = getbyte(); c->cl_flags = getbyte(); c->cl_ratio = getshort(); app = &c->cl_actuals; n = getshort(); while(n--) { act = newactual(); m = getshort(); act->ac_size = getoff(); act->ac_inl = getbyte(); act->ac_exp = getlines(cf,m,&voided); *app = act; app = &act->ac_next; } *app = (actual_p) 0; return c; } line_p get_text(lf,p_out) FILE *lf; proc_p *p_out; { /* Read the EM text of one unit * If it is a procedure, set p_out to * the proc. just read. Else set p_out * to 0. */ line_p dumhead, l, lprev; loop_p *oldlpmap = lpmap; line_p *oldlmap = lmap; short oldllength = llength; short oldlastlabid = lastlabid; curinp = lf; *p_out = (proc_p) 0; dumhead = newline(OPNO); /* The list of instructions is preceeded by a dummy * line, to simplify list manipulation */ dumhead->l_instr = op_nop; /* just for fun */ lprev = dumhead; for (;;) { l = read_line(p_out); if (feof(curinp)) return (line_p) 0; lprev->l_next = l; PREV(l) = lprev; if (INSTR(l) == ps_end) break; if (INSTR(l) == ps_mes) { message(l); } lprev = l; } /* The tables that map labels to instructions * and labels to basic blocks are not used. */ if (*p_out != (proc_p) 0) { oldmap(lmap,llength); oldmap(lbmap,llength); lmap = oldlmap; lpmap = oldlpmap; } llength = oldllength; lastlabid = oldlastlabid; return dumhead; } calcnt_p getcc(ccf,p) FILE *ccf; proc_p p; { /* Get call-count info of procedure p */ calcnt_p head,cc,*ccp; short i; fseek(ccf,p->p_extend->px_il.p_ccaddr,0); curinp = ccf; head = (calcnt_p) 0; ccp = &head; for (i = getshort(); i != (short) 0; i--) { cc = *ccp = newcalcnt(); cc->cc_proc = pmap[getshort()]; cc->cc_count = getshort(); ccp = &cc->cc_next; } return head; } /* The following routines are only used by the Inline Substitution phase */ STATIC putactuals(alist,cfile) actual_p alist; FILE *cfile; { /* output a list of actual parameters */ actual_p a,next; line_p l; int count; count = 0; for (a = alist; a != (actual_p) 0; a = a->ac_next) count++; outshort(count); /* number of actuals */ for (a = alist; a != (actual_p) 0; a = next) { next = a->ac_next; count = 0; for (l = a->ac_exp; l != (line_p) 0; l= l->l_next) count++; outshort(count); /* length of actual */ outoff(a->ac_size); outbyte(a->ac_inl); count = putlines(a->ac_exp,cfile); oldactual(a); } } putcall(c,cfile,level) call_p c; FILE *cfile; short level; { /* output a call */ call_p nc,nextc; curoutp = cfile; outshort(level); /* nesting level */ outshort(c->cl_caller->p_id); /* calling proc */ outshort(c->cl_id); outshort(c->cl_proc->p_id); /* called proc */ outbyte(c->cl_looplevel); outbyte(c->cl_flags); outshort(c->cl_ratio); putactuals(c->cl_actuals,cfile); nc = c->cl_car; oldcall(c); for (; nc != (call_p) 0; nc = nextc) { /* take care of nested calls */ nextc = nc->cl_cdr; putcall(nc,cfile,level+1); } } long putcc(head,ccf) calcnt_p head; FILE *ccf; { /* Write call-count information to file ccf. * Return the disk address of the info written. */ calcnt_p cc; long addr; short cnt; addr = ftell(ccf); curoutp = ccf; cnt = 0; for (cc = head; cc != (calcnt_p) 0;cc = cc->cc_next) cnt++; outshort(cnt); for (cc = head; cc != (calcnt_p) 0; cc = cc->cc_next) { outproc(cc->cc_proc); outshort(cc->cc_count); } return addr; }