/* I N L I N E S U B S T I T U T I O N * * I L 3 _ S U B S T . C */ #include #include "../share/types.h" #include "il.h" #include "../share/debug.h" #include "../share/alloc.h" #include "../share/global.h" #include "../share/lset.h" #include "../share/get.h" #include "../../../h/em_mnem.h" #include "il_aux.h" #include "il3_aux.h" #include "il3_change.h" #include "il3_subst.h" STATIC line_p fetch_text(lf,c) FILE *lf; call_p c; { /* Read the EM text of the called procedure. * We use random access I/O here. */ line_p l; proc_p p; lset savmes; savmes = mesregs; mesregs = Lempty_set(); fseek(lf,c->cl_proc->P_LADDR,0); l = get_text(lf,&p); assert (p == c->cl_proc); Ldeleteset(mesregs); mesregs = savmes; return l; } line_p scan_to_cal(lines,n) line_p lines; short n; { /* Find the n-th CAL instruction */ register line_p l; for (l = lines; l != (line_p) 0; l = l->l_next) { if (INSTR(l) == op_cal) { if (--n == 0) return l; } } return (line_p) 0; /* CAL not found */ } substitute(lf,c,cal,firstline) FILE *lf; call_p c; line_p cal,firstline; { /* Perform in line substitution of the call described * by c. The EM text of the called routine is fetched * and modified, the calling sequence is changed, * the modified routine is put at the place of the call * and all global information (proctable etc.) is kept * up to date. */ line_p l, text, lab; offset ab_off, lb_off; line_p startscan, ncal; short lastcid; call_p nc; Ssubst++; ab_off = - curproc->p_localbytes; /* offset of temporaries for parameters * that are not expanded in line. */ chg_callseq(c,cal,&l); /* Change the calling sequence; l points to the place * where the expanded text must be put */ text = fetch_text(lf,c); /* fetch EM text of called routine */ lb_off = - curproc->p_localbytes; /* offset of temps. for locals of called proc. */ curproc->p_localbytes += c->cl_proc->P_ORGLOCALS; /* locals of called routine are put in stack frame of caller */ if (!FALLTHROUGH(c->cl_proc)) { /* The called proc contains one or more RETurns * somewhere in the middle of its text; these * should be changed into a jump to the end * of the text. We create a label for this * purpose (if there was no one already). */ lab = make_label(l,curproc); } modify(text,c,lab,ab_off,lb_off,curproc->p_nrlabels); curproc->p_nrlabels += c->cl_proc->P_ORGLABELS; insert(text,l,firstline); /* insert text; instructions are put after l, pseudos * are put at beginning of caller. */ /* Now take care of the nested calls */ startscan = l->l_next; lastcid = 0; for (nc = c->cl_car; nc != (call_p) 0; nc = nc->cl_cdr) { mod_actuals(nc,c,lab,ab_off,lb_off,curproc->p_nrlabels); ncal = scan_to_cal(startscan,nc->cl_id - lastcid); assert(ncal != (line_p) 0); startscan = scan_to_cal(ncal->l_next,1); lastcid = nc->cl_id; substitute(lf,nc,ncal,firstline); } }