]>
Commit | Line | Data |
---|---|---|
af9e4a0c | 1 | /* Generate code to initialize optabs from machine description. |
23a5b65a | 2 | Copyright (C) 1993-2014 Free Software Foundation, Inc. |
af9e4a0c | 3 | |
1322177d | 4 | This file is part of GCC. |
af9e4a0c | 5 | |
1322177d LB |
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 | |
9dcd6f09 | 8 | Software Foundation; either version 3, or (at your option) any later |
1322177d | 9 | version. |
af9e4a0c | 10 | |
1322177d LB |
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. | |
af9e4a0c RK |
15 | |
16 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ | |
af9e4a0c RK |
19 | |
20 | ||
4977bab6 | 21 | #include "bconfig.h" |
0b93b64e | 22 | #include "system.h" |
4977bab6 ZW |
23 | #include "coretypes.h" |
24 | #include "tm.h" | |
af9e4a0c | 25 | #include "rtl.h" |
f8b6598e | 26 | #include "errors.h" |
c88c0d42 | 27 | #include "gensupport.h" |
ccd043a9 | 28 | |
af9e4a0c | 29 | |
cd1440b1 | 30 | #define DEF_RTL_EXPR(V, N, X, C) #V, |
af9e4a0c | 31 | |
cd1440b1 RH |
32 | static const char * const rtx_upname[] = { |
33 | #include "rtl.def" | |
34 | }; | |
35 | ||
36 | #undef DEF_RTL_EXPR | |
37 | ||
38 | ||
39 | /* The entries in optabs.def are categorized: | |
40 | C: A "conversion" optab, which uses two modes; has libcall data. | |
41 | N: A "normal" optab, which uses one mode; has libcall data. | |
42 | D: A "direct" optab, which uses one mode; does not have libcall data. | |
43 | V: An "oVerflow" optab. Like N, but does not record its code in | |
44 | code_to_optab. | |
af9e4a0c | 45 | |
cd1440b1 | 46 | CX, NX, VX: An extra pattern entry for a conversion or normal optab. |
af9e4a0c | 47 | |
cd1440b1 RH |
48 | These patterns may be present in the MD file with names that contain |
49 | the mode(s) used and the name of the operation. This array contains | |
50 | a list of optabs that need to be initialized. Within each name, | |
51 | $a and $b are used to match a short mode name (the part of the mode | |
52 | name not including `mode' and converted to lower-case). | |
a484f6ba AS |
53 | |
54 | $I means that only full integer modes should be considered for the | |
55 | next mode, and $F means that only float modes should be considered. | |
91ce572a | 56 | $P means that both full and partial integer modes should be considered. |
0f996086 | 57 | $Q means that only fixed-point modes should be considered. |
91ce572a | 58 | |
cd1440b1 RH |
59 | The pattern may be NULL if the optab exists only for the libcalls |
60 | that we plan to attach to it, and there are no named patterns in | |
61 | the md files. */ | |
62 | ||
63 | #define OPTAB_CL(name, pat, c, b, l) name, | |
64 | #define OPTAB_CX(name, pat) | |
65 | #define OPTAB_CD(name, pat) name, | |
66 | #define OPTAB_NL(name, pat, c, b, s, l) name, | |
67 | #define OPTAB_NC(name, pat, c) name, | |
68 | #define OPTAB_NX(name, pat) | |
69 | #define OPTAB_VL(name, pat, c, b, s, l) name, | |
70 | #define OPTAB_VC(name, pat, c) name, | |
71 | #define OPTAB_VX(name, pat) | |
72 | #define OPTAB_DC(name, pat, c) name, | |
73 | #define OPTAB_D(name, pat) name, | |
74 | ||
75 | typedef enum optab_tag { | |
76 | unknown_optab, | |
77 | #include "optabs.def" | |
78 | NUM_OPTABS | |
79 | } optab; | |
80 | ||
81 | #undef OPTAB_CL | |
82 | #undef OPTAB_CX | |
83 | #undef OPTAB_CD | |
84 | #undef OPTAB_NL | |
85 | #undef OPTAB_NC | |
86 | #undef OPTAB_NX | |
87 | #undef OPTAB_VL | |
88 | #undef OPTAB_VC | |
89 | #undef OPTAB_VX | |
90 | #undef OPTAB_DC | |
91 | #undef OPTAB_D | |
92 | ||
93 | #define NS "NULL" | |
94 | #define ZS "'\\0'" | |
95 | #define OPTAB_CL(o, p, c, b, l) { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 }, | |
96 | #define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 }, | |
97 | #define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 }, | |
98 | #define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 }, | |
99 | #define OPTAB_NC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 3 }, | |
100 | #define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 }, | |
101 | #define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 }, | |
102 | #define OPTAB_VC(o, p, c) { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 }, | |
103 | #define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 }, | |
104 | #define OPTAB_DC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 4 }, | |
105 | #define OPTAB_D(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 }, | |
106 | ||
107 | typedef struct optab_def_d | |
108 | { | |
109 | const char *name; | |
110 | const char *pattern; | |
111 | const char *base; | |
112 | const char *suffix; | |
113 | const char *libcall; | |
114 | unsigned int op; | |
115 | enum rtx_code fcode; | |
116 | enum rtx_code rcode; | |
117 | unsigned int kind; | |
118 | } optab_def; | |
119 | ||
120 | static optab_def optabs[] = { | |
121 | { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 }, | |
122 | #include "optabs.def" | |
48ae6c13 | 123 | }; |
af9e4a0c | 124 | |
cd1440b1 RH |
125 | #undef OPTAB_CL |
126 | #undef OPTAB_CX | |
127 | #undef OPTAB_CD | |
128 | #undef OPTAB_NL | |
129 | #undef OPTAB_NC | |
130 | #undef OPTAB_NX | |
131 | #undef OPTAB_VL | |
132 | #undef OPTAB_VC | |
133 | #undef OPTAB_VX | |
134 | #undef OPTAB_DC | |
135 | #undef OPTAB_D | |
136 | ||
137 | /* Vector in which to collect insns that match. */ | |
138 | ||
139 | typedef struct pattern_d | |
140 | { | |
141 | const char *name; | |
142 | unsigned int op; | |
143 | unsigned int m1, m2; | |
144 | unsigned int sort_num; | |
145 | } pattern; | |
146 | ||
cd1440b1 | 147 | |
9771b263 | 148 | static vec<pattern> patterns; |
cd1440b1 RH |
149 | |
150 | static bool | |
151 | match_pattern (pattern *p, const char *name, const char *pat) | |
152 | { | |
153 | bool force_float = false; | |
154 | bool force_int = false; | |
155 | bool force_partial_int = false; | |
156 | bool force_fixed = false; | |
157 | ||
158 | if (pat == NULL) | |
159 | return false; | |
160 | for (; ; ++pat) | |
161 | { | |
162 | if (*pat != '$') | |
163 | { | |
164 | if (*pat != *name++) | |
165 | return false; | |
166 | if (*pat == '\0') | |
167 | return true; | |
168 | continue; | |
169 | } | |
170 | switch (*++pat) | |
171 | { | |
172 | case 'I': | |
173 | force_int = 1; | |
174 | break; | |
175 | case 'P': | |
176 | force_partial_int = 1; | |
177 | break; | |
178 | case 'F': | |
179 | force_float = 1; | |
180 | break; | |
181 | case 'Q': | |
182 | force_fixed = 1; | |
183 | break; | |
184 | ||
185 | case 'a': | |
186 | case 'b': | |
187 | { | |
188 | int i; | |
189 | ||
190 | /* This loop will stop at the first prefix match, so | |
191 | look through the modes in reverse order, in case | |
192 | there are extra CC modes and CC is a prefix of the | |
193 | CC modes (as it should be). */ | |
194 | for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--) | |
195 | { | |
196 | const char *p, *q; | |
c3284718 | 197 | for (p = GET_MODE_NAME (i), q = name; *p; p++, q++) |
cd1440b1 RH |
198 | if (TOLOWER (*p) != *q) |
199 | break; | |
200 | if (*p == 0 | |
201 | && (! force_int || mode_class[i] == MODE_INT | |
202 | || mode_class[i] == MODE_VECTOR_INT) | |
203 | && (! force_partial_int | |
204 | || mode_class[i] == MODE_INT | |
205 | || mode_class[i] == MODE_PARTIAL_INT | |
206 | || mode_class[i] == MODE_VECTOR_INT) | |
207 | && (! force_float | |
208 | || mode_class[i] == MODE_FLOAT | |
209 | || mode_class[i] == MODE_DECIMAL_FLOAT | |
210 | || mode_class[i] == MODE_COMPLEX_FLOAT | |
211 | || mode_class[i] == MODE_VECTOR_FLOAT) | |
212 | && (! force_fixed | |
213 | || mode_class[i] == MODE_FRACT | |
214 | || mode_class[i] == MODE_UFRACT | |
215 | || mode_class[i] == MODE_ACCUM | |
216 | || mode_class[i] == MODE_UACCUM | |
217 | || mode_class[i] == MODE_VECTOR_FRACT | |
218 | || mode_class[i] == MODE_VECTOR_UFRACT | |
219 | || mode_class[i] == MODE_VECTOR_ACCUM | |
220 | || mode_class[i] == MODE_VECTOR_UACCUM)) | |
221 | break; | |
222 | } | |
223 | ||
224 | if (i < 0) | |
225 | return false; | |
226 | name += strlen (GET_MODE_NAME (i)); | |
227 | if (*pat == 'a') | |
228 | p->m1 = i; | |
229 | else | |
230 | p->m2 = i; | |
231 | ||
232 | force_int = false; | |
233 | force_partial_int = false; | |
234 | force_float = false; | |
235 | force_fixed = false; | |
236 | } | |
237 | break; | |
238 | ||
239 | default: | |
240 | gcc_unreachable (); | |
241 | } | |
242 | } | |
243 | } | |
56c0e996 | 244 | |
af9e4a0c | 245 | static void |
3d7aafde | 246 | gen_insn (rtx insn) |
af9e4a0c | 247 | { |
3cce094d | 248 | const char *name = XSTR (insn, 0); |
cd1440b1 RH |
249 | pattern p; |
250 | unsigned pindex; | |
af9e4a0c | 251 | |
cd1440b1 RH |
252 | /* Don't mention "unnamed" instructions. */ |
253 | if (*name == 0 || *name == '*') | |
254 | return; | |
255 | p.name = name; | |
af9e4a0c | 256 | |
cd1440b1 RH |
257 | /* See if NAME matches one of the patterns we have for the optabs |
258 | we know about. */ | |
b6a1cbae | 259 | for (pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++) |
af9e4a0c | 260 | { |
cd1440b1 RH |
261 | p.m1 = p.m2 = 0; |
262 | if (match_pattern (&p, name, optabs[pindex].pattern)) | |
af9e4a0c | 263 | { |
cd1440b1 RH |
264 | p.op = optabs[pindex].op; |
265 | p.sort_num = (p.op << 16) | (p.m2 << 8) | p.m1; | |
9771b263 | 266 | patterns.safe_push (p); |
cd1440b1 | 267 | return; |
af9e4a0c | 268 | } |
af9e4a0c | 269 | } |
cd1440b1 | 270 | } |
af9e4a0c | 271 | |
cd1440b1 RH |
272 | static int |
273 | pattern_cmp (const void *va, const void *vb) | |
274 | { | |
275 | const pattern *a = (const pattern *)va; | |
276 | const pattern *b = (const pattern *)vb; | |
277 | return a->sort_num - b->sort_num; | |
278 | } | |
af9e4a0c | 279 | |
cd1440b1 RH |
280 | static int |
281 | optab_kind_cmp (const void *va, const void *vb) | |
282 | { | |
283 | const optab_def *a = (const optab_def *)va; | |
284 | const optab_def *b = (const optab_def *)vb; | |
285 | int diff = a->kind - b->kind; | |
286 | if (diff == 0) | |
287 | diff = a->op - b->op; | |
288 | return diff; | |
289 | } | |
af9e4a0c | 290 | |
cd1440b1 RH |
291 | static int |
292 | optab_rcode_cmp (const void *va, const void *vb) | |
293 | { | |
294 | const optab_def *a = (const optab_def *)va; | |
295 | const optab_def *b = (const optab_def *)vb; | |
296 | return a->rcode - b->rcode; | |
297 | } | |
af9e4a0c | 298 | |
cd1440b1 RH |
299 | static const char *header_file_name = "init-opinit.h"; |
300 | static const char *source_file_name = "init-opinit.c"; | |
af9e4a0c | 301 | |
cd1440b1 RH |
302 | static bool |
303 | handle_arg (const char *arg) | |
304 | { | |
305 | switch (arg[1]) | |
af9e4a0c | 306 | { |
cd1440b1 RH |
307 | case 'h': |
308 | header_file_name = &arg[2]; | |
309 | return true; | |
310 | case 'c': | |
311 | source_file_name = &arg[2]; | |
312 | return true; | |
313 | default: | |
314 | return false; | |
af9e4a0c | 315 | } |
af9e4a0c | 316 | } |
af9e4a0c | 317 | |
cd1440b1 RH |
318 | static FILE * |
319 | open_outfile (const char *file_name) | |
320 | { | |
321 | FILE *f = fopen (file_name, "w"); | |
322 | if (!f) | |
323 | fatal ("cannot open file %s: %s", file_name, xstrerror (errno)); | |
324 | fprintf (f, | |
325 | "/* Generated automatically by the program `genopinit'\n" | |
326 | " from the machine description file `md'. */\n\n"); | |
327 | return f; | |
328 | } | |
c1b59dce | 329 | |
af9e4a0c | 330 | int |
3d7aafde | 331 | main (int argc, char **argv) |
af9e4a0c | 332 | { |
cd1440b1 RH |
333 | FILE *h_file, *s_file; |
334 | unsigned int i, j, n, last_kind[5]; | |
335 | pattern *p; | |
af9e4a0c | 336 | |
f8b6598e | 337 | progname = "genopinit"; |
af9e4a0c | 338 | |
cd1440b1 RH |
339 | if (NUM_OPTABS > 0xffff || MAX_MACHINE_MODE >= 0xff) |
340 | fatal ("genopinit range assumptions invalid"); | |
341 | ||
342 | if (!init_rtx_reader_args_cb (argc, argv, handle_arg)) | |
c88c0d42 | 343 | return (FATAL_EXIT_CODE); |
af9e4a0c | 344 | |
cd1440b1 RH |
345 | h_file = open_outfile (header_file_name); |
346 | s_file = open_outfile (source_file_name); | |
dcc3fcf2 | 347 | |
af9e4a0c | 348 | /* Read the machine description. */ |
af9e4a0c RK |
349 | while (1) |
350 | { | |
c88c0d42 | 351 | int line_no, insn_code_number = 0; |
cd1440b1 | 352 | rtx desc = read_md_rtx (&line_no, &insn_code_number); |
c88c0d42 | 353 | if (desc == NULL) |
af9e4a0c | 354 | break; |
af9e4a0c RK |
355 | if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) |
356 | gen_insn (desc); | |
357 | } | |
358 | ||
cd1440b1 | 359 | /* Sort the collected patterns. */ |
9771b263 | 360 | qsort (patterns.address (), patterns.length (), |
cd1440b1 RH |
361 | sizeof (pattern), pattern_cmp); |
362 | ||
363 | /* Now that we've handled the "extra" patterns, eliminate them from | |
364 | the optabs array. That way they don't get in the way below. */ | |
365 | n = ARRAY_SIZE (optabs); | |
366 | for (i = 0; i < n; ) | |
367 | if (optabs[i].base == NULL) | |
368 | optabs[i] = optabs[--n]; | |
369 | else | |
370 | ++i; | |
371 | ||
372 | /* Sort the (real) optabs. Better than forcing the optabs.def file to | |
373 | remain sorted by kind. We also scrogged any real ordering with the | |
374 | purging of the X patterns above. */ | |
c3284718 | 375 | qsort (optabs, n, sizeof (optab_def), optab_kind_cmp); |
cd1440b1 RH |
376 | |
377 | /* Emit the optab enumeration for the header file. */ | |
378 | fprintf (h_file, "enum optab_tag {\n"); | |
379 | for (i = j = 0; i < n; ++i) | |
380 | { | |
381 | optabs[i].op = i; | |
382 | fprintf (h_file, " %s,\n", optabs[i].name); | |
383 | if (optabs[i].kind != j) | |
384 | last_kind[j++] = i - 1; | |
385 | } | |
386 | fprintf (h_file, " FIRST_CONV_OPTAB = %s,\n", optabs[last_kind[0]+1].name); | |
387 | fprintf (h_file, " LAST_CONVLIB_OPTAB = %s,\n", optabs[last_kind[1]].name); | |
388 | fprintf (h_file, " LAST_CONV_OPTAB = %s,\n", optabs[last_kind[2]].name); | |
389 | fprintf (h_file, " FIRST_NORM_OPTAB = %s,\n", optabs[last_kind[2]+1].name); | |
390 | fprintf (h_file, " LAST_NORMLIB_OPTAB = %s,\n", optabs[last_kind[3]].name); | |
391 | fprintf (h_file, " LAST_NORM_OPTAB = %s\n", optabs[i-1].name); | |
392 | fprintf (h_file, "};\n\n"); | |
393 | ||
394 | fprintf (h_file, "#define NUM_OPTABS %u\n", n); | |
395 | fprintf (h_file, "#define NUM_CONVLIB_OPTABS %u\n", | |
396 | last_kind[1] - last_kind[0]); | |
397 | fprintf (h_file, "#define NUM_NORMLIB_OPTABS %u\n", | |
398 | last_kind[3] - last_kind[2]); | |
399 | fprintf (h_file, "#define NUM_OPTAB_PATTERNS %u\n", | |
9771b263 | 400 | (unsigned) patterns.length ()); |
cd1440b1 RH |
401 | |
402 | fprintf (s_file, | |
403 | "#include \"config.h\"\n" | |
404 | "#include \"system.h\"\n" | |
405 | "#include \"coretypes.h\"\n" | |
406 | "#include \"tm.h\"\n" | |
4d648807 | 407 | "#include \"tree.h\"\n" |
d8a2d370 DN |
408 | "#include \"varasm.h\"\n" |
409 | "#include \"stor-layout.h\"\n" | |
410 | "#include \"calls.h\"\n" | |
cd1440b1 RH |
411 | "#include \"rtl.h\"\n" |
412 | "#include \"tm_p.h\"\n" | |
413 | "#include \"flags.h\"\n" | |
414 | "#include \"insn-config.h\"\n" | |
415 | "#include \"expr.h\"\n" | |
416 | "#include \"optabs.h\"\n" | |
417 | "\n" | |
418 | "struct optab_pat {\n" | |
419 | " unsigned scode;\n" | |
420 | " enum insn_code icode;\n" | |
421 | "};\n\n"); | |
422 | ||
423 | fprintf (s_file, | |
424 | "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n"); | |
9771b263 | 425 | for (i = 0; patterns.iterate (i, &p); ++i) |
cd1440b1 RH |
426 | fprintf (s_file, " { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name); |
427 | fprintf (s_file, "};\n\n"); | |
428 | ||
135204dd AH |
429 | fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n"); |
430 | fprintf (s_file, " bool *ena = optabs->pat_enable;\n"); | |
9771b263 | 431 | for (i = 0; patterns.iterate (i, &p); ++i) |
cd1440b1 RH |
432 | fprintf (s_file, " ena[%u] = HAVE_%s;\n", i, p->name); |
433 | fprintf (s_file, "}\n\n"); | |
434 | ||
435 | /* Perform a binary search on a pre-encoded optab+mode*2. */ | |
436 | /* ??? Perhaps even better to generate a minimal perfect hash. | |
437 | Using gperf directly is awkward since it's so geared to working | |
438 | with strings. Plus we have no visibility into the ordering of | |
439 | the hash entries, which complicates the pat_enable array. */ | |
440 | fprintf (s_file, | |
441 | "static int\n" | |
442 | "lookup_handler (unsigned scode)\n" | |
443 | "{\n" | |
444 | " int l = 0, h = ARRAY_SIZE (pats), m;\n" | |
445 | " while (h > l)\n" | |
446 | " {\n" | |
447 | " m = (h + l) / 2;\n" | |
448 | " if (scode == pats[m].scode)\n" | |
449 | " return m;\n" | |
450 | " else if (scode < pats[m].scode)\n" | |
451 | " h = m;\n" | |
452 | " else\n" | |
453 | " l = m + 1;\n" | |
454 | " }\n" | |
455 | " return -1;\n" | |
456 | "}\n\n"); | |
457 | ||
458 | fprintf (s_file, | |
459 | "enum insn_code\n" | |
460 | "raw_optab_handler (unsigned scode)\n" | |
461 | "{\n" | |
462 | " int i = lookup_handler (scode);\n" | |
135204dd | 463 | " return (i >= 0 && this_fn_optabs->pat_enable[i]\n" |
cd1440b1 RH |
464 | " ? pats[i].icode : CODE_FOR_nothing);\n" |
465 | "}\n\n"); | |
466 | ||
467 | fprintf (s_file, | |
468 | "bool\n" | |
469 | "swap_optab_enable (optab op, enum machine_mode m, bool set)\n" | |
470 | "{\n" | |
471 | " unsigned scode = (op << 16) | m;\n" | |
472 | " int i = lookup_handler (scode);\n" | |
473 | " if (i >= 0)\n" | |
474 | " {\n" | |
135204dd AH |
475 | " bool ret = this_fn_optabs->pat_enable[i];\n" |
476 | " this_fn_optabs->pat_enable[i] = set;\n" | |
cd1440b1 RH |
477 | " return ret;\n" |
478 | " }\n" | |
479 | " else\n" | |
480 | " {\n" | |
481 | " gcc_assert (!set);\n" | |
482 | " return false;\n" | |
483 | " }\n" | |
484 | "}\n\n"); | |
485 | ||
486 | /* C++ (even G++) does not support (non-trivial) designated initializers. | |
487 | To work around that, generate these arrays programatically rather than | |
488 | by our traditional multiple inclusion of def files. */ | |
489 | ||
490 | fprintf (s_file, | |
491 | "const struct convert_optab_libcall_d " | |
492 | "convlib_def[NUM_CONVLIB_OPTABS] = {\n"); | |
493 | for (i = last_kind[0] + 1; i <= last_kind[1]; ++i) | |
494 | fprintf (s_file, " { %s, %s },\n", optabs[i].base, optabs[i].libcall); | |
495 | fprintf (s_file, "};\n\n"); | |
496 | ||
497 | fprintf (s_file, | |
498 | "const struct optab_libcall_d " | |
499 | "normlib_def[NUM_NORMLIB_OPTABS] = {\n"); | |
500 | for (i = last_kind[2] + 1; i <= last_kind[3]; ++i) | |
501 | fprintf (s_file, " { %s, %s, %s },\n", | |
502 | optabs[i].suffix, optabs[i].base, optabs[i].libcall); | |
503 | fprintf (s_file, "};\n\n"); | |
504 | ||
505 | fprintf (s_file, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n"); | |
506 | for (i = 0; i < n; ++i) | |
507 | fprintf (s_file, " %s,\n", rtx_upname[optabs[i].fcode]); | |
508 | fprintf (s_file, "};\n\n"); | |
509 | ||
510 | qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp); | |
511 | ||
512 | fprintf (s_file, "const optab code_to_optab_[NUM_RTX_CODE] = {\n"); | |
513 | for (j = 0; optabs[j].rcode == UNKNOWN; ++j) | |
514 | continue; | |
515 | for (i = 0; i < NON_GENERATOR_NUM_RTX_CODE; ++i) | |
516 | { | |
517 | if (j < n && optabs[j].rcode == i) | |
518 | fprintf (s_file, " %s,\n", optabs[j++].name); | |
519 | else | |
520 | fprintf (s_file, " unknown_optab,\n"); | |
521 | } | |
522 | fprintf (s_file, "};\n\n"); | |
523 | ||
524 | return (fclose (h_file) == 0 && fclose (s_file) == 0 | |
525 | ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE); | |
af9e4a0c | 526 | } |