#include "integrate.h"
/**********************************************************************/
/* Code */
/**********************************************************************/
/* Before and after hooks to be passed to my_suif_proc_iter */
void before_hook(void)
{
/* Do nothing */
}
void after_hook(void)
{
count_qints();
delete_duplicate_sets(k_qinfluence_set);
delete_duplicate_sets(k_qif_set);
}
/**********************************************************************/
// [....]
/**********************************************************************/
void define_qifs(tree_node *t, int *num_qifs)
{
annote *an;
char *an_string;
block_symtab *symbol_table;
var_sym *qif_variable;
base_symtab *file_symbol_table;
if (t->kind() != TREE_IF)
return; /* After this: t->kind() == TREE_IF */
an = t->annotes()->peek_annote(k_qif_statement);
if (an == NULL)
return; /* After this: an != NULL */
(*num_qifs)++;
an_string = (an->immeds()->tail()->contents).string();
symbol_table = (block_symtab *) t->scope();
#define LOOK_IN_PARENT_TABLES TRUE
qif_variable = symbol_table->lookup_var(an_string, LOOK_IN_PARENT_TABLES);
assert(qif_variable != NULL);
file_symbol_table = symbol_table;
// In some ways it would be nicer if definitions for qif vars and
// qints were pushed into the global symbol table instead of the
// file symbol table. However, can't do that, since SUIF rightfully
// objects that in the C paradigm, there is no meaning to a global
// variable definition not associated with a source file.
while (file_symbol_table->kind() != SYMTAB_FILE)
file_symbol_table = file_symbol_table->parent();
if (qif_variable->annotes()->peek_annote(k_qif_variable_defined) == NULL)
{
var_def *vd;
#define VD_DATA_ALIGNMENT 32
vd = new var_def(qif_variable,VD_DATA_ALIGNMENT);
immed_list *il = new immed_list();
il->push(new immed_list_e(*(new immed(0))));
il->push(new immed_list_e(*(new immed(32))));
il->push(new immed_list_e(*(new immed(1))));
/* Note: the k_repeat_init annotation [1 32 0] specifies initialization
to zero; however, s2c will not actually explicitly convert these back
to "int i = 0;" since ANSI C specifies that static variables which
are not initialized must be initialized as if they were assigned
0, and s2c apparently takes advantage of this. */
vd->append_annote(k_repeat_init, (void *) il);
file_symbol_table->add_def(vd);
attach_annotation_string
(qif_variable, k_qif_variable_defined,
file_symbol_table->name());
if (debug_level >= 2)
printf(" Definition created for qif variable '%s'.\n", an_string);
}
else
if (debug_level >= 2)
printf(" ...qif variable '%s' already given definition.\n", an_string);
}
/**********************************************************************/
void qif_set_accumulate(tree_node *t, CStringSet *pSet)
{
attach_annotation_string(t, k_qif_set_analyzed, "analyzed");
annote *an = t->annotes()->peek_annote(k_qif_statement);
pSet->add(strdup((an->immeds()->tail()->contents).string()));
tree_node_list *pTNL = ((tree_if *) t)->else_part();
/* pTNL points to (unfortunately, rather dependent on SUIF particulars):
(0) Nothing (no final qelse).
(1) Final qelse, with need for a block:
BLOCK
mrk
....
BLOCK END
(2) Another qif in the chain:
mrk
TREE_IF
(3) Final qelse with no need for a block:
mrk
<statements expressed in SUIF>
*/
if (pTNL->count() == 0)
{
pSet->add("... NO FINAL QELSE");
return;
}
if ((pTNL->count() == 1) && (pTNL->head()->contents->is_block()))
{
pSet->add("... FINAL QELSE");
return;
}
assert(pTNL->count() > 1);
tree_node *pTN2 = pTNL->head()->next()->contents;
if (pTN2->is_if() && (pTN2->annotes()->peek_annote(k_qif_statement) != NULL))
{
qif_set_accumulate(pTN2, pSet);
return;
}
else
{
pSet->add("... FINAL QELSE");
return;
}
}
void find_qif_sets(tree_node *t, int *num_qif_sets)
{
if (t->kind() != TREE_IF)
return; /* After this: t->kind() == TREE_IF */
if ((t->annotes()->peek_annote(k_qif_statement) == NULL)
|| (t->annotes()->peek_annote(k_qif_set_analyzed) != NULL))
return; /* After this: t is an unanalyzed qif statement. */
CStringSet set;
qif_set_accumulate(t, &set);
assert(! set.empty());
t->append_annote(k_qif_set, (void *) pCStringSet2pIL(&set));
global_symbol_table->append_annote
(k_qif_set, (void *) pCStringSet2pIL(&set));
if (debug_level >= 2)
{
printf(" Found qif set {%s}.\n", pCStringSet2pChar(&set));
}
(*num_qif_sets)++;
}
/**********************************************************************/
void count_qints(void)
{
int num_qints = 0;
sym_node_list_iter *iter = new sym_node_list_iter
(global_symbol_table->symbols());
while (! iter->is_empty())
{
sym_node *sn = iter->step();
annote *an = sn->annotes()->peek_annote(k_qint_parameter);
if (an != NULL)
{
num_qints++;
if (debug_level >= 2)
printf(" Found qint declaration '%s' [%s].\n",
sn->name(),
(an->immeds()->tail()->contents).string());
}
}
if (debug_level >= 1)
printf(" File set had %d qint parameters total.\n", num_qints);
}
/**********************************************************************/
void qinfluence_set_process_TNL(CStringSet *pOuterSet, tree_node_list *pTNL)
{
tree_node_list_iter *iter = new tree_node_list_iter(pTNL);
while (! iter->is_empty())
{
tree_node *tn = iter->step();
tree_node_dispatch(pOuterSet, tn);
}
}
void tree_node_dispatch(CStringSet *pOuterSet, tree_node *t)
{
switch (t->kind())
{
case TREE_BLOCK:
if (t->annotes()->peek_annote(k_qinfluence_statement) != NULL)
{
if (t->annotes()->peek_annote(k_qinfluence_set) == NULL)
mark_qinfluence_set_and_traverse(pOuterSet, (tree_block *) t);
else
assert(0); /* shouldn't happen, traversal order must have gotten
messed up. */
}
else
qinfluence_set_process_TNL(pOuterSet, ((tree_block *) t)->body());
return;
case TREE_LOOP:
qinfluence_set_process_TNL(pOuterSet, ((tree_loop *) t)->body());
return;
case TREE_FOR:
qinfluence_set_process_TNL(pOuterSet, ((tree_for *) t)->body());
qinfluence_set_process_TNL(pOuterSet, ((tree_for *) t)->landing_pad());
return;
case TREE_IF:
qinfluence_set_process_TNL(pOuterSet, ((tree_if *) t)->then_part());
qinfluence_set_process_TNL(pOuterSet, ((tree_if *) t)->else_part());
return;
case TREE_INSTR:
return;
default:
/* I've enumerated all the SUIF-listed TREE_FOO types.... */
assert(0); /* shouldn't ever be reached.... */
}
}
void mark_qinfluence_set_and_traverse(CStringSet *pOuterSet, tree_block *t)
{
/*
"Requires": called on an unanalyzed qinfluence TREE_BLOCK.
Effects: marks t with its qinfluence set, also side-effects children
of t with their qinfluence sets.
*/
annote *an = t->annotes()->peek_annote(k_qinfluence_statement);
assert((t->kind() == TREE_BLOCK)
&& (an != NULL)
&& ((t->annotes()->peek_annote(k_qinfluence_set)) == NULL));
CStringSet *pMySet = new CStringSet();
char *str = strdup((an->immeds()->tail()->contents).string());
char *ptr = strtok(str, ",");
while (ptr != NULL)
{
pMySet->add(strdup(ptr));
ptr = strtok(NULL, ",");
}
*pMySet |= *pOuterSet;
t->append_annote(k_qinfluence_set, (void *) pCStringSet2pIL(pMySet));
global_symbol_table->append_annote
(k_qinfluence_set, (void *)pCStringSet2pIL(pMySet));
if (debug_level >= 2)
{
printf(" Found qinfluence set (");
Pix index;
index = pMySet->first();
while (index != 0)
{
printf("'%s'", (*pMySet)(index));
pMySet->next(index);
if (index != 0)
printf(",");
}
printf(").\n");
}
qinfluence_set_process_TNL(pMySet, t->body());
delete pMySet;
}
void find_qinfluence_sets(tree_node *t, int *num_qinfluence_sets)
{
if (t->kind() != TREE_BLOCK)
return; /* After this: t->kind() == TREE_BLOCK */
if ((t->annotes()->peek_annote(k_qinfluence_statement) == NULL)
|| (t->annotes()->peek_annote(k_qinfluence_set) != NULL))
return; /* After this: t is an unanaluzed qinfluence block. */
CStringSet *pEmptySet = new CStringSet();
mark_qinfluence_set_and_traverse(pEmptySet, (tree_block *) t);
delete pEmptySet;
(*num_qinfluence_sets)++;
}
/**********************************************************************/
void do_proc(tree_proc *tp)
{
int num_qifs = 0;
int num_qif_sets = 0;
int num_qinfluence_sets = 0;
if (global_symbol_table == NULL)
/* Can't put this in before_hook since I need to grab onto tp.... */
{
global_symbol_table = tp->scope();
while (global_symbol_table->kind() != SYMTAB_GLOBAL)
global_symbol_table = global_symbol_table->parent();
}
char *procedure_name = tp->proc()->name();
if (debug_level >= 1)
printf(" do_proc: entering procedure '%s'.\n", procedure_name);
/* Note that the default parameters for tp->map() are for a preorder
tree traversal; the preorder nature is important. */
tp->map(define_qifs, &num_qifs);
if (debug_level >= 1)
printf(" do_proc: procedure '%s' has %d qif statements.\n",
procedure_name, num_qifs);
tp->map(find_qif_sets, &num_qif_sets);
if (debug_level >= 1)
printf(" do_proc: procedure '%s' has %d qif sets.\n",
procedure_name, num_qif_sets);
/*
XXX Somewhere around here I could use a step to effectively
insert qinfluence statements as necessary for qints which don't
have any qinfluences otherwise.
Or, I could just leave it as is and make the programmer explicitly
put in qinfluence statements.
*/
tp->map(find_qinfluence_sets, &num_qinfluence_sets);
if (debug_level >= 1)
printf(" do_proc: procedure '%s' has %d outermost qinfluence sets.\n",
procedure_name, num_qinfluence_sets);
}
/**********************************************************************/
void delete_duplicate_sets(char *k_annotation_type)
{
annote_list *annotes = global_symbol_table->annotes();
annote *an;
CStringSet set;
int non_unique_sets = 0;
while ((an = annotes->get_annote(k_annotation_type)) != NULL)
{
CStringSet *pTmpSet = pIL2pCStringSet(an->immeds());
char *rep = pCStringSet2pChar(pTmpSet); delete pTmpSet;
set.add(rep);
if (debug_level >= 2)
printf(" delete_duplicate_sets(\"%s\"): found {%s}.\n",
k_annotation_type, rep);
non_unique_sets++;
}
if (debug_level >= 1)
{
printf(" delete_duplicate_sets(\"%s\"): total %d sets, %d unique.\n",
k_annotation_type, non_unique_sets, set.length());
}
Pix index = set.first();
while (index != 0)
{
static UID = 0;
CStringSet *pTmpSet = pChar2pCStringSet(set(index));
if (debug_level >= 2)
printf(" delete_duplicate_sets(\"%s\"): putting back {%s}.\n",
k_annotation_type, set(index));
immed_list *il = pCStringSet2pIL(pTmpSet);
il->push(new immed_list_e(*(new immed(UID++))));
global_symbol_table->append_annote
(k_annotation_type, (void *) il);
delete pTmpSet;
set.next(index);
}
}
/**********************************************************************/
int main(int argc, char *argv[])
{
start_suif(argc, argv);
register_qannotations();
process_command_line(argc, argv);
if (argc-optind != 2)
{
fprintf(stderr, "%s: wrong number of filenames given on command line.\n",
argv[0]);
exit(1);
}
#define WRITE_BACK_TO_FILE TRUE
my_suif_proc_iter(argc, argv, do_proc, before_hook, after_hook,
WRITE_BACK_TO_FILE);
}
/**********************************************************************/