genflags.c 5.56 KB
Newer Older
Tom Wood committed
1 2 3
/* Generate from machine description:
   - some flags HAVE_... saying which simple standard instructions are
   available for this machine.
4
   Copyright (C) 1987-2016 Free Software Foundation, Inc.
Tom Wood committed
5

6
This file is part of GCC.
Tom Wood committed
7

8 9
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
10
Software Foundation; either version 3, or (at your option) any later
11
version.
Tom Wood committed
12

13 14 15 16
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
Tom Wood committed
17 18

You should have received a copy of the GNU General Public License
19 20
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
Tom Wood committed
21 22


23
#include "bconfig.h"
24
#include "system.h"
25 26
#include "coretypes.h"
#include "tm.h"
Tom Wood committed
27 28
#include "rtl.h"
#include "obstack.h"
Zack Weinberg committed
29
#include "errors.h"
30
#include "read-md.h"
Clinton Popetz committed
31
#include "gensupport.h"
Tom Wood committed
32

33 34
/* Obstack to remember insns with.  */
static struct obstack obstack;
35 36 37 38

/* Max size of names encountered.  */
static int max_id_len;

39 40
/* Max operand encountered in a scan over some insn.  */
static int max_opno;
41

42 43 44
static void max_operand_1 (rtx);
static int num_operands (rtx);
static void gen_proto (rtx);
45

46
/* Count the number of match_operand's found.  */
Mike Stump committed
47

48
static void
49
max_operand_1 (rtx x)
50
{
51 52 53 54
  RTX_CODE code;
  int i;
  int len;
  const char *fmt;
55

56 57
  if (x == 0)
    return;
58

59
  code = GET_CODE (x);
60

61 62 63 64 65 66 67
  if (code == MATCH_OPERAND || code == MATCH_OPERATOR
      || code == MATCH_PARALLEL)
    max_opno = MAX (max_opno, XINT (x, 0));

  fmt = GET_RTX_FORMAT (code);
  len = GET_RTX_LENGTH (code);
  for (i = 0; i < len; i++)
68
    {
69 70 71
      if (fmt[i] == 'e' || fmt[i] == 'u')
	max_operand_1 (XEXP (x, i));
      else if (fmt[i] == 'E')
72
	{
73 74 75
	  int j;
	  for (j = 0; j < XVECLEN (x, i); j++)
	    max_operand_1 (XVECEXP (x, i, j));
76 77
	}
    }
78
}
79

80
static int
81
num_operands (rtx insn)
82
{
83 84
  int len = XVECLEN (insn, 1);
  int i;
85 86 87 88 89 90 91

  max_opno = -1;

  for (i = 0; i < len; i++)
    max_operand_1 (XVECEXP (insn, 1, i));

  return max_opno + 1;
92 93
}

94 95 96
/* Print out prototype information for a generator function.  If the
   insn pattern has been elided, print out a dummy generator that
   does nothing.  */
Mike Stump committed
97

98
static void
99
gen_proto (rtx insn)
100 101
{
  int num = num_operands (insn);
102
  int i;
103
  const char *name = XSTR (insn, 0);
104
  int truth = maybe_eval_c_test (XSTR (insn, 2));
105

106
  if (truth != 0)
107
    printf ("extern rtx        gen_%-*s (", max_id_len, name);
108
  else
109
    printf ("static inline rtx gen_%-*s (", max_id_len, name);
110 111

  if (num == 0)
112
    fputs ("void", stdout);
113 114
  else
    {
115 116
      for (i = 1; i < num; i++)
	fputs ("rtx, ", stdout);
117

118
      fputs ("rtx", stdout);
119 120
    }

121
  puts (");");
122 123 124 125 126 127 128 129 130 131

  /* Some back ends want to take the address of generator functions,
     so we cannot simply use #define for these dummy definitions.  */
  if (truth == 0)
    {
      printf ("static inline rtx\ngen_%s", name);
      if (num > 0)
	{
	  putchar ('(');
	  for (i = 0; i < num-1; i++)
132 133
	    printf ("rtx ARG_UNUSED (%c), ", 'a' + i);
	  printf ("rtx ARG_UNUSED (%c))\n", 'a' + i);
134 135
	}
      else
136
	puts ("(void)");
137 138
      puts ("{\n  return 0;\n}");
    }
139 140 141

}

