home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / gcc-2.3.3-src.lha / GNU / src / amiga / gcc-2.3.3 / genrecog.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  53KB  |  1,782 lines

  1. /* Generate code from machine description to recognize rtl as insns.
  2.    Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU CC.
  5.  
  6. GNU CC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU CC is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU CC; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. /* This program is used to produce insn-recog.c, which contains
  22.    a function called `recog' plus its subroutines.
  23.    These functions contain a decision tree
  24.    that recognizes whether an rtx, the argument given to recog,
  25.    is a valid instruction.
  26.  
  27.    recog returns -1 if the rtx is not valid.
  28.    If the rtx is valid, recog returns a nonnegative number
  29.    which is the insn code number for the pattern that matched.
  30.    This is the same as the order in the machine description of the
  31.    entry that matched.  This number can be used as an index into various
  32.    insn_* tables, such as insn_template, insn_outfun, and insn_n_operands
  33.    (found in insn-output.c).
  34.  
  35.    The third argument to recog is an optional pointer to an int.
  36.    If present, recog will accept a pattern if it matches except for
  37.    missing CLOBBER expressions at the end.  In that case, the value
  38.    pointed to by the optional pointer will be set to the number of
  39.    CLOBBERs that need to be added (it should be initialized to zero by
  40.    the caller).  If it is set nonzero, the caller should allocate a
  41.    PARALLEL of the appropriate size, copy the initial entries, and call
  42.    add_clobbers (found in insn-emit.c) to fill in the CLOBBERs.
  43.  
  44.    This program also generates the function `split_insns',
  45.    which returns 0 if the rtl could not be split, or
  46.    it returns the split rtl in a SEQUENCE.  */
  47.  
  48. #include <stdio.h>
  49. #include "hconfig.h"
  50. #include "rtl.h"
  51. #include "obstack.h"
  52.  
  53. static struct obstack obstack;
  54. struct obstack *rtl_obstack = &obstack;
  55.  
  56. #define obstack_chunk_alloc xmalloc
  57. #define obstack_chunk_free free
  58.  
  59. extern void free ();
  60. extern rtx read_rtx ();
  61.  
  62. /* Data structure for a listhead of decision trees.  The alternatives
  63.    to a node are kept in a doublely-linked list so we can easily add nodes
  64.    to the proper place when merging.  */
  65.  
  66. struct decision_head { struct decision *first, *last; };
  67.  
  68. /* Data structure for decision tree for recognizing
  69.    legitimate instructions.  */
  70.  
  71. struct decision
  72. {
  73.   int number;            /* Node number, used for labels */
  74.   char *position;        /* String denoting position in pattern */
  75.   RTX_CODE code;        /* Code to test for or UNKNOWN to suppress */
  76.   char ignore_code;        /* If non-zero, need not test code */
  77.   char ignore_mode;        /* If non-zero, need not test mode */
  78.   int veclen;            /* Length of vector, if nonzero */
  79.   enum machine_mode mode;    /* Machine mode of node */
  80.   char enforce_mode;        /* If non-zero, test `mode' */
  81.   char retest_code, retest_mode; /* See write_tree_1 */
  82.   int test_elt_zero_int;    /* Nonzero if should test XINT (rtl, 0) */
  83.   int elt_zero_int;        /* Required value for XINT (rtl, 0) */
  84.   int test_elt_one_int;        /* Nonzero if should test XINT (rtl, 1) */
  85.   int elt_one_int;        /* Required value for XINT (rtl, 1) */
  86.   int test_elt_zero_wide;    /* Nonzero if should test XWINT (rtl, 0) */
  87.   HOST_WIDE_INT elt_zero_wide;    /* Required value for XWINT (rtl, 0) */
  88.   char *tests;            /* If nonzero predicate to call */
  89.   int pred;            /* `preds' index of predicate or -1 */
  90.   char *c_test;            /* Additional test to perform */
  91.   struct decision_head success;    /* Nodes to test on success */
  92.   int insn_code_number;        /* Insn number matched, if success */
  93.   int num_clobbers_to_add;    /* Number of CLOBBERs to be added to pattern */
  94.   struct decision *next;    /* Node to test on failure */
  95.   struct decision *prev;    /* Node whose failure tests us */
  96.   struct decision *afterward;    /* Node to test on success, but failure of
  97.                    successor nodes */
  98.   int opno;            /* Operand number, if >= 0 */
  99.   int dupno;            /* Number of operand to compare against */
  100.   int label_needed;        /* Nonzero if label needed when writing tree */
  101.   int subroutine_number;    /* Number of subroutine this node starts */
  102. };
  103.  
  104. #define SUBROUTINE_THRESHOLD 50
  105.  
  106. static int next_subroutine_number;
  107.  
  108. /* We can write two types of subroutines: One for insn recognition and
  109.    one to split insns.  This defines which type is being written.  */
  110.  
  111. enum routine_type {RECOG, SPLIT};
  112.  
  113. /* Next available node number for tree nodes.  */
  114.  
  115. static int next_number;
  116.  
  117. /* Next number to use as an insn_code.  */
  118.  
  119. static int next_insn_code;
  120.  
  121. /* Similar, but counts all expressions in the MD file; used for
  122.    error messages. */
  123.  
  124. static int next_index;
  125.  
  126. /* Record the highest depth we ever have so we know how many variables to
  127.    allocate in each subroutine we make.  */
  128.  
  129. static int max_depth;
  130.  
  131. /* This table contains a list of the rtl codes that can possibly match a
  132.    predicate defined in recog.c.  The function `not_both_true' uses it to
  133.    deduce that there are no expressions that can be matches by certain pairs
  134.    of tree nodes.  Also, if a predicate can match only one code, we can
  135.    hardwire that code into the node testing the predicate.  */
  136.  
  137. static struct pred_table
  138. {
  139.   char *name;
  140.   RTX_CODE codes[NUM_RTX_CODE];
  141. } preds[]
  142.   = {{"general_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
  143.               LABEL_REF, SUBREG, REG, MEM}},
  144. #ifdef PREDICATE_CODES
  145.      PREDICATE_CODES
  146. #endif
  147.      {"address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
  148.               LABEL_REF, SUBREG, REG, MEM, PLUS, MINUS, MULT}},
  149.      {"register_operand", {SUBREG, REG}},
  150.      {"scratch_operand", {SCRATCH, REG}},
  151.      {"immediate_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
  152.                 LABEL_REF}},
  153.      {"const_int_operand", {CONST_INT}},
  154.      {"const_double_operand", {CONST_INT, CONST_DOUBLE}},
  155.      {"nonimmediate_operand", {SUBREG, REG, MEM}},
  156.      {"nonmemory_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
  157.                 LABEL_REF, SUBREG, REG}},
  158.      {"push_operand", {MEM}},
  159.      {"memory_operand", {SUBREG, MEM}},
  160.      {"indirect_operand", {SUBREG, MEM}},
  161.      {"comparison_operation", {EQ, NE, LE, LT, GE, LT, LEU, LTU, GEU, GTU}},
  162.      {"mode_independent_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
  163.                    LABEL_REF, SUBREG, REG, MEM}}};
  164.  
  165. #define NUM_KNOWN_PREDS (sizeof preds / sizeof preds[0])
  166.  
  167. static int try_merge_1 ();
  168. static int no_same_mode ();
  169. static int same_codes ();
  170. static int same_modes ();
  171. char *xmalloc ();
  172. static struct decision *add_to_sequence ();
  173. static struct decision_head merge_trees ();
  174. static struct decision *try_merge_2 ();
  175. static void write_subroutine ();
  176. static void print_code ();
  177. static void clear_codes ();
  178. static void clear_modes ();
  179. static void change_state ();
  180. static void write_tree ();
  181. static char *copystr ();
  182. static char *concat ();
  183. static void fatal ();
  184. void fancy_abort ();
  185. static void mybzero ();
  186. static void mybcopy ();
  187.  
  188. /* Construct and return a sequence of decisions
  189.    that will recognize INSN.
  190.  
  191.    TYPE says what type of routine we are recognizing (RECOG or SPLIT).  */
  192.  
  193. static struct decision_head
  194. make_insn_sequence (insn, type)
  195.      rtx insn;
  196.      enum routine_type type;
  197. {
  198.   rtx x;
  199.   char *c_test = XSTR (insn, type == RECOG ? 2 : 1);
  200.   struct decision *last;
  201.   struct decision_head head;
  202.  
  203.   if (XVECLEN (insn, type == RECOG) == 1)
  204.     x = XVECEXP (insn, type == RECOG, 0);
  205.   else
  206.     {
  207.       x = rtx_alloc (PARALLEL);
  208.       XVEC (x, 0) = XVEC (insn, type == RECOG);
  209.       PUT_MODE (x, VOIDmode);
  210.     }
  211.  
  212.   last = add_to_sequence (x, &head, "");
  213.  
  214.   if (c_test[0])
  215.     last->c_test = c_test;
  216.   last->insn_code_number = next_insn_code;
  217.   last->num_clobbers_to_add = 0;
  218.  
  219.   /* If this is not a DEFINE_SPLIT and X is a PARALLEL, see if it ends with a
  220.      group of CLOBBERs of (hard) registers or MATCH_SCRATCHes.  If so, set up
  221.      to recognize the pattern with