251 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			251 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* $Id$ */
 | |
| /*
 | |
|  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | |
|  * See the copyright notice in the ACK home directory, in the file "Copyright".
 | |
|  */
 | |
| /*  S H A R E D   F I L E
 | |
|  *
 | |
|  *  A U X I L I A R Y   R O U T I N E S
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <em_mes.h>
 | |
| #include <em_pseu.h>
 | |
| #include "types.h"
 | |
| #include "debug.h"
 | |
| #include "global.h"
 | |
| #include "alloc.h"
 | |
| #include "aux.h"
 | |
| #include "map.h"
 | |
| #include "lset.h"
 | |
| 
 | |
| offset off_set(lnp)
 | |
| 	line_p lnp;
 | |
| {
 | |
| 	switch(lnp->l_optype) {
 | |
| 		case OPSHORT:
 | |
| 			return (offset) SHORT(lnp);
 | |
| 		case OPOFFSET:
 | |
| 			return OFFSET(lnp);
 | |
| 		default:
 | |
| 			assert(FALSE);
 | |
| 	}
 | |
| 	/* NOTREACHED */
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| offset aoff(ap,n)
 | |
| 	register arg_p ap;
 | |
| {
 | |
| 	while (n>0) {
 | |
| 		if (ap != (arg_p) 0)
 | |
| 			ap = ap->a_next;
 | |
| 		n--;
 | |
| 	}
 | |
| 	if (ap == (arg_p) 0)
 | |
| 		error("too few parameters");
 | |
| 	if (ap->a_type != ARGOFF)
 | |
| 		error("offset expected");
 | |
| 	return(ap->a_a.a_offset);
 | |
| }
 | |
| 
 | |
| 
 | |
| offset tmplocal(p,size)
 | |
| 	proc_p p;
 | |
| 	offset   size;
 | |
