home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / gcc / genconfig.c < prev    next >
C/C++ Source or Header  |  1995-06-15  |  9KB  |  357 lines

  1. /* Generate from machine description:
  2.  
  3.    - some #define configuration flags.
  4.    Copyright (C) 1987, 1991 Free Software Foundation, Inc.
  5.  
  6. This file is part of GNU CC.
  7.  
  8. GNU CC is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2, or (at your option)
  11. any later version.
  12.  
  13. GNU CC is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with GNU CC; see the file COPYING.  If not, write to
  20. the Free Software Foundation, 59 Temple Place - Suite 330,
  21. Boston, MA 02111-1307, USA.  */
  22.  
  23.  
  24. #include <stdio.h>
  25. #include "hconfig.h"
  26. #include "rtl.h"
  27. #include "obstack.h"
  28.  
  29. static struct obstack obstack;
  30. struct obstack *rtl_obstack = &obstack;
  31.  
  32. #define obstack_chunk_alloc xmalloc
  33. #define obstack_chunk_free free
  34.  
  35. extern void free ();
  36. extern rtx read_rtx ();
  37.  
  38. /* flags to determine output of machine description dependent #define's.  */
  39. static int max_recog_operands;  /* Largest operand number seen.  */
  40. static int max_dup_operands;    /* Largest number of match_dup in any insn.  */
  41. static int max_clobbers_per_insn;
  42. static int register_constraint_flag;
  43. static int have_cc0_flag;
  44. static int have_cmove_flag;
  45. static int have_lo_sum_flag;
  46.  
  47. /* Maximum number of insns seen in a split.  */
  48. static int max_insns_per_split = 1;
  49.  
  50. static int clobbers_seen_this_insn;
  51. static int dup_operands_seen_this_insn;
  52.  
  53. char *xmalloc ();
  54. static void fatal ();
  55. void fancy_abort ();
  56.  
  57. /* RECOG_P will be non-zero if this pattern was seen in a context where it will
  58.    be used to recognize, rather than just generate an insn. 
  59.  
  60.    NON_PC_SET_SRC will be non-zero if this pattern was seen in a SET_SRC
  61.    of a SET whose destination is not (pc).  */
  62.  
  63. static void
  64. walk_insn_part (part, recog_p, non_pc_set_src)
  65.      rtx part;
  66.      int recog_p;
  67.      int non_pc_set_src;
  68. {
  69.   register int i, j;
  70.   register RTX_CODE code;
  71.   register char *format_ptr;
  72.  
  73.   if (part == 0)
  74.     return;
  75.  
  76.   code = GET_CODE (part);
  77.   switch (code)
  78.     {
  79.     case CLOBBER:
  80.       clobbers_seen_this_insn++;
  81.       break;
  82.  
  83.     case MATCH_OPERAND:
  84.       if (XINT (part, 0) > max_recog_operands)
  85.     max_recog_operands = XINT (part, 0);
  86.       if (XSTR (part, 2) && *XSTR (part, 2))
  87.     register_constraint_flag = 1;
  88.       return;
  89.  
  90.     case MATCH_OP_DUP:
  91.     case MATCH_PAR_DUP:
  92.       ++dup_operands_seen_this_insn;
  93.     case MATCH_SCRATCH:
  94.     case MATCH_PARALLEL:
  95.     case MATCH_OPERATOR:
  96.       if (XINT (part, 0) > max_recog_operands)
  97.     max_recog_operands = XINT (part, 0);
  98.       /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or
  99.      MATCH_PARALLEL.  */
  100.       break;
  101.  
  102.     case LABEL_REF:
  103.       if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND)
  104.     break;
  105.       return;
  106.  
  107.     case MATCH_DUP:
  108.       ++dup_operands_seen_this_insn;
  109.       if (XINT (part, 0) > max_recog_operands)
  110.     max_recog_operands = XINT (part, 0);
  111.       return;
  112.  
  113.     case CC0:
  114.       if (recog_p)
  115.     have_cc0_flag = 1;
  116.       return;
  117.  
  118.     case LO_SUM:
  119.       if (recog_p)
  120.     have_lo_sum_flag = 1;
  121.       return;
  122.  
  123.     case SET:
  124.       walk_insn_part (SET_DEST (part), 0, recog_p);
  125.       walk_insn_part (SET_SRC (part), recog_p,
  126.               GET_CODE (SET_DEST (part)) != PC);
  127.       return;
  128.  
  129.     case IF_THEN_ELSE:
  130.       /* Only consider this machine as having a conditional move if the
  131.      two arms of the IF_THEN_ELSE are both MATCH_OPERAND.  Otherwise,
  132.      we have some specific IF_THEN_ELSE construct (like the doz
  133.      instruction on the RS/6000) that can't be used in the general
  134.      context we want it for.  */
  135.  
  136.       if (recog_p && non_pc_set_src
  137.       && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND
  138.       && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND)
  139.     have_cmove_flag = 1;
  140.       break;
  141.  
  142.     case REG: case CONST_INT: case SYMBOL_REF:
  143.     case PC:
  144.       return;
  145.     }
  146.  
  147.   format_ptr = GET_RTX_FORMAT (GET_CODE (part));
  148.  
  149.   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
  150.     switch (*format_ptr++)
  151.       {
  152.       case 'e':
  153.       case 'u':
  154.     walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src);
  155.     break;
  156.       case 'E':
  157.     if (XVEC (part, i) != NULL)
  158.       for (j = 0; j < XVECLEN (part, i); j++)
  159.         walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src);
  160.     break;
  161.       }
  162. }
  163.  
  164. static void
  165. gen_insn (insn)
  166.      rtx insn;
  167. {
  168.   int i;
  169.  
  170.   /* Walk the insn pattern to gather the #define's status.  */
  171.   clobbers_seen_this_insn = 0;
  172.   dup_operands_seen_this_insn = 0;
  173.   if (XVEC (insn, 1) != 0)
  174.     for (i = 0; i < XVECLEN (insn, 1); i++)
  175.       walk_insn_part (XVECEXP (insn, 1, i), 1, 0);
  176.  
  177.   if (clobbers_seen_this_insn > max_clobbers_per_insn)
  178.     max_clobbers_per_insn = clobbers_seen_this_insn;
  179.   if (dup_operands_seen_this_insn > max_dup_operands)
  180.     max_dup_operands = dup_operands_seen_this_insn;
  181. }
  182.  
  183. /* Similar but scan a define_expand.  */
  184.  
  185. static void
  186. gen_expand (insn)
  187.      rtx insn;
  188. {
  189.   int i;
  190.  
  191.   /* Walk the insn pattern to gather the #define's status.  */
  192.  
  193.   /* Note that we don't bother recording the number of MATCH_DUPs
  194.      that occur in a gen_expand, because only reload cares about that.  */
  195.   if (XVEC (insn, 1) != 0)
  196.     for (i = 0; i < XVECLEN (insn, 1); i++)
  197.       {
  198.     /* Compute the maximum SETs and CLOBBERS
  199.        in any one of the sub-insns;
  200.        don't sum across all of them.  */
  201.     clobbers_seen_this_insn = 0;
  202.  
  203.     walk_insn_part (XVECEXP (insn, 1, i), 0, 0);
  204.  
  205.     if (clobbers_seen_this_insn > max_clobbers_per_insn)
  206.       max_clobbers_per_insn = clobbers_seen_this_insn;
  207.       }
  208. }
  209.  
  210. /* Similar but scan a define_split.  */
  211.  
  212. static void
  213. gen_split (split)
  214.      rtx split;
  215. {
  216.   int i;
  217.  
  218.   /* Look through the patterns that are matched
  219.      to compute the maximum operand number.  */
  220.   for (i = 0; i < XVECLEN (split, 0); i++)
  221.     walk_insn_part (XVECEXP (split, 0, i), 1, 0);
  222.   /* Look at the number of insns this insn could split into.  */
  223.   if (XVECLEN (split, 2) > max_insns_per_split)
  224.     max_insns_per_split = XVECLEN (split, 2);
  225. }
  226.  
  227. static void
  228. gen_peephole (peep)
  229.      rtx peep;
  230. {
  231.   int i;
  232.  
  233.   /* Look through the patterns that are matched
  234.      to compute the maximum operand number.  */
  235.   for (i = 0; i < XVECLEN (peep, 0); i++)
  236.     walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
  237. }
  238.  
  239. char *
  240. xmalloc (size)
  241.      unsigned size;
  242. {
  243.   register char *val = (char *) malloc (size);
  244.  
  245.   if (val == 0)
  246.     fatal ("virtual memory exhausted");
  247.  
  248.   return val;
  249. }
  250.  
  251. char *
  252. xrealloc (ptr, size)
  253.      char *ptr;
  254.      unsigned size;
  255. {
  256.   char *result = (char *) realloc (ptr, size);
  257.   if (!result)
  258.     fatal ("virtual memory exhausted");
  259.   return result;
  260. }
  261.  
  262. static void
  263. fatal (s, a1, a2)
  264.      char *s;
  265. {
  266.   fprintf (stderr, "genconfig: ");
  267.   fprintf (stderr, s, a1, a2);
  268.   fprintf (stderr, "\n");
  269.   exit (FATAL_EXIT_CODE);
  270. }
  271.  
  272. /* More 'friendly' abort that prints the line and file.
  273.    config.h can #define abort fancy_abort if you like that sort of thing.  */
  274.  
  275. void
  276. fancy_abort ()
  277. {
  278.   fatal ("Internal gcc abort.");
  279. }
  280.  
  281. int
  282. main (argc, argv)
  283.      int argc;
  284.      char **argv;
  285. {
  286.   rtx desc;
  287.   FILE *infile;
  288.   register int c;
  289.  
  290.   obstack_init (rtl_obstack);
  291.  
  292.   if (argc <= 1)
  293.     fatal ("No input file name.");
  294.  
  295.   infile = fopen (argv[1], "r");
  296.   if (infile == 0)
  297.     {
  298.       perror (argv[1]);
  299.       exit (FATAL_EXIT_CODE);
  300.     }
  301.  
  302.   init_rtl ();
  303.  
  304.   printf ("/* Generated automatically by the program `genconfig'\n\
  305. from the machine description file `md'.  */\n\n");
  306.  
  307.   /* Allow at least 10 operands for the sake of asm constructs.  */
  308.   max_recog_operands = 9;  /* We will add 1 later.  */
  309.   max_dup_operands = 1;
  310.  
  311.   /* Read the machine description.  */
  312.  
  313.   while (1)
  314.     {
  315.       c = read_skip_spaces (infile);
  316.       if (c == EOF)
  317.     break;
  318.       ungetc (c, infile);
  319.  
  320.       desc = read_rtx (infile);
  321.       if (GET_CODE (desc) == DEFINE_INSN)
  322.     gen_insn (desc);
  323.       if (GET_CODE (desc) == DEFINE_EXPAND)
  324.     gen_expand (desc);
  325.       if (GET_CODE (desc) == DEFINE_SPLIT)
  326.     gen_split (desc);
  327.       if (GET_CODE (desc) == DEFINE_PEEPHOLE)
  328.     gen_peephole (desc);
  329.     }
  330.  
  331.   printf ("\n#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
  332.  
  333.   printf ("\n#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
  334.  
  335.   /* This is conditionally defined, in case the user writes code which emits
  336.      more splits than we can readily see (and knows s/he does it).  */
  337.   printf ("#ifndef MAX_INSNS_PER_SPLIT\n#define MAX_INSNS_PER_SPLIT %d\n#endif\n",
  338.       max_insns_per_split);
  339.  
  340.   if (register_constraint_flag)
  341.     printf ("#define REGISTER_CONSTRAINTS\n");
  342.  
  343.   if (have_cc0_flag)
  344.     printf ("#define HAVE_cc0\n");
  345.  
  346.   if (have_cmove_flag)
  347.     printf ("#define HAVE_conditional_move\n");
  348.  
  349.   if (have_lo_sum_flag)
  350.     printf ("#define HAVE_lo_sum\n");
  351.  
  352.   fflush (stdout);
  353.   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
  354.   /* NOTREACHED */
  355.   return 0;
  356. }
  357.