#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); } /**********************************************************************/