| {
 | |
| 	/* Allocate a new local variable in the stack frame of p */
 | |
| 
 | |
| 	p->p_localbytes +=  size;
 | |
| 	return -(p->p_localbytes);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| line_p int_line(off)
 | |
| 	offset off;
 | |
| {
 | |
| 	/* Allocate a line struct of type OPSHORT or OPOFFSET,
 | |
| 	 * whichever one fits best.
 | |
| 	 */
 | |
| 
 | |
| 	line_p lnp;
 | |
| 
 | |
| 	if ((short) off == off) {
 | |
| 		/* fits in a short */
 | |
| 		lnp = newline(OPSHORT);
 | |
| 		SHORT(lnp) = (short) off;
 | |
| 	} else {
 | |
| 		lnp = newline(OPOFFSET);
 | |
| 		OFFSET(lnp) = off;
 | |
| 	}
 | |
| 	return lnp;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| line_p reg_mes(tmp,size,typ,score)
 | |
| 	offset tmp;
 | |
| 	short  size;
 | |
| 	int    typ,score;
 | |
| {
 | |
| 	/* Generate a register message */
 | |
| 
 | |
| 	line_p l;
 | |
| 	arg_p a;
 | |
| 
 | |
| #define NEXTARG(a,val) a->a_next = newarg(ARGOFF); a = a->a_next; \
 | |
| 			a->a_a.a_offset = val
 | |
| 	l = newline(OPLIST);
 | |
| 	l->l_instr = ps_mes;
 | |
| 	a = ARG(l) = newarg(ARGOFF);
 | |
| 	a->a_a.a_offset = ms_reg;
 | |
| 	NEXTARG(a,tmp);
 | |
| 	NEXTARG(a,size);
 | |
| 	NEXTARG(a,typ);
 | |
| 	NEXTARG(a,score);
 | |
| 	return l;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool dom(b1,b2)
 | |
| 	bblock_p b1,b2;
 | |
| {
 | |
| 	/* See if b1 dominates b2. Note that a block always
 | |
| 	 * dominates itself.
 | |
| 	 */
 | |
| 
 | |
| 	register bblock_p b;
 | |
| 
 | |
| 	for (b = b2; b != (bblock_p) 0; b = b->b_idom) {
 | |
| 		/* See if b1 is a (not necessarily proper) ancestor
 | |
| 		 * of b2 in the immediate dominator tree.
 | |
| 		 */
 | |
| 		if (b == b1) return TRUE;
 | |
| 	}
 | |
| 	return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| bblock_p common_dom(a,b)
 | |
| 	bblock_p a,b;
 | |
| {
 | |
| 	/* find a basic block that dominates a as well as b;
 | |
| 	 * note that a basic block also dominates itself.
 | |
| 	 */
 | |
| 
 | |
| 	assert (a != (bblock_p) 0);
 | |
| 	assert (b != (bblock_p) 0);
 | |
| 	if (dom(a,b)) {
 | |
| 		return a;
 | |
| 	} else {
 | |
| 		if (dom(b,a)) {
 | |
| 			return b;
 | |
| 		} else {
 | |
| 			return common_dom(a->b_idom,b->b_idom);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| #define R	time_space_ratio
 | |
| 
 | |
| short add_timespace(time,space)
 | |
| 	short time,space;
 | |
| {
 | |
| 	/* Add together a time and space, using the time_space_ratio
 | |
| 	 * parameter that may be set by the user, indicating the need
 | |
| 	 * to optimize for time, space or something in between.
 | |
| 	 */
 | |
| 
 | |
| 	return (R * time + (100 - R) * space) / 100;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| rm_line(l,b)
 | |
| 	line_p l;
 | |
| 	bblock_p b;
 | |
| {
 | |
| 	if (b->b_start == l) {
 | |
| 		b->b_start = l->l_next;
 | |
| 	} else {
 | |
| 		PREV(l)->l_next = l->l_next;
 | |
| 	}
 | |
| 	if (l->l_next != (line_p) 0) {
 | |
| 		PREV(l->l_next) = PREV(l);
 | |
| 	}
 | |
| 	oldline(l);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| appnd_line(l1,l2)
 | |
| 	line_p l1,l2;
 | |
| {
 | |
| 	/* Put l1 after l2 */
 | |
| 
 | |
| 	PREV(l1) = l2;
 | |
| 	l1->l_next = l2->l_next;
 | |
| 	l2->l_next = l1;
 | |
| 	if (l1->l_next != (line_p) 0) {
 | |
| 		PREV(l1->l_next) = l1;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| line_p last_instr(b)
 | |
| 	bblock_p b;
 | |
| {
 | |
| 	/* Determine the last line of a list */
 | |
| 
 | |
| 	register line_p l = b->b_start;
 | |
| 
 | |
| 	if (l == (line_p) 0) return (line_p) 0;
 | |
| 	while (l->l_next != (line_p) 0) l = l->l_next;
 | |
| 	return l;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| line_p find_mesreg(off)
 | |
| 	offset off;
 | |
| {
 | |
| 	/* Find the register message for the local with the given offset */
 | |
| 
 | |
| 	Lindex li;
 | |
| 	line_p l;
 | |
| 
 | |
| 	for (li = Lfirst(mesregs); li != (Lindex) 0; li = Lnext(li,mesregs)) {
 | |
| 		l = (line_p) Lelem(li);
 | |
| 		if (aoff(ARG(l),1) == off) return l;
 | |
| 	}
 | |
| 	return (line_p) 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool is_regvar(off)
 | |
| 	offset off;
 | |
| {
 | |
| 	return find_mesreg(off) != (line_p) 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| offset regv_arg(off,n)
 | |
| 	offset off;
 | |
| 	int n;
 | |
| {
 | |
| 	/* fetch the n'th argument of the register message of the
 | |
| 	 * local variable at offset off;
 | |
| 	 */
 | |
| 
 | |
| 	line_p x = find_mesreg(off);
 | |
| 	assert (x != (line_p) 0);
 | |
| 	return aoff(ARG(x),n);
 | |
| }
 |