9037d137f5
This uncovers a problem in il/il_aux.c: it passes 3 arguments to getlines(), but the function expects 4 arguments. I add FALSE as the 4th argument. TRUE would fill in the list of mesregs. IL uses mesregs during phase 1, but this call to getlines() is in phase 2. TRUE would leak memory unless I added a call to Ldeleteset(mesregs). So I pass FALSE. Functions passed to go() now have a `void *` parameter because no_action() now takes a `void *`.
233 lines
3.9 KiB
C
233 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(line_p lnp)
|
|
{
|
|
switch(lnp->l_optype) {
|
|
case OPSHORT:
|
|
return (offset) SHORT(lnp);
|
|
case OPOFFSET:
|
|
return OFFSET(lnp);
|
|
default:
|
|
assert(FALSE);
|
|
}
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
|
|
|
|
|
|
offset aoff(arg_p ap, int n)
|
|
{
|
|
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(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(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(offset tmp, short size, int typ, int 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(bblock_p b1, bblock_p 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(bblock_p a, bblock_p 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(short time, short 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;
|
|
}
|
|
|
|
|
|
|
|
void rm_line(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);
|
|
}
|
|
|
|
|
|
|
|
|
|
void appnd_line(line_p l1, line_p 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(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(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(offset off)
|
|
{
|
|
return find_mesreg(off) != (line_p) 0;
|
|
}
|
|
|
|
|
|
|
|
offset regv_arg(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);
|
|
}
|