]>
Commit | Line | Data |
---|---|---|
4bccb39e RS |
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; | |
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); | |
192 | } | |
193 | ||
194 | int | |
195 | main (int argc, char **argv) | |
196 | { | |
197 | int insn_code_number = 0; | |
198 | ||
199 | progname = "gentarget-def"; | |
200 | ||
201 | if (!init_rtx_reader_args (argc, argv)) | |
202 | return (FATAL_EXIT_CODE); | |
203 | ||
204 | insns = new hash_table <insn_hasher> (31); | |
205 | stubs = new hash_table <nofree_string_hash> (31); | |
206 | have_funcs = new hash_map <nofree_string_hash, const char *>; | |
207 | ||
208 | while (1) | |
209 | { | |
210 | int line_no; | |
211 | rtx desc = read_md_rtx (&line_no, &insn_code_number); | |
212 | if (desc == NULL) | |
213 | break; | |
214 | if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) | |
215 | { | |
216 | const char *name = XSTR (desc, 0); | |
217 | if (name[0] != 0 && name[0] != '*') | |
218 | { | |
219 | hashval_t hash = htab_hash_string (name); | |
220 | rtx *slot = insns->find_slot_with_hash (name, hash, INSERT); | |
221 | if (*slot) | |
222 | { | |
223 | message_with_line (line_no, "duplicate definition of '%s'", | |
224 | name); | |
225 | have_error = 1; | |
226 | } | |
227 | else | |
228 | *slot = desc; | |
229 | } | |
230 | } | |
231 | } | |
232 | ||
233 | printf ("/* Generated automatically by the program `gentarget-def'. */\n"); | |
234 | printf ("#ifndef GCC_INSN_TARGET_DEF_H\n"); | |
235 | printf ("#define GCC_INSN_TARGET_DEF_H\n"); | |
236 | ||
237 | /* Output a routine to convert an rtx to an rtx_insn sequence. | |
238 | ??? At some point the gen_* functions themselves should return | |
239 | rtx_insns. */ | |
240 | printf ("\nstatic inline rtx_insn *\n"); | |
241 | printf ("insnify (rtx x)\n"); | |
242 | printf ("{\n"); | |
243 | printf (" if (!x)\n"); | |
244 | printf (" return NULL;\n"); | |
245 | printf (" if (rtx_insn *insn = dyn_cast <rtx_insn *> (x))\n"); | |
246 | printf (" return insn;\n"); | |
247 | printf (" start_sequence ();\n"); | |
9d8895c9 | 248 | printf (" emit (x, false);\n"); |
4bccb39e RS |
249 | printf (" rtx_insn *res = get_insns ();\n"); |
250 | printf (" end_sequence ();\n"); | |
251 | printf (" return res;\n"); | |
252 | printf ("}\n"); | |
253 | ||
254 | #define DEF_TARGET_INSN(INSN, ARGS) \ | |
255 | def_target_insn (#INSN, #ARGS); | |
256 | #include "target-insns.def" | |
257 | #undef DEF_TARGET_INSN | |
258 | ||
259 | printf ("\n#endif /* GCC_INSN_TARGET_DEF_H */\n"); | |
260 | ||
261 | if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout)) | |
262 | return FATAL_EXIT_CODE; | |
263 | ||
264 | return SUCCESS_EXIT_CODE; | |
265 | } |