17bc9cdef7
Most warnings are for functions implicitly returning int. Change most
of these functions to return void. (Traditional K&R C had no void
type, but C89 has it.)
Add prototypes to most function declarations in headers. This is
easy, because ego declares most of its extern functions, and the
comments listed most parameters. There were a few outdated or missing
declarations, and a few .c files that failed to include an .h with the
declarations.
Add prototypes to a few function definitions in .c files. Most
functions still have traditional K&R definitions. Most STATIC
functions still don't have prototypes, because they have no earlier
declaration where I would have added the prototype.
Change some prototypes in util/ego/share/alloc.h. Functions newmap()
and oldmap() handle an array of pointers to something; change the
array's type from `short **` to `void **`. Callers use casts to go
between `void **` and the correct type, like `line_p *`. Function
oldtable() takes a `short *`, not a `short **`; I added the wrong type
in 5bbbaf4
.
Make a few other changes to silence warnings. There are a few places
where clang wants extra parentheses in the code.
Edit util/ego/ra/build.lua to add the missing dependency on ra*.h; I
needed this to prevent crashes from ra.
248 lines
4.5 KiB
C
248 lines
4.5 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".
|
|
*/
|
|
/* C O N S T A N T P R O P A G A T I O N */
|
|
|
|
#include <em_mnem.h>
|
|
#include <em_pseu.h>
|
|
#include <em_spec.h>
|
|
#include "../share/types.h"
|
|
#include "ud.h"
|
|
#include "../share/debug.h"
|
|
#include "../share/global.h"
|
|
#include "../share/alloc.h"
|
|
#include "../share/lset.h"
|
|
#include "../share/cset.h"
|
|
#include "../share/def.h"
|
|
#include "../share/utils.h"
|
|
#include "../share/locals.h"
|
|
#include "ud_defs.h"
|
|
#include "ud_const.h"
|
|
#include "ud_aux.h"
|
|
|
|
|
|
#define IS_REG(v) (locals[TO_LOCAL(v)]->lc_flags & LCF_REG)
|
|
#define CALLS_UNKNOWN(p) (p->p_flags1 & (byte) PF_CALUNKNOWN)
|
|
|
|
|
|
bool is_use(l)
|
|
line_p l;
|
|
{
|
|
/* See if 'l' is a use of a variable */
|
|
|
|
switch(INSTR(l)) {
|
|
case op_lde:
|
|
case op_ldl:
|
|
case op_loe:
|
|
case op_lol:
|
|
return TRUE;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
|
|
|
|
|
|
bool value_known(def,val_out)
|
|
line_p def;
|
|
offset *val_out;
|
|
{
|
|
/* See if the value stored by definition 'def'
|
|
* is known statically (i.e. is a constant).
|
|
*/
|
|
|
|
short sz1, sz2;
|
|
offset v;
|
|
line_p l;
|
|
|
|
sz1 = ws;
|
|
switch(INSTR(def)) {
|
|
case op_inl:
|
|
case op_ine:
|
|
case op_del:
|
|
case op_dee:
|
|
return FALSE;
|
|
case op_zrl:
|
|
case op_zre:
|
|
v = (offset) 0;
|
|
break;
|
|
case op_sdl:
|
|
case op_sde:
|
|
sz1 += ws;
|
|
/* fall through ... */
|
|
case op_stl:
|
|
case op_ste:
|
|
l = PREV(def);
|
|
if (l == (line_p) 0) return FALSE;
|
|
sz2 = ws;
|
|
switch(INSTR(l)) {
|
|
case op_zer:
|
|
if (SHORT(l) >= sz1) {
|
|
v = (offset) 0;
|
|
break;
|
|
}
|
|
return FALSE;
|
|
case op_ldc:
|
|
sz2 += ws;
|
|
/* fall through ...*/
|
|
case op_loc:
|
|
if (sz1 == sz2) {
|
|
v = off_set(l);
|
|
break;
|
|
}
|
|
/* fall through ... */
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
default:
|
|
assert(FALSE);
|
|
}
|
|
*val_out = v;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
bool affected(line_p use, short v, line_p l)
|
|
{
|
|
/* See if the variable referenced by 'use' may be
|
|
* changed by instruction l, which is either a cal, cai or
|
|
* an indirect assignment.
|
|
*/
|
|
|
|
if (INSTR(l) == op_cal &&
|
|
TYPE(use) == OPOBJECT &&
|
|
BODY_KNOWN(PROC(l)) &&
|
|
!CALLS_UNKNOWN(PROC(l)) &&
|
|
!CHANGE_INDIR(PROC(l))) {
|
|
return Cis_elem(OBJ(use)->o_id,PROC(l)->p_change->c_ext);
|
|
}
|
|
return TYPE(use) == OPOBJECT || !IS_REG(v);
|
|
}
|
|
|
|
|
|
|
|
|
|
STATIC void search_backwards(use,v,found,def)
|
|
line_p use, *def;
|
|
short v;
|
|
bool *found;
|
|
{
|
|
/* Search backwards in the current basic block,
|
|
* starting at 'use', trying to find a definition
|
|
* of the variable referenced by 'use', whose variable
|
|
* number is v. If the definition found is an
|
|
* implicit one, return 0 as def.
|
|
*/
|
|
|
|
register line_p l;
|
|
|
|
for (l = PREV(use); l != (line_p) 0; l = PREV(l)) {
|
|
if (does_expl_def(l) && same_var(use,l)) {
|
|
*found = TRUE;
|
|
*def = l;
|
|
return;
|
|
}
|
|
if (does_impl_def(l) && affected(use,v,l)) {
|
|
*found = TRUE;
|
|
*def = (line_p) 0;
|
|
return;
|
|
}
|
|
}
|
|
*found = FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
STATIC short outer_def(vdefs,in)
|
|
cset vdefs, in;
|
|
{
|
|
/* See if there is a unique definition of variable
|
|
* v reaching the beginning of block b.
|
|
* 'vdefs' is vardefs[v], 'in' is IN(b).
|
|
*/
|
|
|
|
short n,defnr = 0;
|
|
Cindex i;
|
|
|
|
for (i = Cfirst(vdefs); i != (Cindex) 0; i = Cnext(i,vdefs)) {
|
|
n = Celem(i);
|
|
if (Cis_elem(EXPL_TO_DEFNR(n),in)) {
|
|
if (defnr != 0) return 0;
|
|
/* If there was already a def., there's no unique one */
|
|
defnr = n;
|
|
}
|
|
}
|
|
return defnr;
|
|
}
|
|
|
|
|
|
|
|
|
|
line_p unique_def(use,b,defnr_out)
|
|
line_p use;
|
|
bblock_p b;
|
|
short *defnr_out;
|
|
{
|
|
/* See if there is one unique explicit definition
|
|
* of the variable used by 'use', that reaches 'use'.
|
|
*/
|
|
|
|
short v;
|
|
bool found;
|
|
line_p def = (line_p) 0;
|
|
|
|
*defnr_out = 0;
|
|
var_nr(use,&v,&found);
|
|
if (found) {
|
|
/* We do maintain ud-info for this variable.
|
|
* See if there is a previous explicit definition
|
|
* in the current basic block.
|
|
*/
|
|
search_backwards(use,v,&found,&def);
|
|
if (!found && !Cis_elem(IMPLICIT_DEF(v),IN(b))) {
|
|
/* See if there is a unique explicit definition
|
|
* outside the current block, reaching the
|
|
* beginning of the current block.
|
|
*/
|
|
*defnr_out = outer_def(vardefs[v],IN(b));
|
|
def = (*defnr_out == 0 ? (line_p) 0 : defs[*defnr_out]);
|
|
}
|
|
}
|
|
return def;
|
|
}
|
|
|
|
|
|
|
|
void fold_const(l,b,val)
|
|
line_p l;
|
|
bblock_p b;
|
|
offset val;
|
|
{
|
|
/* Perform the substitutions required for constant folding */
|
|
|
|
line_p n;
|
|
|
|
n = int_line(val);
|
|
switch(INSTR(l)) {
|
|
case op_lol:
|
|
case op_loe:
|
|
n->l_instr = op_loc;
|
|
break;
|
|
case op_ldl:
|
|
case op_lde:
|
|
n->l_instr = op_ldc;
|
|
break;
|
|
default:
|
|
assert (FALSE);
|
|
}
|
|
repl_line(l,n,b);
|
|
}
|