355 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			355 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Header$ */
 | 
						|
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 */
 | 
						|
 | 
						|
/* V A L U E N U M B E R I N G   M E T H O D */
 | 
						|
 | 
						|
#include <em_mnem.h>
 | 
						|
#include "../share/types.h"
 | 
						|
#include "../share/global.h"
 | 
						|
#include "../share/debug.h"
 | 
						|
#include "../share/aux.h"
 | 
						|
#include "cs.h"
 | 
						|
#include "cs_alloc.h"
 | 
						|
#include "cs_aux.h"
 | 
						|
#include "cs_entity.h"
 | 
						|
#include "cs_avail.h"
 | 
						|
#include "cs_stack.h"
 | 
						|
#include "cs_kill.h"
 | 
						|
#include "cs_partit.h"
 | 
						|
#include "cs_getent.h"
 | 
						|
 | 
						|
STATIC push_entity(enp, lfirst)
 | 
						|
	entity_p enp;
 | 
						|
	line_p lfirst;
 | 
						|
{
 | 
						|
	/* Build token and Push it. */
 | 
						|
 | 
						|
	struct token tk;
 | 
						|
 | 
						|
	tk.tk_vn = enp->en_vn;
 | 
						|
	tk.tk_size = enp->en_size;
 | 
						|
	tk.tk_lfirst = lfirst;
 | 
						|
	Push(&tk);
 | 
						|
}
 | 
						|
 | 
						|
STATIC put_expensive_load(bp, lnp, lfirst, enp)
 | 
						|
	bblock_p bp;
 | 
						|
	line_p lnp, lfirst;
 | 
						|
	entity_p enp;
 | 
						|
{
 | 
						|
	struct avail av;
 | 
						|
	occur_p	ocp;
 | 
						|
 | 
						|
	av.av_instr = INSTR(lnp);
 | 
						|
	av.av_size = enp->en_size;
 | 
						|
	av.av_operand = enp->en_vn;
 | 
						|
 | 
						|
	ocp = newoccur(lfirst, lnp, bp);
 | 
						|
 | 
						|
	av_enter(&av, ocp, EXPENSIVE_LOAD);
 | 
						|
}
 | 
						|
 | 
						|
STATIC put_aar(bp, lnp, lfirst, enp)
 | 
						|
	bblock_p bp;
 | 
						|
	line_p lnp, lfirst;
 | 
						|
	entity_p enp;
 | 
						|
{
 | 
						|
	/* Enp points to an ENARRELEM. We do as if its address was computed. */
 | 
						|
 | 
						|
	struct avail av;
 | 
						|
	occur_p	ocp;
 | 
						|
 | 
						|
	assert(enp->en_kind == ENARRELEM);
 | 
						|
	av.av_instr = op_aar;
 | 
						|
	av.av_size = ps;
 | 
						|
	av.av_ofirst = enp->en_arbase;
 | 
						|
	av.av_osecond = enp->en_index;
 | 
						|
	av.av_othird = enp->en_adesc;
 | 
						|
 | 
						|
	ocp = newoccur(lfirst, lnp, bp);
 | 
						|
 | 
						|
	av_enter(&av, ocp, TERNAIR_OP);
 | 
						|
}
 | 
						|
 | 
						|
STATIC push_avail(avp, lfirst)
 | 
						|
	avail_p avp;
 | 
						|
	line_p lfirst;
 | 
						|
{
 | 
						|
	struct token tk;
 | 
						|
 | 
						|
	tk.tk_vn = avp->av_result;
 | 
						|
	tk.tk_size = avp->av_size;
 | 
						|
	tk.tk_lfirst = lfirst;
 | 
						|
	Push(&tk);
 | 
						|
}
 | 
						|
 | 
						|
STATIC push_unair_op(bp, lnp, tkp1)
 | 
						|
	bblock_p bp;
 | 
						|
	line_p lnp;
 | 
						|
	token_p tkp1;
 | 
						|
{
 | 
						|
	struct avail av;
 | 
						|
	occur_p	ocp;
 | 
						|
 | 
						|
	av.av_instr = INSTR(lnp);
 | 
						|
	av.av_size = avsize(lnp);
 | 
						|
	av.av_operand = tkp1->tk_vn;
 | 
						|
 | 
						|
	ocp = newoccur(tkp1->tk_lfirst, lnp, bp);
 | 
						|
 | 
						|
	push_avail(av_enter(&av, ocp, UNAIR_OP), tkp1->tk_lfirst);
 | 
						|
}
 | 
						|
 | 
						|
STATIC push_binair_op(bp, lnp, tkp1, tkp2)
 | 
						|
	bblock_p bp;
 | 
						|
	line_p lnp;
 | 
						|
	token_p tkp1, tkp2;
 | 
						|
{
 | 
						|
	struct avail av;
 | 
						|
	occur_p	ocp;
 | 
						|
 | 
						|
	av.av_instr = INSTR(lnp);
 | 
						|
	av.av_size = avsize(lnp);
 | 
						|
	av.av_oleft = tkp1->tk_vn;
 | 
						|
	av.av_oright = tkp2->tk_vn;
 | 
						|
 | 
						|
	ocp = newoccur(tkp1->tk_lfirst, lnp, bp);
 | 
						|
 | 
						|
	push_avail(av_enter(&av, ocp, BINAIR_OP), tkp1->tk_lfirst);
 | 
						|
}
 | 
						|
 | 
						|
