211 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			211 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 */
 | 
						|
#ifndef NORCSID
 | 
						|
static char rcsid[] = "$Id$";
 | 
						|
#endif
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
#include "param.h"
 | 
						|
#include "instruct.h"
 | 
						|
#include "pseudo.h"
 | 
						|
#include "varinfo.h"
 | 
						|
#include "set.h"
 | 
						|
#include "expr.h"
 | 
						|
#include "iocc.h"
 | 
						|
#include "subr.h"
 | 
						|
#include <cgg_cg.h>
 | 
						|
#include "extern.h"
 | 
						|
 | 
						|
extern int niops;
 | 
						|
extern iocc_t iops[];
 | 
						|
extern int inproc;
 | 
						|
 | 
						|
extern set_t l_sets[];
 | 
						|
extern inst_t l_instances[];
 | 
						|
 | 
						|
extern expr_t subreg_expr(), regno_expr();
 | 
						|
 | 
						|
static struct varinfo * setcoco(int n)
 | 
						|
{
 | 
						|
	struct varinfo *vi;
 | 
						|
 | 
						|
	NEW(vi, struct varinfo);
 | 
						|
	vi->vi_next = VI_NULL;
 | 
						|
	vi->vi_int[0] = INSSETCC;
 | 
						|
	vi->vi_int[1] = n;
 | 
						|
	return (vi);
 | 
						|
}
 | 
						|
 | 
						|
static struct varinfo * generase(int n)
 | 
						|
{
 | 
						|
	struct varinfo *vi;
 | 
						|
 | 
						|
	NEW(vi, struct varinfo);
 | 
						|
	vi->vi_next = VI_NULL;
 | 
						|
	vi->vi_int[0] = INSERASE;
 | 
						|
	vi->vi_int[1] = n;
 | 
						|
	return (vi);
 | 
						|
}
 | 
						|
 | 
						|
static struct varinfo * genremove(int n)
 | 
						|
{
 | 
						|
	struct varinfo *vi;
 | 
						|
 | 
						|
	NEW(vi, struct varinfo);
 | 
						|
	vi->vi_next = VI_NULL;
 | 
						|
	vi->vi_int[0] = INSREMOVE;
 | 
						|
	vi->vi_int[1] = n;
 | 
						|
	return (vi);
 | 
						|
}
 | 
						|
 | 
						|
static int onlyreg(int argno)
 | 
						|
{
 | 
						|
	register int bitno;
 | 
						|
	register short *sp;
 | 
						|
 | 
						|
	if (!argno)
 | 
						|
		argno++;
 | 
						|
	sp = l_sets[tokpatset[argno - 1]].set_val;
 | 
						|
	for (bitno = nregs; bitno < nregs + ntokens; bitno++)
 | 
						|
		if (BIT(sp, bitno))
 | 
						|
			return (0);
 | 
						|
	return (1);
 | 
						|
}
 | 
						|
 | 
						|
static void makescratch(int argno)
 | 
						|
{
 | 
						|
	set_t s;
 | 
						|
 | 
						|
	if (!argno)
 | 
						|
		argno++;
 | 
						|
	if (tokpatro[argno - 1])
 | 
						|
		error("Instruction destroys %%%d, not allowed here", argno);
 | 
						|
	s = l_sets[tokpatset[argno - 1]];
 | 
						|
	BIC(s.set_val, 0);
 | 
						|
	tokpatset[argno - 1] = setlookup(s);
 | 
						|
}
 | 
						|
 | 
						|
