genconfig.c revision 18334
118334Speter/* Generate from machine description:
218334Speter
318334Speter   - some #define configuration flags.
418334Speter   Copyright (C) 1987, 1991 Free Software Foundation, Inc.
518334Speter
618334SpeterThis file is part of GNU CC.
718334Speter
818334SpeterGNU CC is free software; you can redistribute it and/or modify
918334Speterit under the terms of the GNU General Public License as published by
1018334Speterthe Free Software Foundation; either version 2, or (at your option)
1118334Speterany later version.
1218334Speter
1318334SpeterGNU CC is distributed in the hope that it will be useful,
1418334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1518334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1618334SpeterGNU General Public License for more details.
1718334Speter
1818334SpeterYou should have received a copy of the GNU General Public License
1918334Speteralong with GNU CC; see the file COPYING.  If not, write to
2018334Speterthe Free Software Foundation, 59 Temple Place - Suite 330,
2118334SpeterBoston, MA 02111-1307, USA.  */
2218334Speter
2318334Speter
2418334Speter#include <stdio.h>
2518334Speter#include "hconfig.h"
2618334Speter#include "rtl.h"
2718334Speter#include "obstack.h"
2818334Speter
2918334Speterstatic struct obstack obstack;
3018334Speterstruct obstack *rtl_obstack = &obstack;
3118334Speter
3218334Speter#define obstack_chunk_alloc xmalloc
3318334Speter#define obstack_chunk_free free
3418334Speter
3518334Speterextern void free ();
3618334Speterextern rtx read_rtx ();
3718334Speter
3818334Speter/* flags to determine output of machine description dependent #define's.  */
3918334Speterstatic int max_recog_operands;  /* Largest operand number seen.  */
4018334Speterstatic int max_dup_operands;    /* Largest number of match_dup in any insn.  */
4118334Speterstatic int max_clobbers_per_insn;
4218334Speterstatic int register_constraint_flag;
4318334Speterstatic int have_cc0_flag;
4418334Speterstatic int have_cmove_flag;
4518334Speterstatic int have_lo_sum_flag;
4618334Speter
4718334Speter/* Maximum number of insns seen in a split.  */
4818334Speterstatic int max_insns_per_split = 1;
4918334Speter
5018334Speterstatic int clobbers_seen_this_insn;
5118334Speterstatic int dup_operands_seen_this_insn;
5218334Speter
5318334Speterchar *xmalloc ();
5418334Speterstatic void fatal ();
5518334Spetervoid fancy_abort ();
5618334Speter
5718334Speter/* RECOG_P will be non-zero if this pattern was seen in a context where it will
5818334Speter   be used to recognize, rather than just generate an insn.
5918334Speter
6018334Speter   NON_PC_SET_SRC will be non-zero if this pattern was seen in a SET_SRC
6118334Speter   of a SET whose destination is not (pc).  */
6218334Speter
6318334Speterstatic void
6418334Speterwalk_insn_part (part, recog_p, non_pc_set_src)
6518334Speter     rtx part;
6618334Speter     int recog_p;
6718334Speter     int non_pc_set_src;
6818334Speter{
6918334Speter  register int i, j;
7018334Speter  register RTX_CODE code;
7118334Speter  register char *format_ptr;
7218334Speter
7318334Speter  if (part == 0)
7418334Speter    return;
7518334Speter
7618334Speter  code = GET_CODE (part);
7718334Speter  switch (code)
7818334Speter    {
7918334Speter    case CLOBBER:
8018334Speter      clobbers_seen_this_insn++;
8118334Speter      break;
8218334Speter
8318334Speter    case MATCH_OPERAND:
8418334Speter      if (XINT (part, 0) > max_recog_operands)
8518334Speter	max_recog_operands = XINT (part, 0);
8618334Speter      if (XSTR (part, 2) && *XSTR (part, 2))
8718334Speter	register_constraint_flag = 1;
8818334Speter      return;
8918334Speter
9018334Speter    case MATCH_OP_DUP:
9118334Speter    case MATCH_PAR_DUP:
9218334Speter      ++dup_operands_seen_this_insn;
9318334Speter    case MATCH_SCRATCH:
9418334Speter    case MATCH_PARALLEL:
9518334Speter    case MATCH_OPERATOR:
9618334Speter      if (XINT (part, 0) > max_recog_operands)
9718334Speter	max_recog_operands = XINT (part, 0);
9818334Speter      /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or
9918334Speter	 MATCH_PARALLEL.  */
10018334Speter      break;
10118334Speter
10218334Speter    case LABEL_REF:
10318334Speter      if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND)
10418334Speter	break;
10518334Speter      return;
10618334Speter
10718334Speter    case MATCH_DUP:
10818334Speter      ++dup_operands_seen_this_insn;
10918334Speter      if (XINT (part, 0) > max_recog_operands)
11018334Speter	max_recog_operands = XINT (part, 0);
11118334Speter      return;
11218334Speter
11318334Speter    case CC0:
11418334Speter      if (recog_p)
11518334Speter	have_cc0_flag = 1;
11618334Speter      return;
11718334Speter
11818334Speter    case LO_SUM:
11918334Speter      if (recog_p)
12018334Speter	have_lo_sum_flag = 1;
12118334Speter      return;
12218334Speter
12318334Speter    case SET:
12418334Speter      walk_insn_part (SET_DEST (part), 0, recog_p);
12518334Speter      walk_insn_part (SET_SRC (part), recog_p,
12618334Speter		      GET_CODE (SET_DEST (part)) != PC);
12718334Speter      return;
12818334Speter
12918334Speter    case IF_THEN_ELSE:
13018334Speter      /* Only consider this machine as having a conditional move if the
13118334Speter	 two arms of the IF_THEN_ELSE are both MATCH_OPERAND.  Otherwise,
13218334Speter	 we have some specific IF_THEN_ELSE construct (like the doz
13318334Speter	 instruction on the RS/6000) that can't be used in the general
13418334Speter	 context we want it for.  */
13518334Speter
13618334Speter      if (recog_p && non_pc_set_src
13718334Speter	  && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND
13818334Speter	  && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND)
13918334Speter	have_cmove_flag = 1;
14018334Speter      break;
14118334Speter
14218334Speter    case REG: case CONST_INT: case SYMBOL_REF:
14318334Speter    case PC:
14418334Speter      return;
14518334Speter    }
14618334Speter
14718334Speter  format_ptr = GET_RTX_FORMAT (GET_CODE (part));
14818334Speter
14918334Speter  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
15018334Speter    switch (*format_ptr++)
15118334Speter      {
15218334Speter      case 'e':
15318334Speter      case 'u':
15418334Speter	walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src);
15518334Speter	break;
15618334Speter      case 'E':
15718334Speter	if (XVEC (part, i) != NULL)
15818334Speter	  for (j = 0; j < XVECLEN (part, i); j++)
15918334Speter	    walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src);
16018334Speter	break;
16118334Speter      }
16218334Speter}
16318334Speter
16418334Speterstatic void
16518334Spetergen_insn (insn)
16618334Speter     rtx insn;
16718334Speter{
16818334Speter  int i;
16918334Speter
17018334Speter  /* Walk the insn pattern to gather the #define's status.  */
17118334Speter  clobbers_seen_this_insn = 0;
17218334Speter  dup_operands_seen_this_insn = 0;
17318334Speter  if (XVEC (insn, 1) != 0)
17418334Speter    for (i = 0; i < XVECLEN (insn, 1); i++)
17518334Speter      walk_insn_part (XVECEXP (insn, 1, i), 1, 0);
17618334Speter
17718334Speter  if (clobbers_seen_this_insn > max_clobbers_per_insn)
17818334Speter    max_clobbers_per_insn = clobbers_seen_this_insn;
17918334Speter  if (dup_operands_seen_this_insn > max_dup_operands)
18018334Speter    max_dup_operands = dup_operands_seen_this_insn;
18118334Speter}
18218334Speter
18318334Speter/* Similar but scan a define_expand.  */
18418334Speter
18518334Speterstatic void
18618334Spetergen_expand (insn)
18718334Speter     rtx insn;
18818334Speter{
18918334Speter  int i;
19018334Speter
19118334Speter  /* Walk the insn pattern to gather the #define's status.  */
19218334Speter
19318334Speter  /* Note that we don't bother recording the number of MATCH_DUPs
19418334Speter     that occur in a gen_expand, because only reload cares about that.  */
19518334Speter  if (XVEC (insn, 1) != 0)
19618334Speter    for (i = 0; i < XVECLEN (insn, 1); i++)
19718334Speter      {
19818334Speter	/* Compute the maximum SETs and CLOBBERS
19918334Speter	   in any one of the sub-insns;
20018334Speter	   don't sum across all of them.  */
20118334Speter	clobbers_seen_this_insn = 0;
20218334Speter
20318334Speter	walk_insn_part (XVECEXP (insn, 1, i), 0, 0);
20418334Speter
20518334Speter	if (clobbers_seen_this_insn > max_clobbers_per_insn)
20618334Speter	  max_clobbers_per_insn = clobbers_seen_this_insn;
20718334Speter      }
20818334Speter}
20918334Speter
21018334Speter/* Similar but scan a define_split.  */
21118334Speter
21218334Speterstatic void
21318334Spetergen_split (split)
21418334Speter     rtx split;
21518334Speter{
21618334Speter  int i;
21718334Speter
21818334Speter  /* Look through the patterns that are matched
21918334Speter     to compute the maximum operand number.  */
22018334Speter  for (i = 0; i < XVECLEN (split, 0); i++)
22118334Speter    walk_insn_part (XVECEXP (split, 0, i), 1, 0);
22218334Speter  /* Look at the number of insns this insn could split into.  */
22318334Speter  if (XVECLEN (split, 2) > max_insns_per_split)
22418334Speter    max_insns_per_split = XVECLEN (split, 2);
22518334Speter}
22618334Speter
22718334Speterstatic void
22818334Spetergen_peephole (peep)
22918334Speter     rtx peep;
23018334Speter{
23118334Speter  int i;
23218334Speter
23318334Speter  /* Look through the patterns that are matched
23418334Speter     to compute the maximum operand number.  */
23518334Speter  for (i = 0; i < XVECLEN (peep, 0); i++)
23618334Speter    walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
23718334Speter}
23818334Speter
23918334Speterchar *
24018334Speterxmalloc (size)
24118334Speter     unsigned size;
24218334Speter{
24318334Speter  register char *val = (char *) malloc (size);
24418334Speter
24518334Speter  if (val == 0)
24618334Speter    fatal ("virtual memory exhausted");
24718334Speter
24818334Speter  return val;
24918334Speter}
25018334Speter
25118334Speterchar *
25218334Speterxrealloc (ptr, size)
25318334Speter     char *ptr;
25418334Speter     unsigned size;
25518334Speter{
25618334Speter  char *result = (char *) realloc (ptr, size);
25718334Speter  if (!result)
25818334Speter    fatal ("virtual memory exhausted");
25918334Speter  return result;
26018334Speter}
26118334Speter
26218334Speterstatic void
26318334Speterfatal (s, a1, a2)
26418334Speter     char *s;
26518334Speter{
26618334Speter  fprintf (stderr, "genconfig: ");
26718334Speter  fprintf (stderr, s, a1, a2);
26818334Speter  fprintf (stderr, "\n");
26918334Speter  exit (FATAL_EXIT_CODE);
27018334Speter}
27118334Speter
27218334Speter/* More 'friendly' abort that prints the line and file.
27318334Speter   config.h can #define abort fancy_abort if you like that sort of thing.  */
27418334Speter
27518334Spetervoid
27618334Speterfancy_abort ()
27718334Speter{
27818334Speter  fatal ("Internal gcc abort.");
27918334Speter}
28018334Speter
28118334Speterint
28218334Spetermain (argc, argv)
28318334Speter     int argc;
28418334Speter     char **argv;
28518334Speter{
28618334Speter  rtx desc;
28718334Speter  FILE *infile;
28818334Speter  register int c;
28918334Speter
29018334Speter  obstack_init (rtl_obstack);
29118334Speter
29218334Speter  if (argc <= 1)
29318334Speter    fatal ("No input file name.");
29418334Speter
29518334Speter  infile = fopen (argv[1], "r");
29618334Speter  if (infile == 0)
29718334Speter    {
29818334Speter      perror (argv[1]);
29918334Speter      exit (FATAL_EXIT_CODE);
30018334Speter    }
30118334Speter
30218334Speter  init_rtl ();
30318334Speter
30418334Speter  printf ("/* Generated automatically by the program `genconfig'\n\
30518334Speterfrom the machine description file `md'.  */\n\n");
30618334Speter
30718334Speter  /* Allow at least 10 operands for the sake of asm constructs.  */
30818334Speter  max_recog_operands = 9;  /* We will add 1 later.  */
30918334Speter  max_dup_operands = 1;
31018334Speter
31118334Speter  /* Read the machine description.  */
31218334Speter
31318334Speter  while (1)
31418334Speter    {
31518334Speter      c = read_skip_spaces (infile);
31618334Speter      if (c == EOF)
31718334Speter	break;
31818334Speter      ungetc (c, infile);
31918334Speter
32018334Speter      desc = read_rtx (infile);
32118334Speter      if (GET_CODE (desc) == DEFINE_INSN)
32218334Speter	gen_insn (desc);
32318334Speter      if (GET_CODE (desc) == DEFINE_EXPAND)
32418334Speter	gen_expand (desc);
32518334Speter      if (GET_CODE (desc) == DEFINE_SPLIT)
32618334Speter	gen_split (desc);
32718334Speter      if (GET_CODE (desc) == DEFINE_PEEPHOLE)
32818334Speter	gen_peephole (desc);
32918334Speter    }
33018334Speter
33118334Speter  printf ("\n#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
33218334Speter
33318334Speter  printf ("\n#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
33418334Speter
33518334Speter  /* This is conditionally defined, in case the user writes code which emits
33618334Speter     more splits than we can readily see (and knows s/he does it).  */
33718334Speter  printf ("#ifndef MAX_INSNS_PER_SPLIT\n#define MAX_INSNS_PER_SPLIT %d\n#endif\n",
33818334Speter	  max_insns_per_split);
33918334Speter
34018334Speter  if (register_constraint_flag)
34118334Speter    printf ("#define REGISTER_CONSTRAINTS\n");
34218334Speter
34318334Speter  if (have_cc0_flag)
34418334Speter    printf ("#define HAVE_cc0\n");
34518334Speter
34618334Speter  if (have_cmove_flag)
34718334Speter    printf ("#define HAVE_conditional_move\n");
34818334Speter
34918334Speter  if (have_lo_sum_flag)
35018334Speter    printf ("#define HAVE_lo_sum\n");
35118334Speter
35218334Speter  fflush (stdout);
35318334Speter  exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
35418334Speter  /* NOTREACHED */
35518334Speter  return 0;
35618334Speter}
357