Is this still an open project?  and if so can anyone
give me more information on what is needed?

Yes, it is.

Basically, insn-recog.c is a huge decision tree. genrecog.c builds it and outputs it as C code. It uses variables like "x0, x1, x2, ..., xn" which would become the virtual machine's registers. It should be possible to linearize into something like bytecodes (more likely an array of structs).

Some of the bytecodes are already visible from the "decision_type" enum in genrecog.c:

      DT_mode, DT_code, DT_veclen,
      DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide,
      DT_elt_zero_wide_safe,
      DT_const_int,
      DT_veclen_ge, DT_dup, DT_pred, DT_c_test,
      DT_accept_op, DT_accept_insn

To these, you should add some for control flow. In the end you may have something like

- one bytecode for each of DT_mode ... DT_dup
- if ... goto ...
- switch (maybe more than one bytecode, see later)
- xK = PATTERN (peep2_next_insn (N))
- if peep2_next_insn (N) == NULL_RTX goto ... else same as above
- xK = XVECEXP (xJ, 0, N)
- xK = XEXP (xJ, N)
- operands[K] = N (this is DT_accept_op
- at least three bytecodes for DT_accept_insn, depending on subroutine_type (see write_action in genrecog.c)
- one bytecode per predicate (not sure about this)

The moderately complex part of it should be:
- the switch statements, where it is mostly a matter of efficiently encoding them. Most of them have a handful of cases, but few have 20 or so.

- the labels, where genrecog can already associate each decision tree node with a C label. I guess you can do two compilation passes, one to linearize the tree, and one to put in the "virtual program counter" values and actually output the bytecoded description.

- DT_c_test: these are embedded C predicates. You can also have one bytecode per test there. Anyway, you're already going to write at least "part" of the virtual machine interpreter in your rewritten genrecog, if you have one bytecode per predicate. Luckily, if the host compiler is 3.0.1 or later, insn-conditions.c has most of the work already done! gensupport.c has this code

  int
  maybe_eval_c_test (const char *expr)
  {
    const struct c_test *test;
    struct c_test dummy;

    if (expr[0] == 0)
      return 1;

    if (insn_elision_unavailable)
      return -1;

    dummy.expr = expr;
    test = (const struct c_test *)htab_find (condition_table, &dummy);
    gcc_assert (test);

    return test->value;
  }

which gives this function

  int
  c_test_id (const char *expr)
  {
    const struct c_test *test;
    struct c_test dummy;

    if (expr[0] == 0)
      return -1;

    dummy.expr = expr;
    test = (const struct c_test *)htab_find (condition_table, &dummy);
    gcc_assert (test);
    return test - insn_conditions;
  }

With a GCC earlier than 3.0.1, dummy-conditions.c is used instead, but you can ditch this. You'll have to modify write_one_condition in genconditions.c, so that instead of

   { "! optimize_size && ! TARGET_READ_MODIFY",
     __builtin_constant_p (! optimize_size && ! TARGET_READ_MODIFY)
     ? (int) (! optimize_size && ! TARGET_READ_MODIFY)
     : -1) },

it outputs something like

   { "! optimize_size && ! TARGET_READ_MODIFY",
#if GCC_VERSION < 3001
     __builtin_constant_p (! optimize_size && ! TARGET_READ_MODIFY)
     ? (int) (! optimize_size && ! TARGET_READ_MODIFY) :
#endif
     -1) },

Similarly in write_conditions, instead of

   const int insn_elision_unavailable = 0;

you can output

#if GCC_VERSION < 3001
   const int insn_elision_unavailable = 1;
#else
   const int insn_elision_unavailable = 0;
#endif

I guess the only complicated part is really the switch statements.

Paolo

Reply via email to