229 lines
		
	
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			229 lines
		
	
	
	
		
			5.1 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".
 | |
|  *
 | |
|  * Author: Hans van Staveren
 | |
|  */
 | |
| #include <assert.h>
 | |
| #include "param.h"
 | |
| #include "types.h"
 | |
| #include "tes.h"
 | |
| #include <em_spec.h>
 | |
| #include <em_pseu.h>
 | |
| #include "alloc.h"
 | |
| #include "util.h"
 | |
| #include "putline.h"
 | |
| #include "line.h"
 | |
| #include "reg.h"
 | |
| #include "lookup.h"
 | |
| #include "proinf.h"
 | |
| #include "ext.h"
 | |
| 
 | |
| /* External definitions */
 | |
| extern void flow(void);
 | |
| extern void backward(void);
 | |
| extern int peephole(void);
 | |
| 
 | |
| static void relabel(void)
 | |
| {
 | |
| 	register num_p *npp, np, tp;
 | |
| 	register num_p repl, ttp;
 | |
| 
 | |
| 	/*
 | |
| 	 * For each label find its final destination after crossjumping.
 | |
| 	 * Care has to be taken to prevent a loop in the program to
 | |
| 	 * cause same in the optimizer.
 | |
| 	 */
 | |
| 
 | |
| 	for (npp = curpro.numhash; npp < &curpro.numhash[NNUMHASH]; npp++)
 | |
| 		for (np = *npp; np != (num_p) 0; np = np->n_next)
 | |
| 		{
 | |
| 			assert(
 | |
| 					! np->n_line || ((np->n_line->l_instr&BMASK) == op_lab && np->n_line->l_a.la_np == np));
 | |
| 			for (tp = np; (tp->n_flags & (NUMKNOWN | NUMMARK)) == 0;
 | |
| 					tp = tp->n_repl)
 | |
| 				tp->n_flags |= NUMMARK;
 | |
| 			repl = tp->n_repl;
 | |
| 			for (tp = np; tp->n_flags & NUMMARK; tp = ttp)
 | |
| 			{
 | |
| 				ttp = tp->n_repl;
 | |
| 				tp->n_repl = repl;
 | |
| 				tp->n_flags &= ~ NUMMARK;
 | |
| 				tp->n_flags |= NUMKNOWN;
 | |
| 			}
 | |
| 		}
 | |
| 	for (npp = curpro.numhash; npp < &curpro.numhash[NNUMHASH]; npp++)
 | |
| 		for (np = *npp; np != (num_p) 0; np = np->n_next)
 | |
| 		{
 | |
| 			np->n_flags &= ~(NUMKNOWN | NUMSCAN | NUMREACH);
 | |
| 			np->n_jumps = 0;
 | |
| 		}
 | |
| }
 | |
| 
 | |
| static void symknown(void)
 | |
| {
 | |
| 	register sym_p *spp, sp;
 | |
| 
 | |
| 	for (spp = symhash; spp < &symhash[NSYMHASH]; spp++)
 | |
| 		for (sp = *spp; sp != (sym_p) 0; sp = sp->s_next)
 | |
| 			if (sp->s_flags & SYMSEEN)
 | |
| 				sp->s_flags |= SYMKNOWN;
 | |
| }
 | |
| 
 | |
| static void cleanlocals(void)
 | |