Tom Wood committed
142
static void
143
gen_insn (md_rtx_info *info)
Tom Wood committed
144
{
145
  rtx insn = info->def;
146 147
  const char *name = XSTR (insn, 0);
  const char *p;
148
  const char *lt, *gt;
149
  int len;
150
  int truth = maybe_eval_c_test (XSTR (insn, 2));
Tom Wood committed
151

H.J. Lu committed
152
  lt = strchr (name, '<');
153 154
  if (lt && strchr (lt + 1, '>'))
    {
155
      error_at (info->loc, "unresolved iterator");
156 157 158
      return;
    }

H.J. Lu committed
159
  gt = strchr (name, '>');
160 161
  if (lt || gt)
    {
162 163
      error_at (info->loc, "unmatched angle brackets, likely "
		"an error in iterator syntax");
164 165 166
      return;
    }

167 168 169 170
  /* Don't mention instructions whose names are the null string
     or begin with '*'.  They are in the machine description just
     to be recognized.  */
  if (name[0] == 0 || name[0] == '*')
Tom Wood committed
171 172
    return;

173 174
  len = strlen (name);

175 176 177
  if (len > max_id_len)
    max_id_len = len;

178
  if (truth == 0)
179
    /* Emit nothing.  */;
180 181
  else if (truth == 1)
    printf ("#define HAVE_%s 1\n", name);
Tom Wood committed
182 183 184 185
  else
    {
      /* Write the macro definition, putting \'s at the end of each line,
	 if more than one.  */
186
      printf ("#define HAVE_%s (", name);
Tom Wood committed
187 188
      for (p = XSTR (insn, 2); *p; p++)
	{
189
	  if (IS_VSPACE (*p))
190
	    fputs (" \\\n", stdout);
Tom Wood committed
191
	  else
192
	    putchar (*p);
Tom Wood committed
193
	}
194
      fputs (")\n", stdout);
Tom Wood committed
195
    }
196

197
  obstack_grow (&obstack, &insn, sizeof (rtx));
Tom Wood committed
198 199 200
}

int
201
main (int argc, const char **argv)
Tom Wood committed
202
{
203
  rtx dummy;
204
  rtx *insns;
205
  rtx *insn_ptr;
Tom Wood committed
206

Zack Weinberg committed
207
  progname = "genflags";
208
  obstack_init (&obstack);
Tom Wood committed
209

210 211 212 213
  /* We need to see all the possibilities.  Elided insns may have
     direct calls to their generators in C code.  */
  insn_elision = 0;

214
  if (!init_rtx_reader_args (argc, argv))
Clinton Popetz committed
215
    return (FATAL_EXIT_CODE);
216

217 218 219 220
  puts ("/* Generated automatically by the program `genflags'");
  puts ("   from the machine description file `md'.  */\n");
  puts ("#ifndef GCC_INSN_FLAGS_H");
  puts ("#define GCC_INSN_FLAGS_H\n");
Tom Wood committed
221 222 223

  /* Read the machine description.  */

224 225 226 227 228 229 230 231
  md_rtx_info info;
  while (read_md_rtx (&info))
    switch (GET_CODE (info.def))
      {
      case DEFINE_INSN:
      case DEFINE_EXPAND:
	gen_insn (&info);
	break;
Tom Wood committed
232

233
      default:
Clinton Popetz committed
234
	break;
235
      }
Tom Wood committed
236

237
  /* Print out the prototypes now.  */
Mike Stump committed
238
  dummy = (rtx) 0;
239
  obstack_grow (&obstack, &dummy, sizeof (rtx));
240
  insns = XOBFINISH (&obstack, rtx *);
241

242
  for (insn_ptr = insns; *insn_ptr; insn_ptr++)
243 244
    gen_proto (*insn_ptr);

245
  puts ("\n#endif /* GCC_INSN_FLAGS_H */");
246

247
  if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
248 249 250
    return FATAL_EXIT_CODE;

  return SUCCESS_EXIT_CODE;
Tom Wood committed
251
}