]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/gentarget-def.c
target.def: Add code_for_* hooks.
[thirdparty/gcc.git] / gcc / gentarget-def.c
1 /* Generate insn-target-def.h, an automatically-generated part of targetm.
2 Copyright (C) 1987-2015 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along 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. */
31 struct 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
40 hashval_t
41 insn_hasher::hash (rtx x)
42 {
43 return htab_hash_string (XSTR (x, 0));
44 }
45
46 bool
47 insn_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. */
53 static hash_table <insn_hasher> *insns;
54
55 /* Records the prototype suffix X for each invalid_X stub that has been
56 generated. */
57 static 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. */
61 static 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
66 static void
67 def_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;
88 if ((unsigned int) strtol (p + 1, &endptr, 10) != opno
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);
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);
199 }
200
201 int
202 main (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");
255 printf (" emit (x, false);\n");
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 }