One of the best way to learn how to write a new pass is to read some patches that implement new passes:

Some issues are raised (but not solved) in MakingGCCEasierToLearn

All the information concerning a pass is collected in a structure instantiated as in the following example:

struct tree_opt_pass pass_scev_cprop =
{
  "sccp",                               /* name */
  gate_scev_const_prop,                 /* gate */
  scev_const_prop,                      /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  0,                                    /* static_pass_number */
  TV_SCEV_CONST,                        /* tv_id */
  PROP_cfg | PROP_ssa,                  /* properties_required */
  0,                                    /* properties_provided */
  0,                                    /* properties_destroyed */
  0,                                    /* todo_flags_start */
  TODO_dump_func,                       /* todo_flags_finish */
  0                                     /* letter */
};

The current (march 2008) trunk (future 4.4) has a slightly different pass description (in the struct opt_pass of file gcc/tree-pass.h) which is included in specialized struct-s gimple_opt_pass rtl_opt_pass simple_ipa_opt_passwhich essentially add a type field (an enum).

Each of these fields is documented in the declaration of tree_opt_pass (included here, but you'll have to look at the source of [gccsource:tree-pass.h] for the last version):

/* Describe one pass.  */
struct tree_opt_pass
{
  /* Terse name of the pass used as a fragment of the dump file name.  */
  const char *name;

  /* If non-null, this pass and all sub-passes are executed only if
     the function returns true.  */
  bool (*gate) (void);

  /* This is the code to run.  If null, then there should be sub-passes
     otherwise this pass does nothing.  The return value contains
     TODOs to execute in addition to those in TODO_flags_finish.   */
  unsigned int (*execute) (void);

  /* A list of sub-passes to run, dependent on gate predicate.  */
  struct tree_opt_pass *sub;

  /* Next in the list of passes to run, independent of gate predicate.  */
  struct tree_opt_pass *next;

  /* Static pass number, used as a fragment of the dump file name.  */
  int static_pass_number;

  /* The timevar id associated with this pass.  */
  /* ??? Ideally would be dynamically assigned.  */
  unsigned int tv_id;

  /* Sets of properties input and output from this pass.  */
  unsigned int properties_required;
  unsigned int properties_provided;
  unsigned int properties_destroyed;

  /* Flags indicating common sets things to do before and after.  */
  unsigned int todo_flags_start;
  unsigned int todo_flags_finish;

  /* Letter for RTL dumps.  */
  char letter;
};

Once you have declared and defined your pass structure, you can schedule it in [gccsource:passes.c] using NEXT_PASS(). In your pass named foop (the content of field name in above structure), you can dump information to the dump_file (a possibly null FILE* variable), and this dump is triggered by passing -fdump-foop or -fdump-tree-foop or -fdump-ipa-foop or -fdump-rtl-foop as a compiler program flag. The exact name depends upon where is the pass scheduled in file passes.c. If the pass name starts with a star (or if it is null), no dump happens. It is suggested to uniquely name passes, and to comment their behavior (including the internal representations needed, computed, or invalidated by it) in a small paragraph.

None: WritingANewPass (last edited 2008-09-11 15:25:38 by BasileStarynkevitch)