STATIC push_ternair_op(bp, lnp, tkp1, tkp2, tkp3)
 | 
						|
	bblock_p bp;
 | 
						|
	line_p lnp;
 | 
						|
	token_p tkp1, tkp2, tkp3;
 | 
						|
{
 | 
						|
	struct avail av;
 | 
						|
	occur_p	ocp;
 | 
						|
 | 
						|
	av.av_instr = INSTR(lnp);
 | 
						|
	av.av_size = avsize(lnp);
 | 
						|
	av.av_ofirst = tkp1->tk_vn;
 | 
						|
	av.av_osecond = tkp2->tk_vn;
 | 
						|
	av.av_othird = tkp3->tk_vn;
 | 
						|
 | 
						|
	ocp = newoccur(tkp1->tk_lfirst, lnp, bp);
 | 
						|
 | 
						|
	push_avail(av_enter(&av, ocp, TERNAIR_OP), tkp1->tk_lfirst);
 | 
						|
}
 | 
						|
 | 
						|
STATIC fiddle_stack(lnp)
 | 
						|
	line_p lnp;
 | 
						|
{
 | 
						|
	/* The instruction in lnp does something to the valuenumber-stack. */
 | 
						|
 | 
						|
	struct token dummy;
 | 
						|
	offset size;
 | 
						|
 | 
						|
	/* Partly initialize dummy. */
 | 
						|
	dummy.tk_lfirst = lnp;
 | 
						|
 | 
						|
	switch (INSTR(lnp)) {
 | 
						|
		default:
 | 
						|
			assert(FALSE);
 | 
						|
			break;
 | 
						|
		case op_lor:
 | 
						|
			dummy.tk_vn = newvalnum(); dummy.tk_size = ps;
 | 
						|
			Push(&dummy);
 | 
						|
			break;
 | 
						|
		case op_asp:
 | 
						|
			if ((size = off_set(lnp)) > 0) {
 | 
						|
				Pop(&dummy, size);
 | 
						|
			} else {
 | 
						|
				dummy.tk_vn = newvalnum();
 | 
						|
				dummy.tk_size = size;
 | 
						|
				Push(&dummy);
 | 
						|
			}
 | 
						|
			break;
 | 
						|
		case op_dup:
 | 
						|
			Dup(lnp);
 | 
						|
			break;
 | 
						|
		case op_ass:
 | 
						|
		case op_dus:
 | 
						|
		case op_exg:
 | 
						|
		case op_los:
 | 
						|
			/* Don't waste effort. */
 | 
						|
			clr_stack();
 | 
						|
			break;
 | 
						|
		case op_sig:
 | 
						|
			Pop(&dummy, (offset) ps);
 | 
						|
			break;
 | 
						|
		case op_lfr:
 | 
						|
			dummy.tk_vn = newvalnum();
 | 
						|
			dummy.tk_size = off_set(lnp);
 | 
						|
			Push(&dummy);
 | 
						|
			break;
 | 
						|
		case op_beq:
 | 
						|
		case op_bge:
 | 
						|
		case op_bgt:
 | 
						|
		case op_bne:
 | 
						|
		case op_ble:
 | 
						|
		case op_blt:
 | 
						|
			Pop(&dummy, (offset) ws);
 | 
						|
			Pop(&dummy, (offset) ws);
 | 
						|
			break;
 | 
						|
		case op_bra:
 | 
						|
		case op_csa:/* ??? */
 | 
						|
		case op_csb:/* ??? */
 | 
						|
		case op_gto:/* ??? */
 | 
						|
		case op_ret:/* ??? */
 | 
						|
		case op_rtt:/* ??? */
 | 
						|
			break;
 | 
						|
		case op_zeq:
 | 
						|
		case op_zge:
 | 
						|
		case op_zgt:
 | 
						|
		case op_zne:
 | 
						|
		case op_zle:
 | 
						|
		case op_zlt:
 | 
						|
		case op_trp:
 | 
						|
			Pop(&dummy, (offset) ws);
 | 
						|
			break;
 | 
						|
		case op_rck:
 | 
						|
			Pop(&dummy, (offset) ps);
 | 
						|
			break;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
STATIC proc_p find_proc(vn)
 | 
						|
	valnum vn;
 | 
						|
{
 | 
						|
	/* Find the procedure-identifier with valuenumber vn. */
 | 
						|
 | 
						|
	entity_p enp;
 | 
						|
 | 
						|
	enp = find_entity(vn);
 | 
						|
 | 
						|
	if (enp != (entity_p) 0 && enp->en_kind == ENPROC)
 | 
						|
		return enp->en_pro;
 | 
						|
 | 
						|
	return (proc_p) 0;
 | 
						|
}
 | 
						|
 | 
						|
STATIC side_effects(lnp)
 | 
						|
	line_p lnp;
 | 
						|
{
 | 
						|
	/* Lnp contains a cai or cal instruction. We try to find the callee
 | 
						|
	 * and see what side-effects it has.
 | 
						|
	 */
 | 
						|
	struct token tk;
 | 
						|
	proc_p pp;
 | 
						|
 | 
						|
	if (INSTR(lnp) == op_cai) {
 | 
						|
		Pop(&tk, (offset) ps);
 | 
						|
		pp = find_proc(tk.tk_vn);
 | 
						|
	} else {
 | 
						|
		assert(INSTR(lnp) == op_cal);
 | 
						|
		pp = PROC(lnp);
 | 
						|
	}
 | 
						|
	if (pp != (proc_p) 0) {
 | 
						|
		kill_call(pp);
 | 
						|
	} else {
 | 
						|
		kill_much();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
hopeless(instr)
 | 
						|
	int instr;
 | 
						|
{
 | 
						|
	/* The effect of `instr' is too difficult to
 | 
						|
	 * compute. We assume worst case behaviour.
 | 
						|
	 */
 | 
						|
	switch (instr) {
 | 
						|
		default:
 | 
						|
			assert(FALSE);
 | 
						|
			break;
 | 
						|
		case op_mon:
 | 
						|
		case op_str:
 | 
						|
			/* We can't even trust "static" entities. */
 | 
						|
			kill_all();
 | 
						|
			clr_stack();
 | 
						|
			break;
 | 
						|
		case op_blm:
 | 
						|
		case op_bls:
 | 
						|
		case op_sts:
 | 
						|
			kill_much();
 | 
						|
			clr_stack();
 | 
						|
			break;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
vnm(bp)
 | 
						|
	bblock_p bp;
 | 
						|
{
 | 
						|
	register line_p lnp;
 | 
						|
	register entity_p rep;
 | 
						|
	line_p lfirst;
 | 
						|
	struct token tk, tk1, tk2, tk3;
 | 
						|
 | 
						|
	for (lnp = bp->b_start; lnp != (line_p) 0; lnp = lnp->l_next) {
 | 
						|
 | 
						|
		rep = getentity(lnp, &lfirst);
 | 
						|
		switch (instrgroup(lnp)) {
 | 
						|
			case SIMPLE_LOAD:	
 | 
						|
				push_entity(rep, lfirst);
 | 
						|
				break;
 | 
						|
			case LOAD_ARRAY:
 | 
						|
				put_aar(bp, lnp, lfirst, rep);
 | 
						|
				/* Fall through ... */
 | 
						|
			case EXPENSIVE_LOAD:
 | 
						|
				push_entity(rep, lfirst);
 | 
						|
				put_expensive_load(bp, lnp, lfirst, rep);
 | 
						|
				break;
 | 
						|
			case STORE_DIRECT:
 | 
						|
				kill_direct(rep);
 | 
						|
				Pop(&tk, rep->en_size);
 | 
						|
				rep->en_vn = tk.tk_vn;
 | 
						|
				break;
 | 
						|
			case STORE_ARRAY:
 | 
						|
				put_aar(bp, lnp, lfirst, rep);
 | 
						|
				/* Fall through ... */
 | 
						|
			case STORE_INDIR:
 | 
						|
				kill_indir(rep);
 | 
						|
				Pop(&tk, rep->en_size);
 | 
						|
				rep->en_vn = tk.tk_vn;
 | 
						|
				break;
 | 
						|
			case UNAIR_OP:
 | 
						|
				Pop(&tk1, op11size(lnp));
 | 
						|
				push_unair_op(bp, lnp, &tk1);
 | 
						|
				break;
 | 
						|
			case BINAIR_OP:
 | 
						|
				Pop(&tk2, op22size(lnp));
 | 
						|
				Pop(&tk1, op12size(lnp));
 | 
						|
				push_binair_op(bp, lnp, &tk1, &tk2);
 | 
						|
				break;
 | 
						|
			case TERNAIR_OP:
 | 
						|
				Pop(&tk3, op33size(lnp));
 | 
						|
				Pop(&tk2, op23size(lnp));
 | 
						|
				Pop(&tk1, op13size(lnp));
 | 
						|
				push_ternair_op(bp, lnp, &tk1, &tk2, &tk3);
 | 
						|
				break;
 | 
						|
			case KILL_ENTITY:
 | 
						|
				kill_direct(rep);
 | 
						|
				break;
 | 
						|
			case SIDE_EFFECTS:
 | 
						|
				side_effects(lnp);
 | 
						|
				break;
 | 
						|
			case FIDDLE_STACK:
 | 
						|
				fiddle_stack(lnp);
 | 
						|
				break;
 | 
						|
			case IGNORE:
 | 
						|
				break;
 | 
						|
			case HOPELESS:
 | 
						|
				hopeless(INSTR(lnp));
 | 
						|
				break;
 | 
						|
			case BBLOCK_END:
 | 
						|
				fiddle_stack(lnp);
 | 
						|
				break;
 | 
						|
			default:
 | 
						|
				assert(FALSE);
 | 
						|
				break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |