ack/util/ego/il/il1_anal.c
1994-06-24 11:31:16 +00:00

186 lines
3.8 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".
*/
/* I N L I N E S U B S T I T U T I O N
*
* I L 1 _ A N A L . C
*/
#include <stdio.h>
#include <em_mnem.h>
#include <em_pseu.h>
#include "../share/types.h"
#include "il.h"
#include "../share/debug.h"
#include "../share/alloc.h"
#include "../share/global.h"
#include "../share/lset.h"
#include "../share/aux.h"
#include "il1_aux.h"
#include "il1_formal.h"
#include "il1_cal.h"
#include "il1_anal.h"
#include "il_aux.h"
#include "../share/put.h"
#define ENVIRON(p) (p->p_flags1 & (byte) PF_ENVIRON)
#define RETURN_BLOCK(b) (Lnrelems(b->b_succ) == 0)
#define LAST_BLOCK(b) (b->b_next == (bblock_p) 0)
/* Daisy chain recursion not yet accounted for: */
#define RECURSIVE(p) (Cis_elem(p->p_id,p->p_calling))
/*
#define CALLS_UNKNOWN(p) (p->p_flags1 & (byte) PF_CALUNKNOWN)
*/
#define CALLS_UNKNOWN(p) (FALSE)
apriori(proctab)
proc_p proctab;
{
/* For every procedure, see if we can determine
* from the information provided by the previous
* phases of the optimizer that it cannot or should not
* be expanded in line. This will reduce the length
* of the call list.
*/
register proc_p p;
for (p = proctab; p != (proc_p) 0; p = p->p_next) {
if (!BODY_KNOWN(p) ||
ENVIRON(p) || RECURSIVE(p) ||
PARAMS_UNKNOWN(p) || MANY_LOCALS(p) ||
IS_ENTERED_WITH_GTO(p)) {
UNSUITABLE(p);
#ifdef VERBOSE
if (BODY_KNOWN(p)) {
if (ENVIRON(p)) Senv++;
if (RECURSIVE(p)) Srecursive++;
if (MANY_LOCALS(p)) Slocals++;
}
#endif
}
}
}
STATIC check_labels(p,arglist)
proc_p p;
arg_p arglist;
{
/* Check if any of the arguments contains an instruction
* label; if so, make p unsuitable.
*/
arg_p arg;
for (arg = arglist; arg != (arg_p) 0; arg = arg->a_next) {
if (arg->a_type == ARGINSTRLAB) {
UNSUITABLE(p);
#ifdef VERBOSE
Sinstrlab++;
#endif
break;
}
}
}
STATIC anal_instr(p,b,cf)
proc_p p;
bblock_p b;
FILE *cf;
{
/* Analyze the instructions of block b
* within procedure p.
* See which parameters are used, changed
* or have their address taken. Recognize
* the actual parameter expressions of
* the CAL instructions.
*/
register line_p l;
for (l = b->b_start; l != (line_p) 0; l = l->l_next) {
switch(INSTR(l)) {
case op_cal:
anal_cal(p,l,b,cf);
break;
case op_stl:
case op_inl:
case op_del:
case op_zrl:
formal(p,b,off_set(l),SINGLE,CHANGE);
/* see if the local is a parameter.
* If so, it is a one-word parameter
* that is stored into.
*/
break;
case op_sdl:
formal(p,b,off_set(l),DOUBLE,CHANGE);
break;
case op_lol:
formal(p,b,off_set(l),SINGLE,USE);
break;
case op_ldl:
formal(p,b,off_set(l),DOUBLE,USE);
break;
case op_sil:
case op_lil:
formal(p,b,off_set(l),POINTER,USE);
break;
case op_lal:
formal(p,b,off_set(l),UNKNOWN,ADDRESS);
break;
case ps_rom:
case ps_con:
case ps_bss:
case ps_hol:
check_labels(p,ARG(l));
break;
case op_nop: /* volatile */
UNSUITABLE(p);
break;
}
}
}
anal_proc(p,cf,ccf)
proc_p p;
FILE *cf,*ccf;
{
/* Analyze a procedure; use information
* stored in its basic blocks or in
* its instructions.
*/
register bblock_p b;
bool fallthrough = TRUE;
cchead = (calcnt_p) 0;
for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
if (RETURN_BLOCK(b) && !LAST_BLOCK(b)) {
fallthrough = FALSE;
/* p contains a RET instruction somewhere
* in the middle of its code.
*/
}
anal_instr(p,b,cf); /* analyze instructions */
}
if (fallthrough) {
p->p_flags2 |= PF_FALLTHROUGH;
}
rem_indir_acc(p);
/* don't expand formal that may be accessed indirectly */
p->P_CCADDR = putcc(cchead,ccf);
/* write calcnt info and remember disk address */
remcc(cchead);
}