]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gentarget-def.c
gensupport.h (compute_test_codes): Take a file_location rather than a line number.
[thirdparty/gcc.git] / gcc / gentarget-def.c
CommitLineData
4bccb39e
RS
1/* Generate insn-target-def.h, an automatically-generated part of targetm.
2 Copyright (C) 1987-2015 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
20#include "bconfig.h"
21#include "system.h"
22#include "coretypes.h"
23#include "tm.h"
24#include "rtl.h"
25#include "errors.h"
26#include "read-md.h"
27#include "gensupport.h"
28#include "hash-table.h"
29
30/* This class hashes define_insns and define_expands by name. */
31struct insn_hasher : nofree_ptr_hash <rtx_def>
32{
33 typedef rtx value_type;
34 typedef const char *compare_type;
35
36 static inline hashval_t hash (rtx);
37 static inline bool equal (rtx, const char *);
38};
39
40hashval_t
41insn_hasher::hash (rtx x)
42{
43 return htab_hash_string (XSTR (x, 0));
44}
45
46bool
47insn_hasher::equal (rtx x, const char *y)
48{
49 return strcmp (XSTR (x, 0), y) == 0;
50}
51
52/* All define_insns and define_expands, hashed by name. */
53static hash_table <insn_hasher> *insns;
54
55/* Records the prototype suffix X for each invalid_X stub that has been
56 generated. */
57static hash_table <nofree_string_hash> *stubs;
58
59/* Records which C conditions have been wrapped in functions, as a mapping
60 from the C condition to the function name. */
61static hash_map <nofree_string_hash, const char *> *have_funcs;
62
63/* Output hook definitions for pattern NAME, which has target-insns.def
64 prototype PROTOTYPE. */
65
66static void
67def_target_insn (const char *name, const char *prototype)
68{
69 /* Get an upper-case form of NAME. */
70 unsigned int i;
71 char *upper_name = XALLOCAVEC (char, strlen (name) + 1);
72 for (i = 0; name[i]; ++i)
73 upper_name[i] = TOUPPER (name[i]);
74 upper_name[i] = 0;
75
76 /* Check that the prototype is valid and concatenate the types
77 together to get a suffix. */
78 char *suffix = XALLOCAVEC (char, strlen (prototype) + 1);
79 i = 0;
80 unsigned int opno = 0;
81 for (const char *p = prototype; *p; ++p)
82 if (*p == 'x' && ISDIGIT (p[1]))
83 {
84 /* This should be a parameter name of the form "x<OPNO>".
85 That doesn't contribute to the suffix, so skip ahead and
86 process the following character. */
87 char *endptr;
cf3e5186 88 if ((unsigned int) strtol (p + 1, &endptr, 10) != opno
4bccb39e
RS
89 || (*endptr != ',' && *endptr != ')'))
90 {
91 error ("invalid prototype for '%s'", name);
92 exit (FATAL_EXIT_CODE);
93 }
94 opno += 1;
95 p = endptr;
96 if (*p == ',')
97 suffix[i++] = '_';
98 }
99 else if (*p == ')' || *p == ',')
100 {
101 /* We found the end of a parameter without finding a
102 parameter name. */
103 if (strcmp (prototype, "(void)") != 0)
104 {
105 error ("argument %d of '%s' did not have the expected name",
106 opno, name);
107 exit (FATAL_EXIT_CODE);
108 }
109 }
110 else if (*p != '(' && !ISSPACE (*p))
111 suffix[i++] = *p;
112 suffix[i] = 0;
113
114 /* See whether we have an implementation of this pattern. */
115 hashval_t hash = htab_hash_string (name);
116 int truth = 0;
117 const char *have_name = name;
118 if (rtx insn = insns->find_with_hash (name, hash))
119 {
120 const char *test = XSTR (insn, 2);
121 truth = maybe_eval_c_test (test);
122 gcc_assert (truth != 0);
123 if (truth < 0)
124 {
125 /* Try to reuse an existing function that performs the same test. */
126 bool existed;
127 const char *&entry = have_funcs->get_or_insert (test, &existed);
128 if (!existed)
129 {
130 entry = name;
131 printf ("\nstatic bool\n");
132 printf ("target_have_%s (void)\n", name);
133 printf ("{\n");
134 printf (" return ");
135 print_c_condition (test);
136 printf (";\n");
137 printf ("}\n");
138 }
139 have_name = entry;
140 }
141 printf ("\nstatic rtx_insn *\n");
142 printf ("target_gen_%s %s\n", name, prototype);
143 printf ("{\n");
144 if (truth < 0)
145 printf (" gcc_checking_assert (targetm.have_%s ());\n", name);
146 printf (" return insnify (gen_%s (", name);
147 for (i = 0; i < opno; ++i)
148 printf ("%sx%d", i == 0 ? "" : ", ", i);
149 printf ("));\n");
150 printf ("}\n");
151 }
152 else
153 {
154 const char **slot = stubs->find_slot (suffix, INSERT);
155 if (!*slot)
156 {
157 *slot = xstrdup (suffix);
158 printf ("\nstatic rtx_insn *\n");
159 printf ("invalid_%s ", suffix);
160 const char *p = prototype;
161 while (*p)
162 {
163 if (p[0] == 'x' && ISDIGIT (p[1]))
164 {
165 char *endptr;
166 strtol (p + 1, &endptr, 10);
167 p = endptr;
168 }
169 else
170 fputc (*p++, stdout);
171 }
172 printf ("\n{\n");
173 printf (" gcc_unreachable ();\n");
174 printf ("}\n");
175 }
176 }
177 printf ("\n#undef TARGET_HAVE_%s\n", upper_name);
178 printf ("#define TARGET_HAVE_%s ", upper_name);
179 if (truth == 0)
180 printf ("hook_bool_void_false\n");
181 else if (truth == 1)
182 printf ("hook_bool_void_true\n");
183 else
184 printf ("target_have_%s\n", have_name);
185
186 printf ("#undef TARGET_GEN_%s\n", upper_name);
187 printf ("#define TARGET_GEN_%s ", upper_name);
188 if (truth == 0)
189 printf ("invalid_%s\n", suffix);
190 else
191 printf ("target_gen_%s\n", name);
8684d89d
RS
192
193 printf ("#undef TARGET_CODE_FOR_%s\n", upper_name);
194 printf ("#define TARGET_CODE_FOR_%s ", upper_name);
195 if (truth == 0)
196 printf ("CODE_FOR_nothing\n");
197 else
198 printf ("CODE_FOR_%s\n", name);
4bccb39e
RS
199}
200
201int
202main (int argc, char **argv)
203{
204 int insn_code_number = 0;
205
206 progname = "gentarget-def";
207
208 if (!init_rtx_reader_args (argc, argv))
209 return (FATAL_EXIT_CODE);
210
211 insns = new hash_table <insn_hasher> (31);
212 stubs = new hash_table <nofree_string_hash> (31);
213 have_funcs = new hash_map <nofree_string_hash, const char *>;
214
215 while (1)
216 {
217 int line_no;
218 rtx desc = read_md_rtx (&line_no, &insn_code_number);
219 if (desc == NULL)
220 break;
221 if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
222 {
223 const char *name = XSTR (desc, 0);
224 if (name[0] != 0 && name[0] != '*')
225 {
226 hashval_t hash = htab_hash_string (name);
227 rtx *slot = insns->find_slot_with_hash (name, hash, INSERT);
228 if (*slot)
229 {
230 message_with_line (line_no, "duplicate definition of '%s'",
231 name);
232 have_error = 1;
233 }
234 else
235 *slot = desc;
236 }
237 }
238 }
239
240 printf ("/* Generated automatically by the program `gentarget-def'. */\n");
241 printf ("#ifndef GCC_INSN_TARGET_DEF_H\n");
242 printf ("#define GCC_INSN_TARGET_DEF_H\n");
243
244 /* Output a routine to convert an rtx to an rtx_insn sequence.
245 ??? At some point the gen_* functions themselves should return
246 rtx_insns. */
247 printf ("\nstatic inline rtx_insn *\n");
248 printf ("insnify (rtx x)\n");
249 printf ("{\n");
250 printf (" if (!x)\n");
251 printf (" return NULL;\n");
252 printf (" if (rtx_insn *insn = dyn_cast <rtx_insn *> (x))\n");
253 printf (" return insn;\n");
254 printf (" start_sequence ();\n");
9d8895c9 255 printf (" emit (x, false);\n");
4bccb39e
RS
256 printf (" rtx_insn *res = get_insns ();\n");
257 printf (" end_sequence ();\n");
258 printf (" return res;\n");
259 printf ("}\n");
260
261#define DEF_TARGET_INSN(INSN, ARGS) \
262 def_target_insn (#INSN, #ARGS);
263#include "target-insns.def"
264#undef DEF_TARGET_INSN
265
266 printf ("\n#endif /* GCC_INSN_TARGET_DEF_H */\n");
267
268 if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
269 return FATAL_EXIT_CODE;
270
271 return SUCCESS_EXIT_CODE;
272}