| {
 | |
| 	register num_p *npp, np, tp;
 | |
| 
 | |
| 	for (npp = curpro.numhash; npp < &curpro.numhash[NNUMHASH]; npp++)
 | |
| 	{
 | |
| 		np = *npp;
 | |
| 		while (np != (num_p) 0)
 | |
| 		{
 | |
| 			tp = np->n_next;
 | |
| 			oldnum(np);
 | |
| 			np = tp;
 | |
| 		}
 | |
| 		*npp = (num_p) 0;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void checklocs(void)
 | |
| {
 | |
| 	register num_p *npp, np;
 | |
| 
 | |
| 	for (npp = curpro.numhash; npp < &curpro.numhash[NNUMHASH]; npp++)
 | |
| 		for (np = *npp; np != (num_p) 0; np = np->n_next)
 | |
| 			if (np->n_line == (line_p) 0)
 | |
| 				error("local label %u undefined", (unsigned) np->n_number);
 | |
| }
 | |
| 
 | |
| static offset align(offset count, offset alignment)
 | |
| {
 | |
| 
 | |
| 	assert(alignment == 1 || alignment == 2 || alignment == 4);
 | |
| 	return ((count + alignment - 1) & ~(alignment - 1));
 | |
| }
 | |
| 
 | |
| static void symvalue(void)
 | |
| {
 | |
| 	register line_p lp;
 | |
| 	register sym_p sp;
 | |
| 	register arg_p ap;
 | |
| 	register argb_p abp;
 | |
| 	short curfrag = 0;
 | |
| 	offset count;
 | |
| 
 | |
| 	for (lp = pseudos; lp != (line_p) 0; lp = lp->l_next)
 | |
| 		switch (lp->l_instr & BMASK)
 | |
| 		{
 | |
| 			default:
 | |
| 				assert(FALSE);
 | |
| 				break;
 | |
| 			case ps_sym:
 | |
| 				sp = lp->l_a.la_sp;
 | |
| 				if (sp->s_frag != curfrag)
 | |
| 				{
 | |
| 					count = 0;
 | |
| 					curfrag = sp->s_frag;
 | |
| 				}
 | |
| 				count = align(count, wordsize);
 | |
| 				sp->s_value = count;
 | |
| 				break;
 | |
| 			case ps_bss:
 | |
| 			case ps_hol:
 | |
| 				/* nothing to do, all bss pseudos are in diff frags */
 | |
| 			case ps_mes:
 | |
| 				break;
 | |
| 			case ps_con:
 | |
| 			case ps_rom:
 | |
| 				for (ap = lp->l_a.la_arg; ap != (arg_p) 0; ap = ap->a_next)
 | |
| 					switch (ap->a_typ)
 | |
| 					{
 | |
| 						default:
 | |
| 							assert(FALSE);
 | |
| 						case ARGOFF:
 | |
| 							count = align(count, wordsize) + wordsize;
 | |
| 							break;
 | |
| 						case ARGNUM:
 | |
| 						case ARGSYM:
 | |
| 						case ARGVAL:
 | |
| 							count = align(count, wordsize) + pointersize;
 | |
| 							break;
 | |
| 						case ARGICN:
 | |
| 						case ARGUCN:
 | |
| 						case ARGFCN:
 | |
| 							if (ap->a_a.a_con.ac_length < wordsize)
 | |
| 								count = align(count,
 | |
| 										(offset) ap->a_a.a_con.ac_length);
 | |
| 							else
 | |
| 								count = align(count, wordsize);
 | |
| 							count += ap->a_a.a_con.ac_length;
 | |
| 							break;
 | |
| 						case ARGSTR:
 | |
| 							for (abp = &ap->a_a.a_string; abp != (argb_p) 0;
 | |
| 									abp = abp->ab_next)
 | |
| 								count += abp->ab_index;
 | |
| 							break;
 | |
| 					}
 | |
| 		}
 | |
| }
 | |
| 
 | |
| static void do_tes(void)
 | |
| {
 | |
| 	register line_p insptr = instrs, oldlin = NULL, oldlin2 = NULL;
 | |
| 
 | |
| 	init_state();
 | |
| 	tes_pseudos();
 | |
| 	while (insptr != NULL)
 | |
| 	{
 | |
| 		tes_instr(insptr, oldlin, oldlin2);
 | |
| 		oldlin2 = oldlin;
 | |
| 		oldlin = insptr;
 | |
| 		insptr = insptr->l_next;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void process(void)
 | |
| {
 | |
| 
 | |
| 	if (wordsize == 0 || pointersize == 0)
 | |
| 		error("No MES EMX encountered");
 | |
| 	backward(); /* reverse and cleanup list */
 | |
| 	symknown(); /* symbol scope is now known */
 | |
| 	if (!nflag)
 | |
| 		symvalue(); /* give symbols value */
 | |
| 	if (prodepth != 0)
 | |
| 	{
 | |
| 		if (!nflag)
 | |
| 		{
 | |
| 			int npasses = 0;
 | |
| 			bool madeopt;
 | |
| 
 | |
| 			checklocs(); /* check definition of locals */
 | |
| 			do
 | |
| 			{
 | |
| 				madeopt = peephole(); /* local optimization */
 | |
| 				relabel(); /* relabel local labels */
 | |
| 				flow(); /* throw away unreachable code */
 | |
| 			} while (madeopt && ++npasses < 5000);
 | |
| 			assert(!madeopt);
 | |
| 		}
 | |
| 		do_tes(); /* top elt. size computation phase */
 | |
| 		outpro(); /* generate PRO pseudo */
 | |
| 		outregs(); /* generate MES ms_reg pseudos */
 | |
| 		outtes(); /* generate MES ms_tes pseudos */
 | |
| 	}
 | |
| 	putlines(pseudos); /* pseudos first */
 | |
| 	if (prodepth != 0)
 | |
| 	{
 | |
| 		putlines(instrs); /* instructions next */
 | |
| 		outend(); /* generate END pseudo */
 | |
| 		cleanlocals(); /* forget instruction labels */
 | |
| 	}
 | |
| 	else if (instrs != (line_p) 0)
 | |
| 		error("instructions outside procedure");
 | |
| #ifdef COREDEBUG
 | |
| 	coreverbose();
 | |
| #endif
 | |
| }
 | |
| 
 |