struct varinfo *gen_inst(char *ident, int star)
 | 
						|
{
 | 
						|
	register struct varinfo *vi, *retval, *eravi;
 | 
						|
	register instr_p ip;
 | 
						|
	register struct operand *op;
 | 
						|
	register int i;
 | 
						|
	register inst_p insta;
 | 
						|
 | 
						|
	if (star && !inproc)
 | 
						|
		error("Variable instruction only allowed inside proc");
 | 
						|
	for (ip = l_instr; ip < l_instr + ninstr; ip++)
 | 
						|
	{
 | 
						|
		if (strcmp(ident, ip->i_name))
 | 
						|
			continue;
 | 
						|
		if (ip->i_nops != niops)
 | 
						|
			continue;
 | 
						|
		for (i = 0, op = ip->i_oplist; i < niops; i++, op = op->o_next)
 | 
						|
		{
 | 
						|
			if (!subset(iops[i].in_set, l_sets[op->o_setno].set_val, SETSIZE))
 | 
						|
				goto cont;
 | 
						|
		}
 | 
						|
		goto found;
 | 
						|
		/* oh well, one more won't hurt */
 | 
						|
		cont: ;
 | 
						|
	}
 | 
						|
	error("Such an \"%s\" does not exist", ident);
 | 
						|
	return (0);
 | 
						|
	found:
 | 
						|
	NEW(vi, struct varinfo);
 | 
						|
	vi->vi_int[0] = ip - l_instr;
 | 
						|
	vi->vi_int[1] = star;
 | 
						|
	vi->vi_next = 0;
 | 
						|
	retval = vi;
 | 
						|
	for (i = 0; i < niops; i++)
 | 
						|
	{
 | 
						|
		NEW(vi->vi_vi, struct varinfo);
 | 
						|
		vi = vi->vi_vi;
 | 
						|
		vi->vi_int[0] = iops[i].in_index;
 | 
						|
	}
 | 
						|
	vi->vi_vi = 0;
 | 
						|
	vi = retval;
 | 
						|
	for (i = 0, op = ip->i_oplist; i < niops; i++, op = op->o_next)
 | 
						|
	{
 | 
						|
		if (op->o_adorn & AD_CC)
 | 
						|
		{
 | 
						|
			vi->vi_next = setcoco(iops[i].in_index);
 | 
						|
			vi = vi->vi_next;
 | 
						|
		}
 | 
						|
		switch (op->o_adorn & AD_RWMASK)
 | 
						|
		{
 | 
						|
			default:
 | 
						|
				/* Nothing possible to do */
 | 
						|
				break;
 | 
						|
			case AD_RO:
 | 
						|
				/* It might be possible to do something
 | 
						|
				 * here but not now.
 | 
						|
				 */
 | 
						|
				break;
 | 
						|
			case AD_RW:
 | 
						|
			case AD_WO:
 | 
						|
				/* Treated the same for now */
 | 
						|
				insta = &l_instances[iops[i].in_index];
 | 
						|
				switch (insta->in_which)
 | 
						|
				{
 | 
						|
					case IN_COPY:
 | 
						|
						if (insta->in_info[1] == 0
 | 
						|
								&& !onlyreg(insta->in_info[0]))
 | 
						|
							break;
 | 
						|
						makescratch(insta->in_info[0]);
 | 
						|
						vi->vi_next = generase(ex_lookup(
 | 
						|
						EX_SUBREG, insta->in_info[0], insta->in_info[1]));
 | 
						|
						vi = vi->vi_next;
 | 
						|
						break;
 | 
						|
					case IN_MEMB:
 | 
						|
						vi->vi_next = generase(ex_lookup(
 | 
						|
						EX_TOKFIELD, insta->in_info[0], insta->in_info[1]));
 | 
						|
						vi = vi->vi_next;
 | 
						|
						break;
 | 
						|
					case IN_RIDENT:
 | 
						|
						vi->vi_next = generase(ex_lookup(
 | 
						|
						EX_REG, insta->in_info[0], 0));
 | 
						|
						vi = vi->vi_next;
 | 
						|
						break;
 | 
						|
					case IN_ALLOC:
 | 
						|
						vi->vi_next = generase(ex_lookup(
 | 
						|
						EX_ALLREG, insta->in_info[0] + 1, insta->in_info[1]));
 | 
						|
						vi = vi->vi_next;
 | 
						|
						break;
 | 
						|
					case IN_S_DESCR:
 | 
						|
					case IN_D_DESCR:
 | 
						|
					{
 | 
						|
						int temp;
 | 
						|
 | 
						|
						if (insta->in_which == IN_S_DESCR)
 | 
						|
							temp = wordsize;
 | 
						|
						else
 | 
						|
							temp = 2 * wordsize;
 | 
						|
						temp = ex_lookup(EX_REGVAR, insta->in_info[1], temp);
 | 
						|
						vi->vi_next = generase(temp);
 | 
						|
						vi = vi->vi_next;
 | 
						|
						vi->vi_next = genremove(temp);
 | 
						|
						vi = vi->vi_next;
 | 
						|
						break;
 | 
						|
					}
 | 
						|
				}
 | 
						|
				break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	for (eravi = ip->i_erases; eravi != VI_NULL ; eravi = eravi->vi_next)
 | 
						|
	{
 | 
						|
		if (eravi->vi_int[0] < 0)
 | 
						|
			vi->vi_next = setcoco(0);
 | 
						|
		else
 | 
						|
		{
 | 
						|
			vi->vi_next = generase(eravi->vi_int[0]);
 | 
						|
			vi = vi->vi_next;
 | 
						|
			vi->vi_next = genremove(eravi->vi_int[0]);
 | 
						|
		}
 | 
						|
		vi = vi->vi_next;
 | 
						|
	}
 | 
						|
	return (retval);
 | 
						|
}
 |