1994-06-24 11:31:16 +00:00
|
|
|
/* $Id$ */
|
1987-03-09 19:15:41 +00:00
|
|
|
/*
|
|
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
|
|
*/
|
1984-11-26 14:14:55 +00:00
|
|
|
/* 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>
|
1991-03-05 12:44:05 +00:00
|
|
|
#include <em_mnem.h>
|
|
|
|
#include <em_pseu.h>
|
1984-11-26 14:14:55 +00:00
|
|
|
#include "../share/types.h"
|
|
|
|
#include "il.h"
|
|
|
|
#include "../share/debug.h"
|
|
|
|
#include "../share/alloc.h"
|
2019-10-31 22:05:22 +00:00
|
|
|
#include "../share/cset.h"
|
1984-11-26 14:14:55 +00:00
|
|
|
#include "../share/global.h"
|
|
|
|
#include "../share/lset.h"
|
2019-02-08 23:02:41 +00:00
|
|
|
#include "../share/utils.h"
|
1984-11-26 14:14:55 +00:00
|
|
|
#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)
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-31 22:05:22 +00:00
|
|
|
void apriori(proctab)
|
1984-11-26 14:14:55 +00:00
|
|
|
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) ||
|
1987-10-02 12:52:29 +00:00
|
|
|
PARAMS_UNKNOWN(p) || MANY_LOCALS(p) ||
|
|
|
|
IS_ENTERED_WITH_GTO(p)) {
|
1984-11-26 14:14:55 +00:00
|
|
|
UNSUITABLE(p);
|
|
|
|
#ifdef VERBOSE
|
|
|
|
if (BODY_KNOWN(p)) {
|
|
|
|
if (ENVIRON(p)) Senv++;
|
|
|
|
if (RECURSIVE(p)) Srecursive++;
|
|
|
|
if (MANY_LOCALS(p)) Slocals++;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-10-31 22:05:22 +00:00
|
|
|
STATIC void check_labels(p,arglist)
|
1984-11-26 14:14:55 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-31 22:05:22 +00:00
|
|
|
STATIC void anal_instr(p,b,cf)
|
1984-11-26 14:14:55 +00:00
|
|
|
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;
|
1991-10-02 13:03:31 +00:00
|
|
|
case op_nop: /* volatile */
|
|
|
|
UNSUITABLE(p);
|
|
|
|
break;
|
1984-11-26 14:14:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-31 22:05:22 +00:00
|
|
|
void anal_proc(p,cf,ccf)
|
1984-11-26 14:14:55 +00:00
|
|
|
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);
|
|
|
|
}
|