122 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*  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 <stdio.h>
 | 
						|
#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);
 | 
						|
	}
 | 
						|
}
 |