ack/util/opt/backward.c

202 lines
3.9 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 "line.h"
#include "lookup.h"
#include "alloc.h"
#include "proinf.h"
#include <em_spec.h>
#include <em_pseu.h>
#include <em_mnem.h>
#include <em_mes.h>
#include "ext.h"
#include "getline.h"
#include "reg.h"
#define local(x) ((((x)->s_flags&SYMKNOWN) == 0 && \
((x)->s_flags &= ~ SYMGLOBAL)),\
(x)->s_flags |= SYMSEEN)
#define global(x) ((((x)->s_flags&SYMKNOWN) == 0 && \
((x)->s_flags |= SYMGLOBAL)), \
(x)->s_flags |= SYMSEEN)
#define DTYPHOL 1
#define DTYPBSS 2
#define DTYPCON 3
#define DTYPROM 4
byte curdtyp;
bool goodrom;
short curfrag = 3; /* see also peephole.c */
offset rombuf[MAXROM];
int rc;
void backward(void)
{
register line_p lnp;
line_p next;
register arg_p ap;
line_p i, p;
int n;
register sym_p sp;
i = p = (line_p) 0;
curdtyp = 0;
for (lnp = curpro.lastline; lnp != (line_p) 0; lnp = next)
{
next = lnp->l_next;
switch (lnp->l_optyp)
{
case OPSYMBOL:
global(lnp->l_a.la_sp);
break;
case OPSVAL:
global(lnp->l_a.la_sval.lasv_sp);
break;
case OPLVAL:
global(lnp->l_a.la_lval.lalv_sp);
break;
case OPLIST:
ap = lnp->l_a.la_arg;
while (ap != (arg_p) 0)
{
switch (ap->a_typ)
{
case ARGSYM:
global(ap->a_a.a_sp);
break;
case ARGVAL:
global(ap->a_a.a_val.av_sp);
}
ap = ap->a_next;
}
break;
}
/*
* references to symbols are processed now.
* for plain instructions nothing else is needed
*/
switch (lnp->l_instr & BMASK)
{
/*
* count all local occurences for register counts;
* op_lal is omitted and not by accident.
*/
case op_del:
case op_inl:
case op_ldl:
case op_lil:
case op_lol:
case op_sdl:
case op_sil:
case op_stl:
case op_zrl:
switch (lnp->l_optyp)
{
case OPNO:
case OPNUMLAB:
case OPSYMBOL:
case OPSVAL:
case OPLVAL:
case OPLIST:
break;
case OPOFFSET:
incregusage(lnp->l_a.la_offset);
break;
case OPSHORT:
incregusage((offset) lnp->l_a.la_short);
break;
default:
incregusage((offset) (lnp->l_optyp & BMASK) - Z_OPMINI);
break;
}
/* fall through !! */
default:
assert((lnp->l_instr&BMASK)<=op_last);
lnp->l_next = i;
i = lnp;
continue;
case ps_sym:
sp = lnp->l_a.la_sp;
local(sp);
if (curdtyp == DTYPROM && goodrom)
{
sp->s_rom = newrom();
for (n = 0; n < rc; n++)
sp->s_rom[n] = rombuf[n];
}
sp->s_frag = curfrag;
break;
case ps_hol:
curdtyp = DTYPHOL;
curfrag++;
break;
case ps_bss:
curdtyp = DTYPBSS;
curfrag++;
break;
case ps_con:
if (curdtyp != DTYPCON)
{
curdtyp = DTYPCON;
curfrag++;
}
break;
case ps_rom:
if (curdtyp != DTYPROM)
{
curdtyp = DTYPROM;
curfrag++;
}
ap = lnp->l_a.la_arg;
rc = 0;
while (ap != (arg_p) 0 && rc < MAXROM)
{
if (ap->a_typ == ARGOFF)
{
rombuf[rc++] = ap->a_a.a_offset;
ap = ap->a_next;
}
else
ap = (arg_p) 0;
}
goodrom = (rc >= 2);
break;
case ps_mes:
if (prodepth != 0
&& ((int) aoff(lnp->l_a.la_arg, 0) == ms_std
|| (int) aoff(lnp->l_a.la_arg, 0) == ms_stb
|| (int) aoff(lnp->l_a.la_arg, 0) == ms_ego))
{
lnp->l_next = i;
i = lnp;
continue;
}
break;
case ps_inp:
case ps_ina:
local(lnp->l_a.la_sp);
case ps_exp:
case ps_exa:
case ps_exc:
oldline(lnp);
continue;
}
lnp->l_next = p;
p = lnp;
}
if (prodepth != 0)
local(curpro.symbol);
instrs = i;
pseudos = p;
curpro.lastline = (line_p) 0;
}