read rtx from .md file & gencodes

;; example .md file "ss.md" from SimpleScalar
;; ………………..
;;
;;    ADDITION
;;
;; ………………..
;;

(define_insn "adddf3"
[(set (match_operand:DF 0 "register_operand" "=f")
    (plus:DF (match_operand:DF 1 "register_operand" "f")
        (match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
"add.d\t%0,%1,%2"
[(set_attr "type"    "fadd")
   (set_attr "mode"    "DF")
   (set_attr "length"    "1")])

(define_insn "addsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
    (plus:SF (match_operand:SF 1 "register_operand" "f")
        (match_operand:SF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
"add.s\t%0,%1,%2"
[(set_attr "type"    "fadd")
   (set_attr "mode"    "SF")
   (set_attr "length"    "1")])
……




/ part of rtl.def /
/ Expression definitions and descriptions for all targets are in this file.
   Some will not be used for some targets.

   The fields in the cpp macro call "DEF_RTL_EXPR()"
   are used to create declarations in the C source of the compiler.

   The fields are:

   1. The internal name of the rtx used in the C source.
   It is a tag in the enumeration "enum rtx_code" defined in "rtl.h".
   By convention these are in UPPER_CASE.

   2. The name of the rtx in the external ASCII format read by
   read_rtx(), and printed by print_rtx().
   These names are stored in rtx_name[].
   By convention these are the internal (field 1) names in lower_case.

   3. The print format, and type of each rtx->fld[] (field) in this rtx.
   These formats are stored in rtx_format[].
   The meaning of the formats is documented in front of this array in rtl.c
  
   4. The class of the rtx. These are stored in rtx_class and are accessed
   via the GET_RTX_CLASS macro. They are defined as follows:

     "o" an rtx code that can be used to represent an object (e.g, REG, MEM)
     "<" an rtx code for a comparison (e.g, EQ, NE, LT)
     "1" an rtx code for a unary arithmetic expression (e.g, NEG, NOT)
     "c" an rtx code for a commutative binary operation (e.g,, PLUS, MULT)
     "3" an rtx code for a non-bitfield three input operation (IF_THEN_ELSE)
     "2" an rtx code for a non-commutative binary operation (e.g., MINUS, DIV)
     "b" an rtx code for a bit-field operation (ZERO_EXTRACT, SIGN_EXTRACT)
     "i" an rtx code for a machine insn (INSN, JUMP_INSN, CALL_INSN)
     "m" an rtx code for something that matches in insns (e.g, MATCH_DUP)
     "x" everything else
    
  
/

/ ———————————————————————
   Expressions (and "meta" expressions) used for structuring the
   rtl representation of a program.
   ———————————————————————
/

/ an expression code name unknown to the reader /
DEF_RTL_EXPR(UNKNOWN, "UnKnown", "", ‘x’)

/
(NIL) is used by rtl reader and printer to represent a null pointer. /

DEF_RTL_EXPR(NIL, "nil", "
", ‘x’)

/ ———————————————————————
   Expressions used in constructing lists.
   ———————————————————————
/

/ a linked list of expressions /
DEF_RTL_EXPR(EXPR_LIST, "expr_list", "ee", ‘x’)

/ a linked list of instructions.
   The insns are represented in print by their uids.
/
DEF_RTL_EXPR(INSN_LIST, "insn_list", "ue", ‘x’)

/ ———————————————————————-
   Expression types for machine descriptions.
   These do not appear in actual rtl code in the compiler.
   ———————————————————————-
/

/ Appears only in machine descriptions.
   Means use the function named by the second arg (the string)
   as a predicate; if matched, store the structure that was matched
   in the operand table at index specified by the first arg (the integer).
   If the second arg is the null string, the structure is just stored.

   A third string argument indicates to the register allocator restrictions
   on where the operand can be allocated.

   If the target needs no restriction on any instruction this field should
   be the null string.

   The string is prepended by:
   ‘=’ to indicate the operand is only written to.
   ‘+’ to indicate the operand is both read and written to.

   Each character in the string represents an allocatable class for an operand.
   ‘g’ indicates the operand can be any valid class.
   ‘i’ indicates the operand can be immediate (in the instruction) data.
   ‘r’ indicates the operand can be in a register.
   ‘m’ indicates the operand can be in memory.
   ‘o’ a subset of the ‘m’ class. Those memory addressing modes that
       can be offset at compile time (have a constant added to them).

   Other characters indicate target dependent operand classes and
   are described in each target’s machine description.

   For instructions with more than one operand, sets of classes can be
   separated by a comma to indicate the appropriate multi-operand constraints.
   There must be a 1 to 1 correspondence between these sets of classes in
   all operands for an instruction.
  
/
DEF_RTL_EXPR(MATCH_OPERAND, "match_operand", "iss", ‘m’)

/ Appears only in machine descriptions.
   Means match a SCRATCH or a register. When used to generate rtl, a
   SCRATCH is generated. As for MATCH_OPERAND, the mode specifies
   the desired mode and the first argument is the operand number.
   The second argument is the constraint.
/
DEF_RTL_EXPR(MATCH_SCRATCH, "match_scratch", "is", ‘m’)

/ Appears only in machine descriptions.
   Means match only something equal to what is stored in the operand table
   at the index specified by the argument.
/
DEF_RTL_EXPR(MATCH_DUP, "match_dup", "i", ‘m’)

/ Appears only in machine descriptions.
   Means apply a predicate, AND match recursively the operands of the rtx.
   Operand 0 is the operand-number, as in match_operand.
   Operand 1 is a predicate to apply (as a string, a function name).
   Operand 2 is a vector of expressions, each of which must match
   one subexpression of the rtx this construct is matching.
/
DEF_RTL_EXPR(MATCH_OPERATOR, "match_operator", "isE", ‘m’)

/ Appears only in machine descriptions.
   Means to match a PARALLEL of arbitrary length. The predicate is applied
   to the PARALLEL and the initial expressions in the PARALLEL are matched.
   Operand 0 is the operand-number, as in match_operand.
   Operand 1 is a predicate to apply to the PARALLEL.
   Operand 2 is a vector of expressions, each of which must match the
   corresponding element in the PARALLEL.
/
DEF_RTL_EXPR(MATCH_PARALLEL, "match_parallel", "isE", ‘m’)

/ Appears only in machine descriptions.
   Means match only something equal to what is stored in the operand table
   at the index specified by the argument. For MATCH_OPERATOR.
/
DEF_RTL_EXPR(MATCH_OP_DUP, "match_op_dup", "iE", ‘m’)

/ Appears only in machine descriptions.
   Means match only something equal to what is stored in the operand table
   at the index specified by the argument. For MATCH_PARALLEL.
/
DEF_RTL_EXPR(MATCH_PAR_DUP, "match_par_dup", "iE", ‘m’)

/ Appears only in machine descriptions.
   Defines the pattern for one kind of instruction.
   Operand:
   0: names this instruction.
      If the name is the null string, the instruction is in the
      machine description just to be recognized, and will never be emitted by
      the tree to rtl expander.
   1: is the pattern.
   2: is a string which is a C expression
      giving an additional condition for recognizing this pattern.
      A null string means no extra condition.
   3: is the action to execute if this pattern is matched.
      If this assembler code template starts with a
then it is a fragment of
      C code to run to decide on a template to use. Otherwise, it is the
      template to use.
   4: optionally, a vector of attributes for this insn.
     /
DEF_RTL_EXPR(DEFINE_INSN, "define_insn", "sEssV", ‘x’)
……





/
gcc-2.7.2.3/rtl.c
gencodes.c:main() > rtl.c:read_rtx()
/
/

   "" undefined.
         can cause a warning message
     "0" field is unused (or used in a phase-dependent manner)
         prints nothing
     "i" an integer
         prints the integer
     "n" like "i", but prints entries from `note_insn_name’
     "w" an integer of width HOST_BITS_PER_WIDE_INT
         prints the integer
     "s" a pointer to a string
         prints the string
     "S" like "s", but optional:
    the containing rtx may end before this operand
     "e" a pointer to an rtl expression
         prints the expression
     "E" a pointer to a vector that points to a number of rtl expressions
         prints a list of the rtl expressions
     "V" like "E", but optional:
    the containing rtx may end before this operand
     "u" a pointer to another insn
         prints the uid of the insn.
/
……
/ Read an rtx in printed representation from INFILE
   and return an actual rtx in core constructed accordingly.
   read_rtx is not used in the compiler proper, but rather in
   the utilities gen
.c that construct C code from machine descriptions. /

rtx
read_rtx (infile)
     FILE
infile;
{
register int i, j, list_counter;
RTX_CODE tmp_code;
register char format_ptr;
/
tmp_char is a buffer used for reading decimal integers
     and names of rtx types and machine modes.
     Therefore, 256 must be enough. /
char tmp_char[256];
rtx return_rtx;
register int c;
int tmp_int;
HOST_WIDE_INT tmp_wide;

/
Linked list structure for making RTXs: /
struct rtx_list
    {
      struct rtx_list
next;
      rtx value;        / Value of this node…        /
    };

c = read_skip_spaces (infile); / Should be open paren. /
if (c != ‘(‘)
    dump_and_abort (‘(‘, c, infile);

read_name (tmp_char, infile);

tmp_code = UNKNOWN;

for (i=0; i < NUM_RTX_CODE; i++) / @@ might speed this search up /
    {
      if (!(strcmp (tmp_char, GET_RTX_NAME (i))))
    {
    tmp_code = (RTX_CODE) i;    / get value for name /
    break;
    }
    }
if (tmp_code == UNKNOWN)
    {
      fprintf (stderr,
           "Unknown rtx read in rtl.read_rtx(). Code name was %s .",
           tmp_char);
    }
/ (NIL) stands for an expression that isn’t there. /
if (tmp_code == NIL)
    {
      / Discard the closeparen. /
      while ((c = getc (infile)) && c != ‘)’);
      return 0;
    }

return_rtx = rtx_alloc (tmp_code); / if we end up with an insn expression
                       then we free this space below.
/
format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));

/ If what follows is `: mode ‘, read it and
     store the mode in the rtx.
/

i = read_skip_spaces (infile);
if (i == ‘:’)
    {
      register int k;
      read_name (tmp_char, infile);
      for (k = 0; k < NUM_MACHINE_MODES; k++)
    if (!strcmp (GET_MODE_NAME (k), tmp_char))
    break;

      PUT_MODE (return_rtx, (enum machine_mode) k );
    }
else
    ungetc (i, infile);

for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
    switch (format_ptr++)
      {
    /
0 means a field for internal use only.
       Don’t expect it to be present in the input. /
      case ‘0’:
    break;

      case ‘e’:
      case ‘u’:
    XEXP (return_rtx, i) = read_rtx (infile);
    break;

      case ‘V’:
    /
‘V’ is an optional vector: if a closeparen follows,
       just store NULL for this element. /
    c = read_skip_spaces (infile);
    ungetc (c, infile);
    if (c == ‘)’)
    {
        XVEC (return_rtx, i) = 0;
        break;
     }
    /
Now process the vector. /

      case ‘E’:
    {
    register struct rtx_list
next_rtx, rtx_list_link;
    struct rtx_list
list_rtx;

    c = read_skip_spaces (infile);
    if (c != ‘[‘)
        dump_and_abort (‘[‘, c, infile);

    / add expressions to a list, while keeping a count /
    next_rtx = NULL;
    list_counter = 0;
    while ((c = read_skip_spaces (infile)) && c != ‘]’)
        {
          ungetc (c, infile);
          list_counter++;
          rtx_list_link = (struct rtx_list )
        alloca (sizeof (struct rtx_list));
          rtx_list_link->value = read_rtx (infile);
          if (next_rtx == 0)
        list_rtx = rtx_list_link;
          else
        next_rtx->next = rtx_list_link;
          next_rtx = rtx_list_link;
          rtx_list_link->next = 0;
        }
    /
get vector length and allocate it /
    XVEC (return_rtx, i) = (list_counter
                ? rtvec_alloc (list_counter) : NULL_RTVEC);
    if (list_counter > 0)
        {
          next_rtx = list_rtx;
          for (j = 0; j < list_counter; j++,
           next_rtx = next_rtx->next)
        XVECEXP (return_rtx, i, j) = next_rtx->value;
        }
    /
close bracket gotten /
    }
    break;

      case ‘S’:
    /
‘S’ is an optional string: if a closeparen follows,
       just store NULL for this element. /
    c = read_skip_spaces (infile);
    ungetc (c, infile);
    if (c == ‘)’)
    {
        XSTR (return_rtx, i) = 0;
        break;
    }

      case ‘s’:
    {
    int saw_paren = 0;
    register char
stringbuf;

    c = read_skip_spaces (infile);
    if (c == ‘(‘)
        {
          saw_paren = 1;
          c = read_skip_spaces (infile);
        }
    if (c != ‘"’)
        dump_and_abort (‘"’, c, infile);

    while (1)
        {
          c = getc (infile); / Read the string /
          if (c == ‘\’)
        {
        c = getc (infile);    / Read the string /
        / ; makes stuff for a C string constant containing
             newline and tab.
/
        if (c == ‘;’)
            {
              obstack_grow (rtl_obstack, "\n\t", 4);
              continue;
            }
        }
          else if (c == ‘"’)
        break;

          obstack_1grow (rtl_obstack, c);
        }

    obstack_1grow (rtl_obstack, 0);
    stringbuf = (char ) obstack_finish (rtl_obstack);

    if (saw_paren)
        {
          c = read_skip_spaces (infile);
          if (c != ‘)’)
        dump_and_abort (‘)’, c, infile);
        }
    XSTR (return_rtx, i) = stringbuf;
    }
    break;

      case ‘w’:
    read_name (tmp_char, infile);
#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
    tmp_wide = atoi (tmp_char);
#else
    tmp_wide = atol (tmp_char);
#endif
    XWINT (return_rtx, i) = tmp_wide;
    break;

      case ‘i’:
      case ‘n’:
    read_name (tmp_char, infile);
    tmp_int = atoi (tmp_char);
    XINT (return_rtx, i) = tmp_int;
    break;

      default:
    fprintf (stderr,
        "switch format wrong in rtl.read_rtx(). format was: %c.n",
        format_ptr[-1]);
    fprintf (stderr, "tfile position: %ldn", ftell (infile));
    abort ();
      }

c = read_skip_spaces (infile);
if (c != ‘)’)
    dump_and_abort (‘)’, c, infile);

return return_rtx;
}
……





/

    insn-codes.h
/
/
Generated automatically by the program gencodes'<br />from the machine description filemd’. /

#ifndef MAX_INSN_CODE

enum insn_code {
CODE_FOR_adddf3 = 0,
CODE_FOR_addsf3 = 1,
CODE_FOR_addsi3 = 2,
CODE_FOR_addsi3_internal = 3,
CODE_FOR_adddi3 = 4,
CODE_FOR_adddi3_internal_1 = 5,
CODE_FOR_adddi3_internal_2 = 8,
CODE_FOR_subdf3 = 11,
CODE_FOR_subsf3 = 12,
CODE_FOR_subsi3 = 13,
CODE_FOR_subsi3_internal = 14,
CODE_FOR_subdi3 = 15,
CODE_FOR_subdi3_internal = 16,
CODE_FOR_subdi3_internal_2 = 19,
CODE_FOR_muldf3 = 22,
CODE_FOR_mulsf3 = 23,
CODE_FOR_mulsi3 = 24,
CODE_FOR_mulsi3_internal = 26,
CODE_FOR_mulsidi3 = 27,
CODE_FOR_umulsidi3 = 28,
CODE_FOR_divdf3 = 29,
CODE_FOR_divsf3 = 30,
CODE_FOR_divmodsi4 = 31,
CODE_FOR_udivmodsi4 = 32,
CODE_FOR_divsi3 = 33,
CODE_FOR_modsi3 = 34,
CODE_FOR_udivsi3 = 35,
CODE_FOR_umodsi3 = 36,
CODE_FOR_sqrtdf2 = 37,
CODE_FOR_sqrtsf2 = 38,
CODE_FOR_abssi2 = 39,
CODE_FOR_absdf2 = 40,
CODE_FOR_abssf2 = 41,
CODE_FOR_ffssi2 = 42,
CODE_FOR_negsi2 = 43,
CODE_FOR_negdi2 = 44,
CODE_FOR_negdi2_internal = 45,
CODE_FOR_negdf2 = 46,
CODE_FOR_negsf2 = 47,
CODE_FOR_one_cmplsi2 = 48,
CODE_FOR_one_cmpldi2 = 49,
CODE_FOR_norsi3 = 51,
CODE_FOR_nordi3 = 52,
CODE_FOR_andsi3 = 54,
CODE_FOR_anddi3 = 55,
CODE_FOR_iorsi3 = 57,
CODE_FOR_iordi3 = 58,
CODE_FOR_xorsi3 = 60,
CODE_FOR_xordi3 = 61,
CODE_FOR_truncdfsf2 = 63,
CODE_FOR_zero_extendhisi2 = 64,
CODE_FOR_zero_extendqihi2 = 65,
CODE_FOR_zero_extendqisi2 = 66,
CODE_FOR_extendhisi2 = 67,
CODE_FOR_extendhisi2_internal = 68,
CODE_FOR_extendqihi2 = 69,
CODE_FOR_extendqihi2_internal = 70,
CODE_FOR_extendqisi2 = 71,
CODE_FOR_extendqisi2_insn = 72,
CODE_FOR_extendsfdf2 = 73,
CODE_FOR_fix_truncdfsi2 = 74,
CODE_FOR_fix_truncsfsi2 = 75,
CODE_FOR_floatsidf2 = 76,
CODE_FOR_floatsisf2 = 77,
CODE_FOR_fixuns_truncdfsi2 = 78,
CODE_FOR_fixuns_truncsfsi2 = 79,
CODE_FOR_movsi_unaligned = 80,
CODE_FOR_movsi_ulw = 81,
CODE_FOR_movsi_usw = 82,
CODE_FOR_movdi = 83,
CODE_FOR_movdi_internal = 84,
CODE_FOR_movsi = 87,
CODE_FOR_movsi_internal1 = 88,
CODE_FOR_movsi_internal2 = 89,
CODE_FOR_movhi = 90,
CODE_FOR_movhi_internal1 = 91,
CODE_FOR_movhi_internal2 = 92,
CODE_FOR_movqi = 93,
CODE_FOR_movqi_internal1 = 94,
CODE_FOR_movqi_internal2 = 95,
CODE_FOR_movsf = 96,
CODE_FOR_movsf_internal1 = 97,
CODE_FOR_movsf_internal2 = 98,
CODE_FOR_movdf = 99,
CODE_FOR_movdf_internal1 = 100,
CODE_FOR_movdf_internal2 = 101,
CODE_FOR_movstrsi = 103,
CODE_FOR_movstrsi_internal = 104,
CODE_FOR_movstrsi_internal2 = 106,
CODE_FOR_movstrsi_internal3 = 107,
CODE_FOR_ashlsi3 = 108,
CODE_FOR_ashldi3 = 109,
CODE_FOR_ashldi3_internal = 110,
CODE_FOR_ashldi3_internal2 = 111,
CODE_FOR_ashldi3_internal3 = 114,
CODE_FOR_ashrsi3 = 117,
CODE_FOR_ashrdi3 = 118,
CODE_FOR_ashrdi3_internal = 119,
CODE_FOR_ashrdi3_internal2 = 120,
CODE_FOR_ashrdi3_internal3 = 123,
CODE_FOR_lshrsi3 = 126,
CODE_FOR_lshrdi3 = 127,
CODE_FOR_lshrdi3_internal = 128,
CODE_FOR_lshrdi3_internal2 = 129,
CODE_FOR_lshrdi3_internal3 = 132,
CODE_FOR_cmpsi = 135,
CODE_FOR_tstsi = 136,
CODE_FOR_cmpdf = 137,
CODE_FOR_cmpsf = 138,
CODE_FOR_branch_fp_ne = 139,
CODE_FOR_branch_fp_ne_rev = 140,
CODE_FOR_branch_fp_eq = 141,
CODE_FOR_branch_fp_eq_rev = 142,
CODE_FOR_branch_zero = 143,
CODE_FOR_branch_equality = 144,
CODE_FOR_beq = 145,
CODE_FOR_bne = 146,
CODE_FOR_bgt = 147,
CODE_FOR_bge = 148,
CODE_FOR_blt = 149,
CODE_FOR_ble = 150,
CODE_FOR_bgtu = 151,
CODE_FOR_bgeu = 152,
CODE_FOR_bltu = 153,
CODE_FOR_bleu = 154,
CODE_FOR_seq = 155,
CODE_FOR_seq_si_zero = 156,
CODE_FOR_seq_si = 157,
CODE_FOR_sne = 159,
CODE_FOR_sne_si_zero = 160,
CODE_FOR_sne_si = 161,
CODE_FOR_sgt = 163,
CODE_FOR_sgt_si = 164,
CODE_FOR_sge = 165,
CODE_FOR_sge_si = 166,
CODE_FOR_slt = 168,
CODE_FOR_slt_si = 169,
CODE_FOR_sle = 170,
CODE_FOR_sle_si_const = 171,
CODE_FOR_sle_si_reg = 172,
CODE_FOR_sgtu = 174,
CODE_FOR_sgtu_si = 175,
CODE_FOR_sgeu = 176,
CODE_FOR_sgeu_si = 177,
CODE_FOR_sltu = 179,
CODE_FOR_sltu_si = 180,
CODE_FOR_sleu = 181,
CODE_FOR_sleu_si_const = 182,
CODE_FOR_sleu_si_reg = 183,
CODE_FOR_seq_df = 185,
CODE_FOR_sne_df = 186,
CODE_FOR_slt_df = 187,
CODE_FOR_sle_df = 188,
CODE_FOR_sgt_df = 189,
CODE_FOR_sge_df = 190,
CODE_FOR_seq_sf = 191,
CODE_FOR_sne_sf = 192,
CODE_FOR_slt_sf = 193,
CODE_FOR_sle_sf = 194,
CODE_FOR_sgt_sf = 195,
CODE_FOR_sge_sf = 196,
CODE_FOR_jump = 197,
CODE_FOR_indirect_jump = 198,
CODE_FOR_tablejump = 199,
CODE_FOR_return = 200,
CODE_FOR_return_internal = 201,
CODE_FOR_prologue = 202,
CODE_FOR_blockage = 203,
CODE_FOR_call = 204,
CODE_FOR_call_internal1 = 205,
CODE_FOR_call_internal2 = 206,
CODE_FOR_call_internal3 = 207,
CODE_FOR_call_internal4 = 208,
CODE_FOR_call_value = 209,
CODE_FOR_call_value_internal1 = 210,
CODE_FOR_call_value_internal2 = 211,
CODE_FOR_call_value_internal3 = 212,
CODE_FOR_call_value_internal4 = 213,
CODE_FOR_untyped_call = 214,
CODE_FOR_nop = 215,
CODE_FOR_probe = 216,
CODE_FOR_nothing };

#define MAX_INSN_CODE ((int) CODE_FOR_nothing)
#endif /
MAX_INSN_CODE */