next up previous contents
Next: add_profiling.cc Up: Source Code Previous: Source Code

integrate.cc

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

/**********************************************************************/



Reinventing Computing, MIT AI Lab. Author: pshuang@ai.mit.edu (Ping Huang)