annotate gcc/gentarget-def.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Generate insn-target-def.h, an automatically-generated part of targetm.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 1987-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is part of GCC.
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
7 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
8 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
9 version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
14 for more details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 #include "bconfig.h"
kono
parents:
diff changeset
21 #include "system.h"
kono
parents:
diff changeset
22 #include "coretypes.h"
kono
parents:
diff changeset
23 #include "tm.h"
kono
parents:
diff changeset
24 #include "rtl.h"
kono
parents:
diff changeset
25 #include "errors.h"
kono
parents:
diff changeset
26 #include "read-md.h"
kono
parents:
diff changeset
27 #include "gensupport.h"
kono
parents:
diff changeset
28 #include "hash-table.h"
kono
parents:
diff changeset
29
kono
parents:
diff changeset
30 /* This class hashes define_insns and define_expands by name. */
kono
parents:
diff changeset
31 struct insn_hasher : nofree_ptr_hash <rtx_def>
kono
parents:
diff changeset
32 {
kono
parents:
diff changeset
33 typedef rtx value_type;
kono
parents:
diff changeset
34 typedef const char *compare_type;
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 static inline hashval_t hash (rtx);
kono
parents:
diff changeset
37 static inline bool equal (rtx, const char *);
kono
parents:
diff changeset
38 };
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 hashval_t
kono
parents:
diff changeset
41 insn_hasher::hash (rtx x)
kono
parents:
diff changeset
42 {
kono
parents:
diff changeset
43 return htab_hash_string (XSTR (x, 0));
kono
parents:
diff changeset
44 }
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 bool
kono
parents:
diff changeset
47 insn_hasher::equal (rtx x, const char *y)
kono
parents:
diff changeset
48 {
kono
parents:
diff changeset
49 return strcmp (XSTR (x, 0), y) == 0;
kono
parents:
diff changeset
50 }
kono
parents:
diff changeset
51
kono
parents:
diff changeset
52 /* All define_insns and define_expands, hashed by name. */
kono
parents:
diff changeset
53 static hash_table <insn_hasher> *insns;
kono
parents:
diff changeset
54
kono
parents:
diff changeset
55 /* Records the prototype suffix X for each invalid_X stub that has been
kono
parents:
diff changeset
56 generated. */
kono
parents:
diff changeset
57 static hash_table <nofree_string_hash> *stubs;
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 /* Records which C conditions have been wrapped in functions, as a mapping
kono
parents:
diff changeset
60 from the C condition to the function name. */
kono
parents:
diff changeset
61 static hash_map <nofree_string_hash, const char *> *have_funcs;
kono
parents:
diff changeset
62
kono
parents:
diff changeset
63 /* Return true if the part of the prototype at P is for an argument
kono
parents:
diff changeset
64 name. If so, point *END_OUT to the first character after the name.
kono
parents:
diff changeset
65 If OPNO_OUT is nonnull, set *OPNO_OUT to the number of the associated
kono
parents:
diff changeset
66 operand. If REQUIRED_OUT is nonnull, set *REQUIRED_OUT to whether the
kono
parents:
diff changeset
67 .md pattern is required to match the operand. */
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 static bool
kono
parents:
diff changeset
70 parse_argument (const char *p, const char **end_out,
kono
parents:
diff changeset
71 unsigned int *opno_out = 0,
kono
parents:
diff changeset
72 bool *required_out = 0)
kono
parents:
diff changeset
73 {
kono
parents:
diff changeset
74 while (ISSPACE (*p))
kono
parents:
diff changeset
75 p++;
kono
parents:
diff changeset
76 if (p[0] == 'x' && ISDIGIT (p[1]))
kono
parents:
diff changeset
77 {
kono
parents:
diff changeset
78 p += 1;
kono
parents:
diff changeset
79 if (required_out)
kono
parents:
diff changeset
80 *required_out = true;
kono
parents:
diff changeset
81 }
kono
parents:
diff changeset
82 else if (p[0] == 'o' && p[1] == 'p' && p[2] == 't' && ISDIGIT (p[3]))
kono
parents:
diff changeset
83 {
kono
parents:
diff changeset
84 p += 3;
kono
parents:
diff changeset
85 if (required_out)
kono
parents:
diff changeset
86 *required_out = false;
kono
parents:
diff changeset
87 }
kono
parents:
diff changeset
88 else
kono
parents:
diff changeset
89 return false;
kono
parents:
diff changeset
90
kono
parents:
diff changeset
91 char *endptr;
kono
parents:
diff changeset
92 unsigned int opno = strtol (p, &endptr, 10);
kono
parents:
diff changeset
93 if (opno_out)
kono
parents:
diff changeset
94 *opno_out = opno;
kono
parents:
diff changeset
95 *end_out = endptr;
kono
parents:
diff changeset
96 return true;
kono
parents:
diff changeset
97 }
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99
kono
parents:
diff changeset
100 /* Output hook definitions for pattern NAME, which has target-insns.def
kono
parents:
diff changeset
101 prototype PROTOTYPE. */
kono
parents:
diff changeset
102
kono
parents:
diff changeset
103 static void
kono
parents:
diff changeset
104 def_target_insn (const char *name, const char *prototype)
kono
parents:
diff changeset
105 {
kono
parents:
diff changeset
106 /* Get an upper-case form of NAME. */
kono
parents:
diff changeset
107 unsigned int i;
kono
parents:
diff changeset
108 char *upper_name = XALLOCAVEC (char, strlen (name) + 1);
kono
parents:
diff changeset
109 for (i = 0; name[i]; ++i)
kono
parents:
diff changeset
110 upper_name[i] = TOUPPER (name[i]);
kono
parents:
diff changeset
111 upper_name[i] = 0;
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 /* Check that the prototype is valid and concatenate the types
kono
parents:
diff changeset
114 together to get a suffix. */
kono
parents:
diff changeset
115 char *suffix = XALLOCAVEC (char, strlen (prototype) + 1);
kono
parents:
diff changeset
116 i = 0;
kono
parents:
diff changeset
117 unsigned int opno = 0;
kono
parents:
diff changeset
118 unsigned int required_ops = 0;
kono
parents:
diff changeset
119 unsigned int this_opno;
kono
parents:
diff changeset
120 bool required_p;
kono
parents:
diff changeset
121 for (const char *p = prototype; *p; ++p)
kono
parents:
diff changeset
122 if (parse_argument (p, &p, &this_opno, &required_p))
kono
parents:
diff changeset
123 {
kono
parents:
diff changeset
124 if (this_opno != opno || (*p != ',' && *p != ')'))
kono
parents:
diff changeset
125 {
kono
parents:
diff changeset
126 error ("invalid prototype for '%s'", name);
kono
parents:
diff changeset
127 exit (FATAL_EXIT_CODE);
kono
parents:
diff changeset
128 }
kono
parents:
diff changeset
129 if (required_p && required_ops < opno)
kono
parents:
diff changeset
130 {
kono
parents:
diff changeset
131 error ("prototype for '%s' has required operands after"
kono
parents:
diff changeset
132 " optional operands", name);
kono
parents:
diff changeset
133 exit (FATAL_EXIT_CODE);
kono
parents:
diff changeset
134 }
kono
parents:
diff changeset
135 opno += 1;
kono
parents:
diff changeset
136 if (required_p)
kono
parents:
diff changeset
137 required_ops = opno;
kono
parents:
diff changeset
138 /* Skip over ')'s. */
kono
parents:
diff changeset
139 if (*p == ',')
kono
parents:
diff changeset
140 suffix[i++] = '_';
kono
parents:
diff changeset
141 }
kono
parents:
diff changeset
142 else if (*p == ')' || *p == ',')
kono
parents:
diff changeset
143 {
kono
parents:
diff changeset
144 /* We found the end of a parameter without finding a
kono
parents:
diff changeset
145 parameter name. */
kono
parents:
diff changeset
146 if (strcmp (prototype, "(void)") != 0)
kono
parents:
diff changeset
147 {
kono
parents:
diff changeset
148 error ("argument %d of '%s' did not have the expected name",
kono
parents:
diff changeset
149 opno, name);
kono
parents:
diff changeset
150 exit (FATAL_EXIT_CODE);
kono
parents:
diff changeset
151 }
kono
parents:
diff changeset
152 }
kono
parents:
diff changeset
153 else if (*p != '(' && !ISSPACE (*p))
kono
parents:
diff changeset
154 suffix[i++] = *p;
kono
parents:
diff changeset
155 suffix[i] = 0;
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 /* See whether we have an implementation of this pattern. */
kono
parents:
diff changeset
158 hashval_t hash = htab_hash_string (name);
kono
parents:
diff changeset
159 int truth = 0;
kono
parents:
diff changeset
160 const char *have_name = name;
kono
parents:
diff changeset
161 if (rtx insn = insns->find_with_hash (name, hash))
kono
parents:
diff changeset
162 {
kono
parents:
diff changeset
163 pattern_stats stats;
kono
parents:
diff changeset
164 get_pattern_stats (&stats, XVEC (insn, 1));
kono
parents:
diff changeset
165 unsigned int actual_ops = stats.num_generator_args;
kono
parents:
diff changeset
166 if (opno == required_ops && opno != actual_ops)
kono
parents:
diff changeset
167 error_at (get_file_location (insn),
kono
parents:
diff changeset
168 "'%s' must have %d operands (excluding match_dups)",
kono
parents:
diff changeset
169 name, required_ops);
kono
parents:
diff changeset
170 else if (actual_ops < required_ops)
kono
parents:
diff changeset
171 error_at (get_file_location (insn),
kono
parents:
diff changeset
172 "'%s' must have at least %d operands (excluding match_dups)",
kono
parents:
diff changeset
173 name, required_ops);
kono
parents:
diff changeset
174 else if (actual_ops > opno)
kono
parents:
diff changeset
175 error_at (get_file_location (insn),
kono
parents:
diff changeset
176 "'%s' must have no more than %d operands"
kono
parents:
diff changeset
177 " (excluding match_dups)", name, opno);
kono
parents:
diff changeset
178
kono
parents:
diff changeset
179 const char *test = XSTR (insn, 2);
kono
parents:
diff changeset
180 truth = maybe_eval_c_test (test);
kono
parents:
diff changeset
181 gcc_assert (truth != 0);
kono
parents:
diff changeset
182 if (truth < 0)
kono
parents:
diff changeset
183 {
kono
parents:
diff changeset
184 /* Try to reuse an existing function that performs the same test. */
kono
parents:
diff changeset
185 bool existed;
kono
parents:
diff changeset
186 const char *&entry = have_funcs->get_or_insert (test, &existed);
kono
parents:
diff changeset
187 if (!existed)
kono
parents:
diff changeset
188 {
kono
parents:
diff changeset
189 entry = name;
kono
parents:
diff changeset
190 printf ("\nstatic bool\n");
kono
parents:
diff changeset
191 printf ("target_have_%s (void)\n", name);
kono
parents:
diff changeset
192 printf ("{\n");
kono
parents:
diff changeset
193 printf (" return ");
kono
parents:
diff changeset
194 rtx_reader_ptr->print_c_condition (test);
kono
parents:
diff changeset
195 printf (";\n");
kono
parents:
diff changeset
196 printf ("}\n");
kono
parents:
diff changeset
197 }
kono
parents:
diff changeset
198 have_name = entry;
kono
parents:
diff changeset
199 }
kono
parents:
diff changeset
200 printf ("\nstatic rtx_insn *\n");
kono
parents:
diff changeset
201 printf ("target_gen_%s ", name);
kono
parents:
diff changeset
202 /* Print the prototype with the argument names after ACTUAL_OPS
kono
parents:
diff changeset
203 removed. */
kono
parents:
diff changeset
204 const char *p = prototype, *end;
kono
parents:
diff changeset
205 while (*p)
kono
parents:
diff changeset
206 if (parse_argument (p, &end, &this_opno) && this_opno >= actual_ops)
kono
parents:
diff changeset
207 p = end;
kono
parents:
diff changeset
208 else
kono
parents:
diff changeset
209 fputc (*p++, stdout);
kono
parents:
diff changeset
210
kono
parents:
diff changeset
211 printf ("\n{\n");
kono
parents:
diff changeset
212 if (truth < 0)
kono
parents:
diff changeset
213 printf (" gcc_checking_assert (targetm.have_%s ());\n", name);
kono
parents:
diff changeset
214 printf (" return insnify (gen_%s (", name);
kono
parents:
diff changeset
215 for (i = 0; i < actual_ops; ++i)
kono
parents:
diff changeset
216 printf ("%s%s%d", i == 0 ? "" : ", ",
kono
parents:
diff changeset
217 i < required_ops ? "x" : "opt", i);
kono
parents:
diff changeset
218 printf ("));\n");
kono
parents:
diff changeset
219 printf ("}\n");
kono
parents:
diff changeset
220 }
kono
parents:
diff changeset
221 else
kono
parents:
diff changeset
222 {
kono
parents:
diff changeset
223 const char **slot = stubs->find_slot (suffix, INSERT);
kono
parents:
diff changeset
224 if (!*slot)
kono
parents:
diff changeset
225 {
kono
parents:
diff changeset
226 *slot = xstrdup (suffix);
kono
parents:
diff changeset
227 printf ("\nstatic rtx_insn *\n");
kono
parents:
diff changeset
228 printf ("invalid_%s ", suffix);
kono
parents:
diff changeset
229 /* Print the prototype with the argument names removed. */
kono
parents:
diff changeset
230 const char *p = prototype;
kono
parents:
diff changeset
231 while (*p)
kono
parents:
diff changeset
232 if (!parse_argument (p, &p))
kono
parents:
diff changeset
233 fputc (*p++, stdout);
kono
parents:
diff changeset
234 printf ("\n{\n");
kono
parents:
diff changeset
235 printf (" gcc_unreachable ();\n");
kono
parents:
diff changeset
236 printf ("}\n");
kono
parents:
diff changeset
237 }
kono
parents:
diff changeset
238 }
kono
parents:
diff changeset
239 printf ("\n#undef TARGET_HAVE_%s\n", upper_name);
kono
parents:
diff changeset
240 printf ("#define TARGET_HAVE_%s ", upper_name);
kono
parents:
diff changeset
241 if (truth == 0)
kono
parents:
diff changeset
242 printf ("hook_bool_void_false\n");
kono
parents:
diff changeset
243 else if (truth == 1)
kono
parents:
diff changeset
244 printf ("hook_bool_void_true\n");
kono
parents:
diff changeset
245 else
kono
parents:
diff changeset
246 printf ("target_have_%s\n", have_name);
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 printf ("#undef TARGET_GEN_%s\n", upper_name);
kono
parents:
diff changeset
249 printf ("#define TARGET_GEN_%s ", upper_name);
kono
parents:
diff changeset
250 if (truth == 0)
kono
parents:
diff changeset
251 printf ("invalid_%s\n", suffix);
kono
parents:
diff changeset
252 else
kono
parents:
diff changeset
253 printf ("target_gen_%s\n", name);
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 printf ("#undef TARGET_CODE_FOR_%s\n", upper_name);
kono
parents:
diff changeset
256 printf ("#define TARGET_CODE_FOR_%s ", upper_name);
kono
parents:
diff changeset
257 if (truth == 0)
kono
parents:
diff changeset
258 printf ("CODE_FOR_nothing\n");
kono
parents:
diff changeset
259 else
kono
parents:
diff changeset
260 printf ("CODE_FOR_%s\n", name);
kono
parents:
diff changeset
261 }
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 /* Record the DEFINE_INSN or DEFINE_EXPAND described by INFO. */
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 static void
kono
parents:
diff changeset
266 add_insn (md_rtx_info *info)
kono
parents:
diff changeset
267 {
kono
parents:
diff changeset
268 rtx def = info->def;
kono
parents:
diff changeset
269 const char *name = XSTR (def, 0);
kono
parents:
diff changeset
270 if (name[0] == 0 || name[0] == '*')
kono
parents:
diff changeset
271 return;
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 hashval_t hash = htab_hash_string (name);
kono
parents:
diff changeset
274 rtx *slot = insns->find_slot_with_hash (name, hash, INSERT);
kono
parents:
diff changeset
275 if (*slot)
kono
parents:
diff changeset
276 error_at (info->loc, "duplicate definition of '%s'", name);
kono
parents:
diff changeset
277 else
kono
parents:
diff changeset
278 *slot = def;
kono
parents:
diff changeset
279 }
kono
parents:
diff changeset
280
kono
parents:
diff changeset
281 int
kono
parents:
diff changeset
282 main (int argc, const char **argv)
kono
parents:
diff changeset
283 {
kono
parents:
diff changeset
284 progname = "gentarget-def";
kono
parents:
diff changeset
285
kono
parents:
diff changeset
286 if (!init_rtx_reader_args (argc, argv))
kono
parents:
diff changeset
287 return (FATAL_EXIT_CODE);
kono
parents:
diff changeset
288
kono
parents:
diff changeset
289 insns = new hash_table <insn_hasher> (31);
kono
parents:
diff changeset
290 stubs = new hash_table <nofree_string_hash> (31);
kono
parents:
diff changeset
291 have_funcs = new hash_map <nofree_string_hash, const char *>;
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293 md_rtx_info info;
kono
parents:
diff changeset
294 while (read_md_rtx (&info))
kono
parents:
diff changeset
295 switch (GET_CODE (info.def))
kono
parents:
diff changeset
296 {
kono
parents:
diff changeset
297 case DEFINE_INSN:
kono
parents:
diff changeset
298 case DEFINE_EXPAND:
kono
parents:
diff changeset
299 add_insn (&info);
kono
parents:
diff changeset
300 break;
kono
parents:
diff changeset
301
kono
parents:
diff changeset
302 default:
kono
parents:
diff changeset
303 break;
kono
parents:
diff changeset
304 }
kono
parents:
diff changeset
305
kono
parents:
diff changeset
306 printf ("/* Generated automatically by the program `gentarget-def'. */\n");
kono
parents:
diff changeset
307 printf ("#ifndef GCC_INSN_TARGET_DEF_H\n");
kono
parents:
diff changeset
308 printf ("#define GCC_INSN_TARGET_DEF_H\n");
kono
parents:
diff changeset
309
kono
parents:
diff changeset
310 /* Output a routine to convert an rtx to an rtx_insn sequence.
kono
parents:
diff changeset
311 ??? At some point the gen_* functions themselves should return
kono
parents:
diff changeset
312 rtx_insns. */
kono
parents:
diff changeset
313 printf ("\nstatic inline rtx_insn *\n");
kono
parents:
diff changeset
314 printf ("insnify (rtx x)\n");
kono
parents:
diff changeset
315 printf ("{\n");
kono
parents:
diff changeset
316 printf (" if (!x)\n");
kono
parents:
diff changeset
317 printf (" return NULL;\n");
kono
parents:
diff changeset
318 printf (" if (rtx_insn *insn = dyn_cast <rtx_insn *> (x))\n");
kono
parents:
diff changeset
319 printf (" return insn;\n");
kono
parents:
diff changeset
320 printf (" start_sequence ();\n");
kono
parents:
diff changeset
321 printf (" emit (x, false);\n");
kono
parents:
diff changeset
322 printf (" rtx_insn *res = get_insns ();\n");
kono
parents:
diff changeset
323 printf (" end_sequence ();\n");
kono
parents:
diff changeset
324 printf (" return res;\n");
kono
parents:
diff changeset
325 printf ("}\n");
kono
parents:
diff changeset
326
kono
parents:
diff changeset
327 #define DEF_TARGET_INSN(INSN, ARGS) \
kono
parents:
diff changeset
328 def_target_insn (#INSN, #ARGS);
kono
parents:
diff changeset
329 #include "target-insns.def"
kono
parents:
diff changeset
330 #undef DEF_TARGET_INSN
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 printf ("\n#endif /* GCC_INSN_TARGET_DEF_H */\n");
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
kono
parents:
diff changeset
335 return FATAL_EXIT_CODE;
kono
parents:
diff changeset
336
kono
parents:
diff changeset
337 return SUCCESS_EXIT_CODE;
kono
parents:
diff changeset
338 }