1819 lines
51 KiB
C
1819 lines
51 KiB
C
/*********************************************************************/
|
|
/* pC++/Sage++ Copyright (C) 1993 */
|
|
/* Indiana University University of Oregon University of Rennes */
|
|
/*********************************************************************/
|
|
|
|
|
|
/* File: sets.c */
|
|
#include "db.h"
|
|
|
|
extern PCF UnparseBfnd[];
|
|
extern PCF UnparseLlnd[];
|
|
|
|
extern PTR_FILE cur_file;
|
|
|
|
#define PLUS 2
|
|
#define ZPLUS 3
|
|
#define MINUS 4
|
|
#define ZMINUS 5
|
|
#define PLUSMINUS 6
|
|
#define NODEP -1
|
|
#define FLOWD 1
|
|
#define OUTPUTD 2
|
|
#define ANTID -1
|
|
#define INPUTD 3
|
|
|
|
extern char *tag[611];
|
|
extern struct subscript source[AR_DIM_MAX]; /* a source reference or def. */
|
|
extern struct subscript destin[AR_DIM_MAX]; /* a destination ref. or def. */
|
|
extern PTR_SYMB induct_list[MAX_NEST_DEPTH];
|
|
extern int is_forall[MAX_NEST_DEPTH];
|
|
extern int language; /* is either ForSrc or CSrc */
|
|
extern int num_ll_allocated;
|
|
|
|
extern char *funparse_bfnd();
|
|
extern char *cunparse_bfnd();
|
|
extern char *funparse_llnd();
|
|
extern char *cunparse_llnd();
|
|
extern void collect_garbage();
|
|
extern void normal_form();
|
|
extern void bind_call_site_info();
|
|
extern PTR_LLND make_llnd();
|
|
extern PTR_FILE cur_file;
|
|
extern int show_deps;
|
|
extern void disp_refl();
|
|
int search_decl();
|
|
extern int comp_dist();
|
|
extern int identical();
|
|
extern void assign();
|
|
int node_count = 0;
|
|
|
|
void fix_symbol_list( b)
|
|
PTR_BFND b;
|
|
{
|
|
PTR_BLOB bp;
|
|
PTR_SYMB f, v;
|
|
if(b == NULL || b->variant != GLOBAL) return;
|
|
bp = b->entry.Template.bl_ptr1;
|
|
while(bp){
|
|
if(bp->ref->variant == PROC_HEDR ||
|
|
bp->ref->variant == FUNC_HEDR){
|
|
f = bp->ref->entry.Template.symbol;
|
|
if(f->entry.proc_decl.symb_list == NULL){
|
|
v = f->thread;
|
|
while(v){
|
|
if(v->scope == bp->ref){
|
|
f->entry.proc_decl.symb_list = v;
|
|
v = NULL;
|
|
}
|
|
else{
|
|
v = v->thread;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
bp=bp->next;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************/
|
|
/* The following external functions found in setutils.c and */
|
|
/* anal_index.c. and symb_alg.c */
|
|
/*******************************************************************/
|
|
|
|
void *malloc();
|
|
PTR_SETS alloc_sets();
|
|
PTR_REFL alloc_ref();
|
|
PTR_REFL copy_refl();
|
|
PTR_REFL union_refl();
|
|
PTR_REFL intersect_refl();
|
|
PTR_REFL make_name_list();
|
|
PTR_REFL remove_locals_from_list();
|
|
PTR_REFL build_refl(), merge_array_refs();
|
|
void print_subscr();
|
|
void append_refl();
|
|
void normal_form();
|
|
void bind_call_site_info();
|
|
|
|
/* Gather_ref is a function that makes a reference node and a list */
|
|
/* for each reference to a varialbe at the tree rooted at the low */
|
|
/* level node ll. the parameter defs is used by C programs. in */
|
|
/* this case defs points to a list of definitions that are generated*/
|
|
/* durring the evaluation of this expression. */
|
|
|
|
PTR_REFL gather_refl(rnd, defs, bif, ll)
|
|
int rnd; /* flag = 1 to gather refs for func. calls */
|
|
PTR_REFL *defs; /* for C expressions that define values */
|
|
PTR_BFND bif;
|
|
PTR_LLND ll;
|
|
{
|
|
PTR_REFL p, q, t;
|
|
PTR_REFL r;
|
|
PTR_LLND a;
|
|
|
|
if (ll == NULL)
|
|
return (NULL);
|
|
|
|
if (bif->variant == PROC_STAT && rnd) {
|
|
PTR_LLND bused, bmodified;
|
|
PTR_REFL brlu, brlm;
|
|
/* assume global analysis done. */
|
|
bind_call_site_info(bif, &bused, &bmodified);
|
|
brlu = build_refl(bif, bused);
|
|
brlu = merge_array_refs(brlu);
|
|
brlu = merge_array_refs(brlu); /* one more pass */
|
|
brlm = build_refl(bif, bmodified);
|
|
brlm = merge_array_refs(brlm);
|
|
brlm = merge_array_refs(brlm); /* one more pass */
|
|
append_refl(defs, brlm);
|
|
return (brlu);
|
|
}
|
|
|
|
if (ll->variant == VAR_REF)
|
|
return (alloc_ref(bif, ll));
|
|
else if ((ll->variant == PROC_CALL) || (ll->variant == FUNC_CALL))
|
|
if (rnd) {
|
|
PTR_LLND bused, bmodified;
|
|
PTR_REFL brlu, brlm;
|
|
/* assume global analysis done. */
|
|
bind_call_site_info(bif, &bused, &bmodified);
|
|
brlu = build_refl(bif, bused);
|
|
brlu = merge_array_refs(brlu);
|
|
brlu = merge_array_refs(brlu); /* one more pass */
|
|
brlm = build_refl(bif, bmodified);
|
|
brlm = merge_array_refs(brlm);
|
|
brlm = merge_array_refs(brlm); /* one more pass */
|
|
append_refl(defs, brlm);
|
|
return (brlu);
|
|
}
|
|
else
|
|
return (NULL);
|
|
else if (ll->variant == ARRAY_REF) {
|
|
r = alloc_ref(bif, ll);
|
|
p = gather_refl(rnd, defs, bif, ll->entry.Template.ll_ptr1);
|
|
if (rnd == 0 && bif->variant == PROC_STAT)
|
|
t = p;
|
|
else {
|
|
t = union_refl(r, p);
|
|
disp_refl(p);
|
|
}
|
|
return (t);
|
|
}
|
|
else if (ll->variant == DEREF_OP) {
|
|
p = gather_refl(rnd, defs, bif, ll->entry.Template.ll_ptr1);
|
|
return (p);
|
|
}
|
|
else if (ll->variant == ADDRESS_OP) {
|
|
p = gather_refl(rnd, defs, bif, ll->entry.Template.ll_ptr1);
|
|
return (p);
|
|
}
|
|
else if (ll->variant == POINTST_OP || ll->variant == RECORD_REF) {
|
|
/* a->b type operation. in this case we have a */
|
|
/* reference to a substructure of a struct. */
|
|
r = alloc_ref(bif, ll);
|
|
r->id = NULL;
|
|
return (r);
|
|
}
|
|
else if (ll->variant == PLUSPLUS_OP || ll->variant == MINUSMINUS_OP) {
|
|
p = gather_refl(rnd, defs, bif, ll->entry.Template.ll_ptr1);
|
|
q = gather_refl(rnd, defs, bif, ll->entry.Template.ll_ptr1);
|
|
/* better check for predecriment too! */
|
|
append_refl(defs, q);
|
|
disp_refl(q);
|
|
return (p);
|
|
}
|
|
else if (ll->variant == ASSGN_OP || ll->variant == ARITH_ASSGN_OP) {
|
|
if (ll->entry.Template.ll_ptr2->variant == DEREF_OP) {
|
|
/* create an equivalence pair for later use */
|
|
/* i don't know what to return */
|
|
return (NULL);
|
|
}
|
|
else {
|
|
p = gather_refl(rnd, defs, bif, ll->entry.Template.ll_ptr2);
|
|
a = ll->entry.Template.ll_ptr1;
|
|
if (a->variant == VAR_REF || a->variant == POINTST_OP
|
|
|| a->variant == RECORD_REF) {
|
|
r = alloc_ref(bif, a);
|
|
append_refl(defs, r);
|
|
if (ll->variant == ARITH_ASSGN_OP) {
|
|
r = alloc_ref(bif, a);
|
|
append_refl(&p, r);
|
|
}
|
|
return (p);
|
|
}
|
|
else if (a->variant == ARRAY_REF) {
|
|
r = alloc_ref(bif, a);
|
|
append_refl(defs, r);
|
|
q = gather_refl(rnd, defs, bif, a->entry.Template.ll_ptr1);
|
|
t = union_refl(p, q);
|
|
disp_refl(p);
|
|
disp_refl(q);
|
|
if (ll->variant == ARITH_ASSGN_OP) {
|
|
r = alloc_ref(bif, a);
|
|
append_refl(&t, r);
|
|
}
|
|
return (t);
|
|
}
|
|
else if (a->variant == DEREF_OP) {
|
|
/* not so sure about this! */
|
|
q = gather_refl(rnd, defs, bif, a->entry.Template.ll_ptr1);
|
|
if (ll->variant == ARITH_ASSGN_OP) {
|
|
r = alloc_ref(bif, a);
|
|
append_refl(&q, r);
|
|
}
|
|
return (q);
|
|
}
|
|
else {
|
|
q = gather_refl(rnd, defs, bif, ll->entry.Template.ll_ptr1);
|
|
append_refl(defs, q);
|
|
disp_refl(q);
|
|
if (ll->variant == ARITH_ASSGN_OP) {
|
|
r = alloc_ref(bif, a);
|
|
append_refl(&p, r);
|
|
}
|
|
return (p);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
p = gather_refl(rnd, defs, bif, ll->entry.Template.ll_ptr1);
|
|
q = gather_refl(rnd, defs, bif, ll->entry.Template.ll_ptr2);
|
|
t = union_refl(p, q);
|
|
disp_refl(p);
|
|
disp_refl(q);
|
|
return (t);
|
|
}
|
|
}
|
|
|
|
static int before(bsor, bdes)
|
|
PTR_BFND bsor, bdes;
|
|
{
|
|
return (bsor->id < bdes->id);
|
|
}
|
|
|
|
|
|
PTR_REFL rem_kill(in, gen)
|
|
PTR_REFL in, gen;
|
|
{
|
|
/* search "in" for things in "in" that are killed by gen. */
|
|
/* for scalars this means we just look at the ID. */
|
|
/* for arrays we have to check for an induction variable expression */
|
|
/* that is constant in the current iteration. */
|
|
PTR_REFL t, g, rk, tmp;
|
|
|
|
t = copy_refl(in);
|
|
for (g = gen; g; g = g->next)
|
|
for (tmp = t; tmp; tmp = tmp->next)
|
|
if (tmp->id == g->id) {
|
|
if ((tmp->node && (tmp->node->refer->variant == POINTST_OP ||
|
|
tmp->node->refer->variant == RECORD_REF)) ||
|
|
(g->node && (g->node->refer->variant == POINTST_OP ||
|
|
g->node->refer->variant == RECORD_REF))
|
|
) {
|
|
/* don't know what to do! */
|
|
}
|
|
/* have a hit here. */
|
|
else if (tmp->node->refer->variant == VAR_REF) {
|
|
tmp->id = NULL;
|
|
tmp->node = NULL;
|
|
/* just killed a scalar */
|
|
}
|
|
else {
|
|
/* it is an ARRAY_REF so we need much work */
|
|
/* the key is to kill definitions to the same subscripted */
|
|
/* variables that are defined in the same iteration */
|
|
/* and are lexically before the current definition. */
|
|
/* But you must then do subscript analysis. the code */
|
|
/* below gives the idea. funct. match_subs not yet done */
|
|
/* it does not hurt to leave this out. the extra dep. */
|
|
/* that are generated are not harmfull. */
|
|
/* for now we only kill off unsubscripted array refs */
|
|
/* because they are redefinitions of the whole array */
|
|
if (tmp->node->refer->variant == ARRAY_REF)
|
|
if (g->node->refer->entry.array_ref.index == NULL) {
|
|
tmp->id = NULL;
|
|
tmp->node = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* now prune out all killed nodes from t */
|
|
rk = NULL;
|
|
while (t) {
|
|
tmp = t;
|
|
t = t->next;
|
|
tmp->next = NULL;
|
|
if (tmp->node == NULL)
|
|
disp_refl(tmp);
|
|
else {
|
|
tmp->next = rk;
|
|
rk = tmp;
|
|
}
|
|
}
|
|
return (rk);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* the rountines search_local and remove_local are used to surpress carried *
|
|
* deps for forall loops. search the reference list looking for references *
|
|
* to locals *
|
|
****************************************************************************/
|
|
int search_local(b, s)
|
|
PTR_BFND b;
|
|
PTR_SYMB s;
|
|
{
|
|
PTR_SYMB locs;
|
|
PTR_BLOB blob;
|
|
|
|
if (b->variant == FORALL_NODE) {
|
|
locs = b->entry.forall_nd.control_var;
|
|
while (locs != NULL && s != locs)
|
|
locs = locs->next_symb;
|
|
if (locs == s)
|
|
return (0);
|
|
else
|
|
return (1);
|
|
}
|
|
else if (language != ForSrc) {
|
|
blob = b->entry.Template.bl_ptr1;
|
|
return (search_decl(blob, s));
|
|
}
|
|
else
|
|
return (1);
|
|
}
|
|
|
|
int search_decl(blob, s)
|
|
PTR_BLOB blob;
|
|
PTR_SYMB s;
|
|
{
|
|
PTR_BFND b;
|
|
PTR_LLND ll, v;
|
|
|
|
while (blob != NULL && blob->ref->variant != CONTROL_END) {
|
|
b = blob->ref;
|
|
if (b->variant == VAR_DECL) {
|
|
ll = b->entry.Template.ll_ptr1;
|
|
/* ll should be an expression list */
|
|
while (ll != NULL) {
|
|
if (ll->entry.Template.ll_ptr1 != NULL) {
|
|
v = ll->entry.Template.ll_ptr1;
|
|
if ((v->variant == VAR_REF ||
|
|
v->variant == ARRAY_REF) &&
|
|
v->entry.Template.symbol == s)
|
|
return (0);
|
|
}
|
|
ll = ll->entry.Template.ll_ptr2;
|
|
}
|
|
}
|
|
blob = blob->next;
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
|
|
PTR_REFL remove_locals(b, in)
|
|
PTR_BFND b;
|
|
PTR_REFL in;
|
|
{
|
|
PTR_SYMB i;
|
|
PTR_REFL t, rk, tmp;
|
|
PTR_BFND loop;
|
|
int notfound;
|
|
|
|
/* prune out all killed nodes from t */
|
|
rk = NULL;
|
|
t = in;
|
|
while (t != NULL) {
|
|
tmp = t;
|
|
t = t->next;
|
|
i = tmp->id;
|
|
tmp->next = NULL;
|
|
loop = b;
|
|
notfound = 1;
|
|
while (loop != NULL &&
|
|
(loop->variant != FOR_NODE &&
|
|
loop->variant != WHILE_NODE &&
|
|
loop->variant != LOOP_NODE &&
|
|
loop->variant != CDOALL_NODE &&
|
|
loop->variant != PARFOR_NODE &&
|
|
loop->variant != IF_NODE &&
|
|
loop->variant != LOGIF_NODE &&
|
|
loop->variant != PAR_NODE)) {
|
|
loop = loop->control_parent;
|
|
}
|
|
if (loop != NULL)
|
|
notfound = search_local(loop, i);
|
|
if (notfound == 0)
|
|
disp_refl(tmp);
|
|
else {
|
|
tmp->next = rk;
|
|
rk = tmp;
|
|
}
|
|
}
|
|
return (rk);
|
|
}
|
|
|
|
int is_star_range(p)
|
|
PTR_LLND p;
|
|
{
|
|
PTR_LLND q, q2;
|
|
|
|
if (p->entry.Template.ll_ptr1 == NULL)
|
|
return (1);
|
|
q = p->entry.Template.ll_ptr1;/* q should be an index list */
|
|
q2 = q->entry.Template.ll_ptr1; /* q2 is the first index */
|
|
if ((q2 == NULL || q2->variant == STAR_RANGE)
|
|
&& q->entry.Template.ll_ptr2 == NULL) {
|
|
return (1);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
PTR_REFL remove_scalar_dups(s)
|
|
PTR_REFL s;
|
|
{
|
|
PTR_SYMB i;
|
|
PTR_REFL t, arr_no_subs, arr_with_subs, final, loop, tmp, point_exps;
|
|
PTR_LLND p;
|
|
int notfound;
|
|
|
|
/* prune out all killed nodes from t */
|
|
final = NULL;
|
|
arr_no_subs = NULL;
|
|
arr_with_subs = NULL;
|
|
point_exps = NULL;
|
|
t = s;
|
|
while (t != NULL) {
|
|
tmp = t;
|
|
t = t->next;
|
|
p = tmp->node->refer;
|
|
i = p->entry.Template.symbol;
|
|
tmp->next = NULL;
|
|
if (p->variant == VAR_REF ||
|
|
(p->variant == ARRAY_REF && is_star_range(p))) {
|
|
if (p->variant == ARRAY_REF) {
|
|
loop = arr_no_subs;
|
|
notfound = 1;
|
|
while (loop != NULL) {
|
|
if (loop->node->refer->entry.Template.symbol == i) {
|
|
notfound = 0;
|
|
}
|
|
loop = loop->next;
|
|
}
|
|
if (notfound) {
|
|
tmp->next = arr_no_subs;
|
|
arr_no_subs = tmp;
|
|
}
|
|
}
|
|
else {
|
|
loop = final;
|
|
notfound = 1;
|
|
while (loop != NULL) {
|
|
if (loop->node->refer->entry.Template.symbol == i)
|
|
notfound = 0;
|
|
loop = loop->next;
|
|
}
|
|
if (notfound) {
|
|
tmp->next = final;
|
|
final = tmp;
|
|
}
|
|
}
|
|
}
|
|
else if (tmp->node->refer->variant == ARRAY_REF) {
|
|
tmp->next = arr_with_subs;
|
|
arr_with_subs = tmp;
|
|
}
|
|
else
|
|
if(tmp->node->refer->variant==POINTST_OP
|
|
|| tmp->node->refer->variant == RECORD_REF) {
|
|
tmp->next = point_exps;
|
|
point_exps = tmp;
|
|
}
|
|
} /* end while */
|
|
t = arr_with_subs;
|
|
while (t != NULL) {
|
|
tmp = t;
|
|
t = t->next;
|
|
i = tmp->node->refer->entry.Template.symbol;
|
|
tmp->next = NULL;
|
|
notfound = 1;
|
|
loop = arr_no_subs;
|
|
while (loop != NULL) {
|
|
if (loop->node->refer->entry.Template.symbol == i)
|
|
notfound = 0;
|
|
loop = loop->next;
|
|
}
|
|
if (notfound) {
|
|
tmp->next = final;
|
|
final = tmp;
|
|
}
|
|
}
|
|
t = arr_no_subs;
|
|
while (t != NULL) {
|
|
tmp = t;
|
|
t = t->next;
|
|
tmp->next = final;
|
|
final = tmp;
|
|
}
|
|
t = point_exps;
|
|
while (t != NULL) {
|
|
tmp = t;
|
|
t = t->next;
|
|
tmp->next = final;
|
|
final = tmp;
|
|
}
|
|
return (final);
|
|
}
|
|
|
|
|
|
/***********************************************************************/
|
|
/* */
|
|
/* dependence manipulation routines rm_dep() and append_dep() */
|
|
/* taken from lists.c in bled. should be deleted from that file */
|
|
/* */
|
|
/***********************************************************************/
|
|
void rm_dep(b, d) /* remove dep d from the list out of b */
|
|
PTR_BFND b;
|
|
PTR_DEP d;
|
|
{
|
|
PTR_DEP s, olds = NULL;
|
|
|
|
s = b->entry.Template.dep_ptr1;
|
|
if (s == d) {
|
|
b->entry.Template.dep_ptr1 = d->from_fwd;
|
|
d->from_fwd = NULL;
|
|
}
|
|
else {
|
|
while ((s != NULL) && (s != d)) {
|
|
olds = s;
|
|
s = s->from_fwd;
|
|
}
|
|
if (s) {
|
|
olds->from_fwd = s->from_fwd;
|
|
d->from_fwd = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int check_dep_copy(b, t, s, bf, lf, bt, lt)
|
|
PTR_BFND b, bf, bt;
|
|
PTR_SYMB s;
|
|
int t;
|
|
PTR_LLND lf, lt;
|
|
{
|
|
PTR_DEP lst;
|
|
lst = b->entry.Template.dep_ptr1;
|
|
while(lst){
|
|
if(lst->type == t && lst->symbol == s &&
|
|
lst->from.stmt == bf && lst->from.refer == lf &&
|
|
lst->to.stmt == bt && lst->to.refer == lt)
|
|
return 0;
|
|
lst = lst->from_fwd;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void append_dep(b, d) /* add the dep d to the list from b */
|
|
PTR_BFND b;
|
|
PTR_DEP d;
|
|
{
|
|
PTR_BFND t;
|
|
|
|
d->from_fwd = b->entry.Template.dep_ptr1;
|
|
b->entry.Template.dep_ptr1 = d;
|
|
t = d->to.stmt;
|
|
d->to_fwd = t->entry.Template.dep_ptr2;
|
|
t->entry.Template.dep_ptr2 = d;
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************/
|
|
/* make deps is the key routine that checks two references to */
|
|
/* see if they are in fact a dependence. if so a new dep is */
|
|
/* created and linked into the structure */
|
|
/**************************************************************/
|
|
void make_deps(type, def, use)
|
|
PTR_REFL def, use;
|
|
int type;
|
|
{
|
|
PTR_REFL g; /* temporary reference list */
|
|
PTR_SYMB s; /* symbol for varialble name */
|
|
PTR_SYMB ivar; /* an induction variable name */
|
|
int i, j, befr, notrub, type1;
|
|
int vect[MAX_NEST_DEPTH], troub[MAX_NEST_DEPTH];
|
|
|
|
PTR_DEP dptr; /* pointer to dependence inserted */
|
|
PTR_DEP make_dep(); /* functions from list.c */
|
|
char t; /* type: 0=flow 1=anti 2 = output */
|
|
PTR_LLND lls, lld; /* term source and destination */
|
|
PTR_BFND bns, bnd; /* biff nd source and destination */
|
|
char dv[MAX_NEST_DEPTH]; /* dep. vector: 1="=" 2="<" 4=">" ? */
|
|
while (def != NULL) {
|
|
s = def->id;
|
|
g = use;
|
|
if ((s != NULL) && (s->type != NULL) &&
|
|
((type != INPUTD) || (s->type->variant == T_ARRAY)))
|
|
while (g != NULL) {
|
|
if (g->id == s) {
|
|
/* compute the distance vector and trouble vector */
|
|
|
|
befr = before(def->node->stmt, g->node->stmt);
|
|
comp_dist(vect, troub, def->node, g->node, befr);
|
|
|
|
/* first zero out all vector components */
|
|
/* outside the scope of the variable */
|
|
|
|
/* this is to fix the problem with */
|
|
/* nested foralls. */
|
|
s = def->id;
|
|
notrub = 1;
|
|
for (i = vect[0]; i >= 1; i--) {
|
|
if (is_forall[i - 1]) {
|
|
ivar = induct_list[i - 1];
|
|
while (ivar != NULL && ivar != s)
|
|
ivar = ivar->next_symb;
|
|
if (ivar == s) { /* found local */
|
|
notrub = 0;
|
|
}
|
|
}
|
|
if (notrub == 0) {
|
|
vect[i] = 0;
|
|
troub[i] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
if (troub[0] == 1) {
|
|
/* no dependence here */
|
|
}
|
|
else {
|
|
/* dependence exists, so generate the record and information */
|
|
bns = def->node->stmt;
|
|
lls = def->node->refer;
|
|
bnd = g->node->stmt;
|
|
lld = g->node->refer;
|
|
type1 = type;
|
|
if(bns == bnd && (lls != lld) && identical(lls, lld)){
|
|
/* this is an accumulation recurrence if lls and lld are */
|
|
/* identical. They should be compared. if they are the */
|
|
/* same, create an accumulation dep ACCD. Check this */
|
|
/* for flow and avoid generating the output and anti deps*/
|
|
if (type1 == FLOWD) type1 = 5;
|
|
else type1 = 6;
|
|
}
|
|
/* convert to standard bif constants */
|
|
switch (type1) {
|
|
case 5: /* ACCD: */
|
|
t = 3;
|
|
break;
|
|
case FLOWD:
|
|
if (show_deps)
|
|
fprintf(stderr, "flow dependence on var:`%s' -", s->ident);
|
|
t = 0;
|
|
break;
|
|
case OUTPUTD:
|
|
case -OUTPUTD:
|
|
if (show_deps)
|
|
fprintf(stderr, " output dependence on var:`%s' -", s->ident);
|
|
t = 2;
|
|
break;
|
|
case ANTID:
|
|
if (show_deps)
|
|
fprintf(stderr, "anti dependence on var:`%s' -", s->ident);
|
|
t = 1;
|
|
break;
|
|
case INPUTD:
|
|
t = 4;
|
|
break;
|
|
default:
|
|
if (show_deps)
|
|
fprintf(stderr, " bad type -");
|
|
t = 5;
|
|
}
|
|
if(t == 5) break;
|
|
if (show_deps &&(t != 4))
|
|
fprintf(stderr, "((level=%d)", vect[0]);
|
|
for (j = 0; j < MAX_NEST_DEPTH; j++)
|
|
dv[j] = 0;
|
|
for (j = 1; j <= vect[0]; j++)
|
|
switch (troub[j]) {
|
|
case NODEP:
|
|
case -99:
|
|
case 0:
|
|
if (show_deps)
|
|
if (t != 4)
|
|
fprintf(stderr, ", %d ", vect[j]);
|
|
if (vect[j] > 0)
|
|
dv[j] = 4;
|
|
else if (vect[j] == 0)
|
|
dv[j] = 1;
|
|
else
|
|
dv[j] = 2;
|
|
break;
|
|
case PLUS:
|
|
if (show_deps)
|
|
if (t != 4)
|
|
fprintf(stderr, ", +");
|
|
dv[j] = 4;
|
|
break;
|
|
case ZPLUS:
|
|
if (show_deps)
|
|
if (t != 4)
|
|
fprintf(stderr, ", 0/+");
|
|
dv[j] = 5;
|
|
break;
|
|
case MINUS:
|
|
if (show_deps)
|
|
if (t != 4)
|
|
fprintf(stderr, ", -");
|
|
dv[j] = 2;
|
|
break;
|
|
case ZMINUS:
|
|
if (show_deps)
|
|
if (t != 4)
|
|
fprintf(stderr, ", 0/-");
|
|
dv[j] = 3;
|
|
break;
|
|
case PLUSMINUS:
|
|
if (show_deps)
|
|
if (t != 4)
|
|
fprintf(stderr, ", +/-");
|
|
dv[j] = 7;
|
|
break;
|
|
default:
|
|
if (show_deps)
|
|
if (t != 4)
|
|
fprintf(stderr, ", ??%d ", troub[j]);
|
|
dv[j] = 8;
|
|
}
|
|
if (show_deps && (t != 4))
|
|
fprintf(stderr, ")\n");
|
|
for (j = 1; j <= vect[0]; j++) {
|
|
if (is_forall[j - 1] && (t != 4)) {
|
|
if (troub[j] == 0 || troub[j] == NODEP
|
|
|| troub[j] == -99) {
|
|
if (vect[j] != 0)
|
|
fprintf(stderr, "WARNING!! may be potential concurrency conflict\n");
|
|
}
|
|
else
|
|
fprintf(stderr, "WARNING!! May be potential Concurrency conflict\n");
|
|
}
|
|
}
|
|
|
|
|
|
/* now make the dependences... */
|
|
/* only generate uniformly generated input deps. */
|
|
/* Temp for cftn. disable input deps */
|
|
/* disabled: note unif_gen has more arguments */
|
|
if (t != 4 && t != 5 &&
|
|
check_dep_copy(bns,t,s,bns,lls,bnd,lld)){
|
|
dptr = make_dep(cur_file, s, t, lls, lld, bns, bnd, dv);
|
|
append_dep(bns, dptr);
|
|
}
|
|
|
|
/* note: only appends to from list */
|
|
/* if you want more fix append_dep */
|
|
}
|
|
}
|
|
else {
|
|
/* symbols do not agree */
|
|
}
|
|
g = g->next;
|
|
}
|
|
def = def->next;
|
|
}
|
|
}
|
|
/***************************************************************/
|
|
/* link_set_list() builds a expr list of low level expressions */
|
|
/* that describe the use of variable in the list. it will list*/
|
|
/* each scalar only once and for each array reference it will */
|
|
/* build an expression that describes the use of the variable */
|
|
/* using ddot form. lots of common subexpressions are used. */
|
|
/* find_bounds() is found in anal_ind.c */
|
|
/***************************************************************/
|
|
|
|
PTR_LLND link_set_list(s)
|
|
PTR_REFL s;
|
|
{
|
|
PTR_LLND p, q, newq, make_llnd(), find_bounds();
|
|
PTR_BFND b;
|
|
PTR_REFL remove_scalar_dups();
|
|
PTR_LLND remove_array_dups(), merge_ll_array_list();
|
|
|
|
s = remove_scalar_dups(s);
|
|
p = NULL;
|
|
while (s != NULL) {
|
|
switch (s->node->refer->variant) {
|
|
case VAR_REF:
|
|
case POINTST_OP:
|
|
case RECORD_REF:
|
|
p = make_llnd(cur_file, EXPR_LIST, s->node->refer, p, NULL);
|
|
break;
|
|
case ARRAY_REF:
|
|
q = s->node->refer;
|
|
b = s->node->stmt;
|
|
newq = make_llnd(cur_file, ARRAY_REF,NULL,NULL,q->entry.Template.symbol);
|
|
newq = find_bounds(b, q, newq);
|
|
/* now put q into normal form */
|
|
normal_form(&(newq->entry.Template.ll_ptr1));
|
|
q = newq->entry.Template.ll_ptr1;
|
|
/* now link into expr list chain p */
|
|
p = make_llnd(cur_file, EXPR_LIST, newq, p, NULL);
|
|
break;
|
|
default:
|
|
fprintf(stderr, "something wrong here ");
|
|
break;
|
|
}
|
|
s = s->next;
|
|
}
|
|
return (merge_ll_array_list(merge_ll_array_list(p))); /* two passes */
|
|
}
|
|
|
|
PTR_LLND remove_array_dups(elist)
|
|
PTR_LLND elist;
|
|
{
|
|
PTR_LLND star_range_list;
|
|
PTR_LLND tmp_list;
|
|
PTR_LLND final_list, cons, item, p, q;
|
|
PTR_SYMB var;
|
|
int not_found;
|
|
|
|
/* first pull off all star range arrays from elist and put them */
|
|
/* on the star_range_list. Others go to tmp_list. Then tmp_list */
|
|
/* compared to star_range list. If not there it is added to final */
|
|
/* list and star_range_list is appended to tmp_list. */
|
|
star_range_list = NULL;
|
|
tmp_list = NULL;
|
|
final_list = NULL;
|
|
while (elist != NULL) {
|
|
cons = elist;
|
|
elist = elist->entry.Template.ll_ptr2;
|
|
cons->entry.Template.ll_ptr2 = NULL;
|
|
item = cons->entry.Template.ll_ptr1;
|
|
var = item->entry.Template.symbol;
|
|
p = star_range_list;
|
|
q = tmp_list;
|
|
if (item->variant == ARRAY_REF && is_star_range(item)) {
|
|
not_found = 1;
|
|
while (p != NULL) {
|
|
if (var == p->entry.Template.ll_ptr1->entry.Template.symbol) {
|
|
not_found = 0;
|
|
break;
|
|
}
|
|
p = p->entry.Template.ll_ptr2;
|
|
}
|
|
if (not_found) {
|
|
cons->entry.Template.ll_ptr2 = star_range_list;
|
|
star_range_list = cons;
|
|
}
|
|
}
|
|
else {
|
|
not_found = 1;
|
|
while (q != NULL) {
|
|
if (identical(q->entry.Template.ll_ptr1, item)) {
|
|
not_found = 0;
|
|
break;
|
|
}
|
|
q = q->entry.Template.ll_ptr2;
|
|
}
|
|
if (not_found) {
|
|
cons->entry.Template.ll_ptr2 = tmp_list;
|
|
tmp_list = cons;
|
|
}
|
|
}
|
|
}
|
|
while (tmp_list != NULL) {
|
|
cons = tmp_list;
|
|
tmp_list = tmp_list->entry.Template.ll_ptr2;
|
|
cons->entry.Template.ll_ptr2 = NULL;
|
|
item = cons->entry.Template.ll_ptr1;
|
|
var = item->entry.Template.symbol;
|
|
p = star_range_list;
|
|
if (item->variant == ARRAY_REF) {
|
|
not_found = 1;
|
|
while (p != NULL) {
|
|
if (var == p->entry.Template.ll_ptr1->entry.Template.symbol) {
|
|
not_found = 0;
|
|
break;
|
|
}
|
|
p = p->entry.Template.ll_ptr2;
|
|
}
|
|
if (not_found) {
|
|
cons->entry.Template.ll_ptr2 = final_list;
|
|
final_list = cons;
|
|
}
|
|
}
|
|
else {
|
|
cons->entry.Template.ll_ptr2 = final_list;
|
|
final_list = cons;
|
|
}
|
|
}
|
|
q = final_list;
|
|
while (q != NULL && q->entry.Template.ll_ptr2 != NULL)
|
|
q = q->entry.Template.ll_ptr2;
|
|
if (q == NULL)
|
|
final_list = star_range_list;
|
|
else
|
|
q->entry.Template.ll_ptr2 = star_range_list;
|
|
return (final_list);
|
|
}
|
|
/* buid_recur_expr will try to reduce simple recurrences like */
|
|
/* i = i+1 in loop into expressions involving an induction var*/
|
|
PTR_LLND build_recur_expr(stmt, s,lls, lld)
|
|
PTR_BFND stmt;
|
|
PTR_SYMB s;
|
|
PTR_LLND lls,lld;
|
|
{
|
|
PTR_BFND parent;
|
|
PTR_LLND init_val, index_ref, rhs, new_expr, coef, lb, one;
|
|
PTR_LLND copy_llnd();
|
|
|
|
parent = stmt->control_parent;
|
|
if(parent->variant == FOR_NODE || parent->variant == CDOALL_NODE){
|
|
if(stmt->variant == ASSIGN_STAT){
|
|
init_val = lld->entry.Template.ll_ptr1;
|
|
lb = copy_llnd(parent->entry.Template.ll_ptr1->entry.Template.ll_ptr1);
|
|
index_ref = make_llnd(cur_file,VAR_REF,NULL,NULL,
|
|
parent->entry.Template.symbol);
|
|
one = make_llnd(cur_file,INT_VAL,NULL,NULL,NULL);
|
|
one->entry.ival = 0;
|
|
lb = make_llnd(cur_file,SUBT_OP,one,lb,NULL);
|
|
index_ref = make_llnd(cur_file,ADD_OP,index_ref,lb,NULL);
|
|
rhs = stmt->entry.Template.ll_ptr2;
|
|
/*
|
|
printf("index:%s init_val:%s rhs:%s",
|
|
(UnparseLlnd[cur_file->lang])(index_ref),
|
|
(UnparseLlnd[cur_file->lang])(init_val),
|
|
(UnparseLlnd[cur_file->lang])(rhs));
|
|
*/
|
|
if(rhs->variant == ADD_OP){
|
|
if(rhs->entry.Template.ll_ptr1 == lld)
|
|
coef = rhs->entry.Template.ll_ptr2;
|
|
else if(rhs->entry.Template.ll_ptr2 == lld)
|
|
coef = rhs->entry.Template.ll_ptr1;
|
|
else return NULL;
|
|
new_expr = make_llnd(cur_file,MULT_OP,
|
|
copy_llnd(coef),index_ref,NULL);
|
|
new_expr = make_llnd(cur_file,ADD_OP,new_expr,init_val,NULL);
|
|
/*printf("new expr:%s",(UnparseLlnd[cur_file->lang])(new_expr));*/
|
|
return new_expr;
|
|
}
|
|
else if(rhs->variant == SUBT_OP){
|
|
if(rhs->entry.Template.ll_ptr1 == lld)
|
|
coef = rhs->entry.Template.ll_ptr2;
|
|
else return NULL;
|
|
if(coef == NULL) return NULL;
|
|
new_expr = make_llnd(cur_file,MULT_OP,
|
|
copy_llnd(coef),index_ref,NULL);
|
|
new_expr = make_llnd(cur_file,SUBT_OP,init_val,new_expr,NULL);
|
|
/*printf("new expr:%s",(UnparseLlnd[cur_file->lang])(new_expr));*/
|
|
return new_expr;
|
|
}
|
|
else return NULL;
|
|
}
|
|
else return NULL;
|
|
}
|
|
else return NULL;
|
|
}
|
|
/* propogate will do the scalar propogation. (test version). */
|
|
void propogate(def, use)
|
|
PTR_REFL def, use;
|
|
{
|
|
PTR_REFL g; /* temporary reference list */
|
|
PTR_SYMB s; /* symbol for varialble name */
|
|
PTR_LLND lls, lld; /* term source and destination */
|
|
PTR_BFND bns; /* biff nd source and destination */
|
|
PTR_LLND p;
|
|
|
|
/* search through each of the definitions */
|
|
while (def != NULL) {
|
|
s = def->id; /* s is the symbol table entry */
|
|
g = use;
|
|
if ((s != NULL) && (s->type != NULL) &&
|
|
(s->type->variant == T_INT))
|
|
while (g != NULL) {
|
|
if (g->id == s) {
|
|
lld = g->node->refer;
|
|
if (def->node->stmt == g->node->stmt) {
|
|
/* definition is reaching itself where it is used */
|
|
/* printf("recurrence\n"); */
|
|
lld = g->node->refer;
|
|
lls = def->node->refer;
|
|
if(lld->entry.Template.ll_ptr1 != NULL)
|
|
lld->entry.Template.ll_ptr1 = build_recur_expr(g->node->stmt,s,lls,lld);
|
|
else lld->entry.Template.ll_ptr1 = NULL;
|
|
}
|
|
else{
|
|
/* a definition is reaching a different use */
|
|
bns = def->node->stmt;
|
|
lld = g->node->refer;
|
|
lls = def->node->refer;
|
|
if (bns->variant == FOR_NODE) {
|
|
lld->entry.Template.ll_ptr1 = NULL;
|
|
}
|
|
else if (bns->variant != EXPR_STMT_NODE) {
|
|
/* a Fortran assignment, p <- rhs of source */
|
|
p = bns->entry.Template.ll_ptr2;
|
|
if (lld->entry.Template.ll_ptr1 == NULL)
|
|
lld->entry.Template.ll_ptr1 = p;
|
|
else if (lld->entry.Template.ll_ptr1 != p)
|
|
lld->entry.Template.ll_ptr1 = NULL;
|
|
}
|
|
else {
|
|
/* a C EXPR_STMT_NODE */
|
|
p = bns->entry.Template.ll_ptr1;
|
|
/* assume it is expr list then asign op */
|
|
p = p->entry.Template.ll_ptr1;
|
|
while (p != NULL &&
|
|
p->entry.Template.ll_ptr1 != lls)
|
|
p = p->entry.Template.ll_ptr2;
|
|
if (p != NULL)
|
|
p = p->entry.Template.ll_ptr2;
|
|
if (lld->entry.Template.ll_ptr1 == NULL)
|
|
lld->entry.Template.ll_ptr1 = p;
|
|
else if (lld->entry.Template.ll_ptr1 != p)
|
|
lld->entry.Template.ll_ptr1 = NULL;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/* symbols do not agree */
|
|
}
|
|
g = g->next;
|
|
}
|
|
def = def->next;
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************/
|
|
/* build sets is called four times.Once with pass = 1 and once */
|
|
/* with pass = 2. On the first pass: */
|
|
/* 1. synthesized attributes: gen and use are passed up tree */
|
|
/* 2. the id fields of the biff nodes are renumbered in */
|
|
/* control flow tree preorder. i.e. lexical order */
|
|
/* on the second pass: */
|
|
/* 1. the inherited attributes are propogated down the tree */
|
|
/* 2. dependence arcs are generated. */
|
|
/* the variable rnd is used to destinguish between using info */
|
|
/* from a global analysis sweep and ignoring the effect of */
|
|
/* function calls. */
|
|
/***************************************************************/
|
|
PTR_SETS build_sets(int rnd, PTR_BFND b, PTR_REFL in_use, PTR_REFL in_def,int pass)
|
|
/*int rnd;*/ /* rnd = 0 first time and rnd = 1 after
|
|
* global analysis */
|
|
/*PTR_BFND b;*/
|
|
/*PTR_REFL in_use, in_def;*/
|
|
/*int pass;*/
|
|
{
|
|
PTR_BLOB bl;
|
|
PTR_SETS s;
|
|
PTR_REFL gen, use, out_use, out_def, detmp;
|
|
PTR_REFL out_useT, out_useF, out_defT, out_defF;
|
|
PTR_REFL remove_locals();
|
|
PTR_LLND link_set_list();
|
|
PTR_REFL tmp1, tmp2, tmp3;
|
|
|
|
if (b == NULL)
|
|
fprintf(stderr, "null bfnd!!\n");
|
|
|
|
if (b != NULL)
|
|
switch (b->variant) {
|
|
|
|
case GLOBAL:
|
|
node_count = 0;
|
|
bl = b->entry.Template.bl_ptr1;
|
|
b->id = node_count++;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
if ((bl->ref->variant == PROG_HEDR) ||
|
|
(bl->ref->variant == FUNC_HEDR) ||
|
|
(bl->ref->variant == PROC_HEDR))
|
|
s = build_sets(rnd, bl->ref, NULL, NULL, pass);
|
|
bl = bl->next;
|
|
}
|
|
break;
|
|
|
|
case PROG_HEDR:
|
|
/* PASS 1 ---------------------- */
|
|
/* visit each child */
|
|
if (pass == 1) {
|
|
b->id = node_count++;
|
|
if (b->entry.Template.sets == NULL)
|
|
b->entry.Template.sets = alloc_sets();
|
|
b->entry.Template.sets->out_use = NULL;
|
|
b->entry.Template.sets->in_use = NULL;
|
|
b->entry.Template.sets->out_def = NULL;
|
|
b->entry.Template.sets->in_def = NULL;
|
|
b->entry.Template.sets->gen = NULL;
|
|
b->entry.Template.sets->use = NULL;
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, NULL, NULL, pass);
|
|
bl = bl->next;
|
|
}
|
|
return (b->entry.Template.sets);
|
|
}
|
|
else {
|
|
PTR_REFL t1, t2;
|
|
/* PASS 2 ---------------------- */
|
|
in_use = NULL;
|
|
out_def = NULL;
|
|
out_use = NULL;
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, out_use, out_def, pass);
|
|
out_use = s->out_use;
|
|
out_def = s->out_def;
|
|
bl = bl->next;
|
|
}
|
|
/* at this point intersect out_use and */
|
|
/* out_def with the global and commons */
|
|
/* and set to out_use and out_def */
|
|
t1 = intersect_refl(b->entry.Template.sets->in_def, out_def);
|
|
t2 = remove_locals_from_list(out_def);
|
|
b->entry.Template.sets->out_def = union_refl(t1, t2);
|
|
disp_refl(t1);
|
|
disp_refl(t2);
|
|
t1 = intersect_refl(b->entry.Template.sets->in_def, out_use);
|
|
t2 = remove_locals_from_list(out_use);
|
|
b->entry.Template.sets->out_use = union_refl(t1, t2);
|
|
disp_refl(t1);
|
|
disp_refl(t2);
|
|
if (rnd == 0) {
|
|
fprintf(stderr, "%%program %s --\n",
|
|
b->entry.procedure.proc_symb->ident);
|
|
fprintf(stderr, "%s\n",
|
|
b->entry.procedure.proc_symb->ident);
|
|
fprintf(stderr, ">>L %d \n", b->g_line);
|
|
fprintf(stderr, "%%defines variables\n");
|
|
b->entry.Template.ll_ptr2 =
|
|
make_llnd(cur_file, EXPR_LIST, NULL, NULL, NULL);
|
|
b->entry.Template.ll_ptr2->entry.Template.ll_ptr1 =
|
|
link_set_list(b->entry.Template.sets->out_def);
|
|
b->entry.Template.ll_ptr3 =
|
|
make_llnd(cur_file, EXPR_LIST, NULL, NULL, NULL);
|
|
b->entry.Template.ll_ptr3->entry.Template.ll_ptr1 =
|
|
link_set_list(b->entry.Template.sets->out_use);
|
|
fprintf(stderr, "%s",
|
|
(UnparseLlnd[cur_file->lang])(b->entry.Template.ll_ptr2));
|
|
fprintf(stderr, "%% and uses\n");
|
|
fprintf(stderr, "%s\n",
|
|
(UnparseLlnd[cur_file->lang])(b->entry.Template.ll_ptr3));
|
|
fprintf(stderr, "\n");
|
|
}
|
|
return (b->entry.Template.sets);
|
|
}
|
|
|
|
case PROC_HEDR:
|
|
case FUNC_HEDR:
|
|
/* PASS 1 ---------------------- */
|
|
if (pass == 1) {
|
|
b->id = node_count++;
|
|
if (b->entry.Template.sets == NULL)
|
|
b->entry.Template.sets = alloc_sets();
|
|
b->entry.Template.sets->out_use = NULL;
|
|
b->entry.Template.sets->in_use = NULL;
|
|
b->entry.Template.sets->out_def = NULL;
|
|
b->entry.Template.sets->in_def = NULL;
|
|
b->entry.Template.sets->gen = NULL;
|
|
b->entry.Template.sets->use = NULL;
|
|
/* set in_def to be a ref list of all */
|
|
/* parameters to this proc. this is */
|
|
/* appended with commons and then it is */
|
|
/* interesected with the real ref and */
|
|
/* use list in pass 2. */
|
|
b->entry.Template.sets->in_def =
|
|
make_name_list(b->entry.Template.symbol->entry.proc_decl.in_list);
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, NULL, NULL, pass);
|
|
bl = bl->next;
|
|
}
|
|
return (b->entry.Template.sets);
|
|
}
|
|
else {
|
|
PTR_REFL t1, t2;
|
|
|
|
/* PASS 2 ---------------------- */
|
|
/* visit each child */
|
|
/* in_def = in_params; in_use = {}; out_def = in_def; out_use = {};
|
|
* for each child do pass out_use and out_def; visit child; out_use =
|
|
* child.out_use; out_def = child.out_def; end; */
|
|
in_use = NULL;
|
|
out_def = NULL;
|
|
out_use = NULL;
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, out_use, out_def, pass);
|
|
out_use = s->out_use;
|
|
out_def = s->out_def;
|
|
bl = bl->next;
|
|
}
|
|
/* interest out_use and out_def with the */
|
|
/* parameters and common statements */
|
|
t1 = intersect_refl(b->entry.Template.sets->in_def, out_def);
|
|
t2 = remove_locals_from_list(out_def);
|
|
b->entry.Template.sets->out_def = union_refl(t1, t2);
|
|
disp_refl(t1);
|
|
disp_refl(t2);
|
|
t1 = intersect_refl(b->entry.Template.sets->in_def, out_use);
|
|
t2 = remove_locals_from_list(out_use);
|
|
b->entry.Template.sets->out_use = union_refl(t1, t2);
|
|
disp_refl(t1);
|
|
disp_refl(t2);
|
|
t1 = b->entry.Template.sets->out_def;
|
|
t2 = b->entry.Template.sets->out_use;
|
|
if (rnd == 0) {
|
|
b->entry.Template.ll_ptr2 =
|
|
make_llnd(cur_file, EXPR_LIST, NULL, NULL, NULL);
|
|
b->entry.Template.ll_ptr2->entry.Template.ll_ptr1 =
|
|
link_set_list(t1);
|
|
b->entry.Template.ll_ptr3 =
|
|
make_llnd(cur_file, EXPR_LIST, NULL, NULL, NULL);
|
|
b->entry.Template.ll_ptr3->entry.Template.ll_ptr1 =
|
|
link_set_list(t2);
|
|
fprintf(stderr, "%%procedure %s-\n",
|
|
b->entry.procedure.proc_symb->ident);
|
|
fprintf(stderr, "%s", (UnparseBfnd[cur_file->lang])(b));
|
|
fprintf(stderr, ">>L %d \n", b->g_line);
|
|
fprintf(stderr, "%%which defines values for-\n");
|
|
fprintf(stderr, "%s",
|
|
(UnparseLlnd[cur_file->lang])(b->entry.Template.ll_ptr2));
|
|
fprintf(stderr, "\n%%and uses values-\n");
|
|
fprintf(stderr, "%s\n",
|
|
(UnparseLlnd[cur_file->lang])(b->entry.Template.ll_ptr3));
|
|
}
|
|
return (b->entry.Template.sets);
|
|
}
|
|
case COMM_STAT:
|
|
if (pass == 1) {
|
|
b->id = node_count++;
|
|
if (b->entry.Template.sets == NULL)
|
|
b->entry.Template.sets = alloc_sets();
|
|
b->entry.Template.sets->gen = NULL;
|
|
b->entry.Template.sets->use = NULL;
|
|
/* now gather up all the varaibles and */
|
|
/* link them in to the parent node. */
|
|
/* not done yet. */
|
|
detmp = NULL;
|
|
tmp1 = gather_refl(rnd, &detmp, b, b->entry.Template.ll_ptr1);
|
|
tmp2 = b->control_parent->entry.Template.sets->in_def;
|
|
while ((tmp2 != NULL) && (tmp2->next != NULL))
|
|
tmp2 = tmp2->next;
|
|
if (tmp2 == NULL)
|
|
b->control_parent->entry.Template.sets->in_def = tmp1;
|
|
else
|
|
tmp2->next = tmp1;
|
|
return (b->entry.Template.sets);
|
|
}
|
|
else {
|
|
/* PASS 2 ----------------------- */
|
|
/* just pass everything through! */
|
|
b->entry.Template.sets->out_def = in_def;
|
|
b->entry.Template.sets->out_use = in_use;
|
|
return (b->entry.Template.sets);
|
|
}
|
|
case EXPR_STMT_NODE:
|
|
/* PASS 1 ----------------------- */
|
|
/* make synth. attribs gen, use */
|
|
if (pass == 1) {
|
|
b->id = node_count++;
|
|
if (b->entry.Template.sets == NULL)
|
|
b->entry.Template.sets = alloc_sets();
|
|
if (b->entry.Template.sets->gen == NULL) {
|
|
detmp = NULL;
|
|
tmp1 = gather_refl(rnd, &detmp, b, b->entry.Template.ll_ptr1);
|
|
/* we only want the first. the others are uses */
|
|
b->entry.Template.sets->gen = detmp;
|
|
b->entry.Template.sets->use = tmp1;
|
|
}
|
|
return (b->entry.Template.sets);
|
|
}
|
|
else {
|
|
/* PASS 2 ----------------------- */
|
|
b->entry.Template.sets->in_use = copy_refl(in_use);
|
|
b->entry.Template.sets->in_def = copy_refl(in_def);
|
|
|
|
/* set local kill = { X in in_def | ref(X) in gen } */
|
|
out_def = rem_kill(in_def, b->entry.Template.sets->gen);
|
|
|
|
assign(&out_def,union_refl(out_def, b->entry.Template.sets->gen));
|
|
b->entry.Template.sets->out_def = out_def;
|
|
|
|
/* out_use = in_use + use */
|
|
b->entry.Template.sets->out_use =
|
|
union_refl(in_use, b->entry.Template.sets->use);
|
|
propogate(in_def, b->entry.Template.sets->use);
|
|
return (b->entry.Template.sets);
|
|
}
|
|
case ASSIGN_STAT:
|
|
case M_ASSIGN_STAT:
|
|
case SUM_ACC:
|
|
case MULT_ACC:
|
|
case MAX_ACC:
|
|
case MIN_ACC:
|
|
case CAT_ACC:
|
|
case OR_ACC:
|
|
case AND_ACC:
|
|
case READ_STAT:
|
|
case WRITE_STAT:
|
|
case PROC_STAT:
|
|
/* PASS 1 ----------------------- */
|
|
/* make synth. attribs gen, use */
|
|
if (pass == 1) {
|
|
b->id = node_count++;
|
|
if (b->entry.Template.sets == NULL)
|
|
b->entry.Template.sets = alloc_sets();
|
|
if (b->entry.Template.sets->gen == NULL) {
|
|
detmp = NULL;
|
|
tmp1 = gather_refl(rnd, &detmp, b, b->entry.Template.ll_ptr1);
|
|
if (b->variant == PROC_STAT) {
|
|
b->entry.Template.sets->gen = detmp;
|
|
b->entry.Template.sets->use = tmp1;
|
|
return (b->entry.Template.sets);
|
|
}
|
|
/* we only want the first. the others are uses */
|
|
if (tmp1 == NULL) {
|
|
tmp2 = NULL;
|
|
b->entry.Template.sets->gen = NULL;
|
|
}
|
|
else {
|
|
tmp2 = tmp1->next;
|
|
tmp1->next = NULL;
|
|
b->entry.Template.sets->gen = tmp1;
|
|
}
|
|
}
|
|
else
|
|
tmp2 = NULL;
|
|
if (b->entry.Template.sets->use == NULL) {
|
|
detmp = NULL;
|
|
tmp1 = gather_refl(rnd, &detmp, b, b->entry.Template.ll_ptr2);
|
|
if (tmp2 != NULL) {
|
|
tmp3 = union_refl(tmp1, tmp2);
|
|
disp_refl(tmp1);
|
|
disp_refl(tmp2);
|
|
}
|
|
else
|
|
tmp3 = tmp1;
|
|
b->entry.Template.sets->use = tmp3;
|
|
}
|
|
return (b->entry.Template.sets);
|
|
}
|
|
else {
|
|
/* PASS 2 ----------------------- */
|
|
b->entry.Template.sets->in_use = copy_refl(in_use);
|
|
b->entry.Template.sets->in_def = copy_refl(in_def);
|
|
|
|
/* set local kill = { X in in_def | ref(X) in gen } */
|
|
out_def = rem_kill(in_def, b->entry.Template.sets->gen);
|
|
|
|
/* create synth. attrib. out_def = in_def - kill + gen */
|
|
assign(&out_def,
|
|
union_refl(out_def, b->entry.Template.sets->gen)
|
|
);
|
|
b->entry.Template.sets->out_def = out_def;
|
|
|
|
/* out_use = in_use + use */
|
|
b->entry.Template.sets->out_use =
|
|
union_refl(in_use, b->entry.Template.sets->use);
|
|
|
|
propogate(in_def, b->entry.Template.sets->use);
|
|
return (b->entry.Template.sets);
|
|
}
|
|
|
|
case LOOP_NODE:
|
|
case FOR_NODE:
|
|
case WHILE_NODE:
|
|
/* PASS 1 ---------------------- */
|
|
/* for each child collect gen and use */
|
|
if (pass == 1) {
|
|
b->id = node_count++;
|
|
use = NULL;
|
|
gen = NULL;
|
|
detmp = NULL;
|
|
if (b->entry.Template.symbol == NULL) { /* this is a C loop */
|
|
use = gather_refl(rnd, &detmp, b, b->entry.Template.ll_ptr1);
|
|
gen = gather_refl(rnd, &detmp, b, b->entry.Template.ll_ptr2);
|
|
assign(&use, union_refl(use, gen));
|
|
gen = gather_refl(rnd, &detmp, b, b->entry.Template.ll_ptr3);
|
|
assign(&use, union_refl(use, gen));
|
|
assign(&gen, detmp);
|
|
}
|
|
else
|
|
use = gather_refl(rnd, &detmp, b, b->entry.for_node.range);
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, NULL, NULL, pass);
|
|
assign(&use, union_refl(use, s->use));
|
|
gen = rem_kill(gen, s->gen); /* try to fix propogation prob */
|
|
assign(&gen, union_refl(gen, s->gen));
|
|
bl = bl->next;
|
|
}
|
|
if (b->entry.Template.sets == NULL)
|
|
b->entry.Template.sets = alloc_sets();
|
|
b->entry.Template.sets->out_use = NULL;
|
|
b->entry.Template.sets->in_use = NULL;
|
|
b->entry.Template.sets->out_def = NULL;
|
|
b->entry.Template.sets->in_def = NULL;
|
|
b->entry.Template.sets->gen = remove_locals(b, gen);
|
|
b->entry.Template.sets->use = remove_locals(b, use);
|
|
return (b->entry.Template.sets);
|
|
}
|
|
else {
|
|
/* PASS 2 ---------------------- */
|
|
s = b->entry.Template.sets;
|
|
b->entry.Template.sets->in_use = copy_refl(in_use);
|
|
b->entry.Template.sets->out_def = copy_refl(in_def);
|
|
/* first take care of range varible propogation. */
|
|
detmp = NULL;
|
|
if (b->entry.Template.symbol == NULL) { /* this is a C loop */
|
|
use = gather_refl(rnd, &detmp, b, b->entry.Template.ll_ptr1);
|
|
gen = gather_refl(rnd, &detmp, b, b->entry.Template.ll_ptr2);
|
|
assign(&use, union_refl(use, gen));
|
|
gen = gather_refl(rnd, &detmp, b, b->entry.Template.ll_ptr3);
|
|
assign(&use, union_refl(use, gen));
|
|
gen = detmp;
|
|
}
|
|
else
|
|
use = gather_refl(rnd, &detmp, b, b->entry.for_node.range);
|
|
propogate(in_def, use);
|
|
/* now take care of children */
|
|
out_use = union_refl(in_use, s->use);
|
|
out_def = union_refl(in_def, s->gen);
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, out_use, out_def, pass);
|
|
assign(&out_use, copy_refl(s->out_use));
|
|
assign(&out_def, copy_refl(s->out_def));
|
|
bl = bl->next;
|
|
}
|
|
b->entry.Template.sets->out_use = out_use;
|
|
b->entry.Template.sets->out_def = out_def;
|
|
return (b->entry.Template.sets);
|
|
}
|
|
case PARFOR_NODE:
|
|
case CDOALL_NODE:
|
|
/* PASS 1 ---------------------- */
|
|
/* for each child collect gen and use */
|
|
if (pass == 1) {
|
|
b->id = node_count++;
|
|
use = NULL;
|
|
gen = NULL;
|
|
detmp = NULL;
|
|
if (b->variant == PARFOR_NODE) {
|
|
use = gather_refl(rnd, &detmp, b, b->entry.Template.ll_ptr2);
|
|
bl = b->entry.Template.bl_ptr1;
|
|
}
|
|
else {
|
|
use = gather_refl(rnd, &detmp, b, b->entry.for_node.range);
|
|
bl = b->entry.Template.bl_ptr2;
|
|
}
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, NULL, NULL, pass);
|
|
assign(&use, union_refl(use, s->use));
|
|
assign(&gen, union_refl(gen, s->gen));
|
|
bl = bl->next;
|
|
}
|
|
if (b->variant == CDOALL_NODE &&
|
|
b->entry.Template.bl_ptr1 != NULL) {
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, NULL, NULL, pass);
|
|
assign(&use, union_refl(use, s->use));
|
|
assign(&gen, union_refl(gen, s->gen));
|
|
bl = bl->next;
|
|
}
|
|
}
|
|
if (b->entry.Template.sets == NULL)
|
|
b->entry.Template.sets = alloc_sets();
|
|
b->entry.Template.sets->out_use = NULL;
|
|
b->entry.Template.sets->in_use = NULL;
|
|
b->entry.Template.sets->out_def = NULL;
|
|
b->entry.Template.sets->in_def = NULL;
|
|
/* here is difference with other loops */
|
|
/* locals must be deleted from gen and use */
|
|
b->entry.Template.sets->gen = remove_locals(b, gen);
|
|
b->entry.Template.sets->use = remove_locals(b, use);
|
|
return (b->entry.Template.sets);
|
|
}
|
|
else {
|
|
/* PASS 2 ---------------------- */
|
|
s = b->entry.Template.sets;
|
|
b->entry.Template.sets->in_use = copy_refl(in_use);
|
|
b->entry.Template.sets->in_def = copy_refl(in_def);
|
|
detmp = NULL;
|
|
if (b->variant == PARFOR_NODE) {
|
|
use = gather_refl(rnd, &detmp, b, b->entry.Template.ll_ptr2);
|
|
bl = b->entry.Template.bl_ptr1;
|
|
}
|
|
else {
|
|
use = gather_refl(rnd, &detmp, b, b->entry.for_node.range);
|
|
bl = b->entry.Template.bl_ptr2;
|
|
}
|
|
out_use = union_refl(in_use, s->use);
|
|
out_def = union_refl(in_def, s->gen);
|
|
propogate(in_def, use);
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, out_use, out_def, pass);
|
|
assign(&out_use, copy_refl(s->out_use));
|
|
assign(&out_def, copy_refl(s->out_def));
|
|
bl = bl->next;
|
|
}
|
|
if (b->variant == CDOALL_NODE &&
|
|
b->entry.Template.bl_ptr1 != NULL) {
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, out_use, out_def, pass);
|
|
assign(&out_use, copy_refl(s->out_use));
|
|
assign(&out_def, copy_refl(s->out_def));
|
|
bl = bl->next;
|
|
}
|
|
}
|
|
b->entry.Template.sets->out_use = out_use;
|
|
b->entry.Template.sets->out_def = out_def;
|
|
return (b->entry.Template.sets);
|
|
}
|
|
case LOGIF_NODE:
|
|
case ELSEIF_NODE:
|
|
case IF_NODE:
|
|
/* PASS 1 ---------------------- */
|
|
/* for each child collect gen and use */
|
|
if (pass == 1) {
|
|
b->id = node_count++;
|
|
use = NULL;
|
|
gen = NULL;
|
|
use = gather_refl(rnd, &gen, b, b->entry.Template.ll_ptr1);
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, NULL, NULL, pass);
|
|
assign(&use, union_refl(use, s->use));
|
|
assign(&gen, union_refl(gen, s->gen));
|
|
bl = bl->next;
|
|
}
|
|
if (b->variant != LOGIF_NODE) {
|
|
bl = b->entry.Template.bl_ptr2;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, NULL, NULL, pass);
|
|
assign(&use, union_refl(use, s->use));
|
|
assign(&gen, union_refl(gen, s->gen));
|
|
bl = bl->next;
|
|
}
|
|
}
|
|
if (b->entry.Template.sets == NULL)
|
|
b->entry.Template.sets = alloc_sets();
|
|
b->entry.Template.sets->out_use = NULL;
|
|
b->entry.Template.sets->in_use = NULL;
|
|
b->entry.Template.sets->out_def = NULL;
|
|
b->entry.Template.sets->in_def = NULL;
|
|
b->entry.Template.sets->gen = gen;
|
|
b->entry.Template.sets->use = use;
|
|
return (b->entry.Template.sets);
|
|
}
|
|
else {
|
|
/* PASS 2 ------------------------------------------------ */
|
|
/* for each branch do */
|
|
/* out_use = in_use; out_def_branch = in_def; */
|
|
/* for each child do */
|
|
/* pass out_use and out_def_branch; */
|
|
/* visit child */
|
|
/* out_use = child.out_use; */
|
|
/* out_def_branch = child.out_def; */
|
|
/* end; */
|
|
/* out_def = out_def_lbranch+out_def_rbranch */
|
|
/* ________________________________________________________ */
|
|
out_defT = in_def;
|
|
out_useT = in_use;
|
|
/* visit True children */
|
|
b->entry.Template.sets->in_use =
|
|
copy_refl(in_use);
|
|
b->entry.Template.sets->in_def =
|
|
copy_refl(in_def);
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, out_useT, out_defT, pass);
|
|
out_useT = s->out_use;
|
|
out_defT = s->out_def;
|
|
bl = bl->next;
|
|
}
|
|
out_defF = in_def;
|
|
out_useF = in_use;
|
|
/* visit False children */
|
|
bl = b->entry.Template.bl_ptr2;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
s = build_sets(rnd, bl->ref, out_useF, out_defF, pass);
|
|
out_useF = s->out_use;
|
|
out_defF = s->out_def;
|
|
bl = bl->next;
|
|
}
|
|
gen = NULL;
|
|
use = gather_refl(rnd, &gen, b, b->entry.Template.ll_ptr1);
|
|
assign(&use, union_refl(out_useF, use));
|
|
assign(&gen, union_refl(out_defF, gen));
|
|
b->entry.Template.sets->out_use =
|
|
union_refl(use, out_useT);
|
|
b->entry.Template.sets->out_def =
|
|
union_refl(gen, out_defT);
|
|
|
|
return (b->entry.Template.sets);
|
|
}
|
|
case EXIT_NODE:
|
|
fprintf(stderr, "exit node found! no dep ananysis!\n");
|
|
|
|
default: /* assume a no op */
|
|
if (pass == 1) {
|
|
b->id = node_count++;
|
|
if (b->entry.Template.sets == NULL)
|
|
b->entry.Template.sets = alloc_sets();
|
|
b->entry.Template.sets->gen = NULL;
|
|
b->entry.Template.sets->use = NULL;
|
|
return (b->entry.Template.sets);
|
|
}
|
|
else {
|
|
/* PASS 2 ----------------------- */
|
|
/* just pass everything through! */
|
|
b->entry.Template.sets->out_def = in_def;
|
|
b->entry.Template.sets->out_use = in_use;
|
|
return (b->entry.Template.sets);
|
|
}
|
|
}
|
|
return (NULL);
|
|
}
|
|
|
|
void gendeps(b)
|
|
PTR_BFND b;
|
|
{
|
|
PTR_BLOB bl;
|
|
|
|
if (b != NULL)
|
|
switch (b->variant) {
|
|
|
|
case GLOBAL:
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
gendeps(bl->ref);
|
|
bl = bl->next;
|
|
}
|
|
break;
|
|
|
|
case PROG_HEDR:
|
|
/* visit each child */
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
gendeps(bl->ref);
|
|
bl = bl->next;
|
|
}
|
|
break;
|
|
case PROC_HEDR:
|
|
case FUNC_HEDR:
|
|
/* visit each child */
|
|
if (show_deps)
|
|
fprintf(stderr, "---------Procedure %s------------------\n",
|
|
b->entry.procedure.proc_symb->ident);
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
gendeps(bl->ref);
|
|
if (num_ll_allocated > 10000)
|
|
collect_garbage(cur_file);
|
|
bl = bl->next;
|
|
}
|
|
break;
|
|
case EXPR_STMT_NODE:
|
|
case ASSIGN_STAT:
|
|
case M_ASSIGN_STAT:
|
|
case SUM_ACC:
|
|
case MULT_ACC:
|
|
case MAX_ACC:
|
|
case MIN_ACC:
|
|
case CAT_ACC:
|
|
case OR_ACC:
|
|
case AND_ACC:
|
|
case READ_STAT:
|
|
case WRITE_STAT:
|
|
case PROC_STAT:
|
|
if (num_ll_allocated > 10000)
|
|
collect_garbage(cur_file);
|
|
if (show_deps)
|
|
fprintf(stderr, "----- line %d \n", b->g_line);
|
|
make_deps(FLOWD, b->entry.Template.sets->in_def,
|
|
b->entry.Template.sets->use);
|
|
|
|
make_deps(OUTPUTD, b->entry.Template.sets->in_def,
|
|
b->entry.Template.sets->gen);
|
|
|
|
make_deps(ANTID, b->entry.Template.sets->in_use,
|
|
b->entry.Template.sets->gen);
|
|
|
|
make_deps(INPUTD, b->entry.Template.sets->in_use,
|
|
b->entry.Template.sets->use);
|
|
|
|
break;
|
|
|
|
case LOOP_NODE:
|
|
case FOR_NODE:
|
|
case WHILE_NODE:
|
|
if (show_deps)
|
|
fprintf(stderr, "----- line %d \n", b->g_line);
|
|
make_deps(FLOWD, b->entry.Template.sets->in_def,
|
|
b->entry.Template.sets->use);
|
|
|
|
make_deps(OUTPUTD, b->entry.Template.sets->in_def,
|
|
b->entry.Template.sets->gen);
|
|
|
|
make_deps(ANTID, b->entry.Template.sets->in_use,
|
|
b->entry.Template.sets->gen);
|
|
|
|
make_deps(INPUTD, b->entry.Template.sets->in_use,
|
|
b->entry.Template.sets->use);
|
|
|
|
if (num_ll_allocated > 10000)
|
|
collect_garbage(cur_file);
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
gendeps(bl->ref);
|
|
if (num_ll_allocated > 10000)
|
|
collect_garbage(cur_file);
|
|
bl = bl->next;
|
|
}
|
|
break;
|
|
case FORALL_NODE:
|
|
case CDOALL_NODE:
|
|
case PARFOR_NODE:
|
|
if (show_deps)
|
|
fprintf(stderr, "----- line %d \n", b->g_line);
|
|
make_deps(FLOWD, b->entry.Template.sets->in_def,
|
|
b->entry.Template.sets->use);
|
|
|
|
make_deps(OUTPUTD, b->entry.Template.sets->in_def,
|
|
b->entry.Template.sets->gen);
|
|
|
|
make_deps(ANTID, b->entry.Template.sets->in_use,
|
|
b->entry.Template.sets->gen);
|
|
|
|
make_deps(INPUTD, b->entry.Template.sets->in_use,
|
|
b->entry.Template.sets->use);
|
|
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
gendeps(bl->ref);
|
|
bl = bl->next;
|
|
}
|
|
break;
|
|
case LOGIF_NODE:
|
|
case IF_NODE:
|
|
if (show_deps)
|
|
fprintf(stderr, "----- line %d \n", b->g_line);
|
|
make_deps(FLOWD, b->entry.Template.sets->in_def,
|
|
b->entry.Template.sets->use);
|
|
|
|
make_deps(OUTPUTD, b->entry.Template.sets->in_def,
|
|
b->entry.Template.sets->gen);
|
|
|
|
make_deps(ANTID, b->entry.Template.sets->in_use,
|
|
b->entry.Template.sets->gen);
|
|
|
|
make_deps(INPUTD, b->entry.Template.sets->in_use,
|
|
b->entry.Template.sets->use);
|
|
|
|
/* visit True children */
|
|
bl = b->entry.Template.bl_ptr1;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
gendeps(bl->ref);
|
|
if (num_ll_allocated > 10000)
|
|
collect_garbage(cur_file);
|
|
bl = bl->next;
|
|
}
|
|
/* visit False children */
|
|
if (b->variant != LOGIF_NODE) {
|
|
bl = b->entry.Template.bl_ptr2;
|
|
while ((bl != NULL) && (bl->ref != b)) {
|
|
gendeps(bl->ref);
|
|
if (num_ll_allocated > 10000)
|
|
collect_garbage(cur_file);
|
|
bl = bl->next;
|
|
}
|
|
}
|
|
break;
|
|
case EXIT_NODE:
|
|
fprintf(stderr, "exit node found! no dep ananysis!\n");
|
|
break;
|
|
default: /* assume a no op */
|
|
/* just pass everything through! */
|
|
break;
|
|
}
|
|
}
|
|
|
|
void relink(fi)
|
|
PTR_FILE fi;
|
|
{
|
|
PTR_BFND bf_ptr;
|
|
int count = 1;
|
|
|
|
for (bf_ptr = fi->head_bfnd; bf_ptr != NULL; bf_ptr = bf_ptr->thread)
|
|
bf_ptr->id = count++;
|
|
}
|