]>
Commit | Line | Data |
---|---|---|
86d7f2db | 1 | /* Bytecode conversion definitions for GNU C-compiler. |
e9a25f70 | 2 | Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc. |
86d7f2db JB |
3 | |
4 | This file is part of GNU CC. | |
5 | ||
6 | GNU CC is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2, or (at your option) | |
9 | any later version. | |
10 | ||
11 | GNU CC is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GNU CC; see the file COPYING. If not, write to | |
940d9d63 RK |
18 | the Free Software Foundation, 59 Temple Place - Suite 330, |
19 | Boston, MA 02111-1307, USA. */ | |
86d7f2db JB |
20 | |
21 | ||
22 | #include "config.h" | |
e9a25f70 | 23 | #include <stdio.h> |
956d6950 JL |
24 | #ifdef HAVE_STDLIB_H |
25 | #include <stdlib.h> | |
26 | #endif | |
86d7f2db JB |
27 | #include "tree.h" |
28 | #include "rtl.h" | |
29 | #include "machmode.h" | |
30 | #include "obstack.h" | |
31 | #include "bytecode.h" | |
32 | #include "bc-typecd.h" | |
33 | #include "bc-opcode.h" | |
34 | #include "bc-optab.h" | |
35 | ||
2601ebca JL |
36 | #ifdef HAVE_STDLIB_H |
37 | #include <stdlib.h> | |
38 | #endif | |
39 | ||
40 | #ifdef NEED_DECLARATION_FREE | |
41 | extern void free PROTO((void *)); | |
42 | #endif | |
43 | ||
86d7f2db JB |
44 | #define obstack_chunk_alloc xmalloc |
45 | #define obstack_chunk_free free | |
46 | ||
47 | extern char *xmalloc (); | |
86d7f2db JB |
48 | |
49 | /* Table relating interpreter typecodes to machine modes. */ | |
50 | #define GET_TYPECODE_MODE(CODE) (typecode_mode[((int) CODE)]) | |
51 | enum machine_mode typecode_mode[] = { | |
52 | #define DEFTYPECODE(CODE, NAME, MODE, TYPE) MODE, | |
53 | #include "bc-typecd.def" | |
54 | #undef DEFTYPECODE | |
55 | }; | |
56 | ||
57 | /* Machine mode to type code map */ | |
58 | static enum typecode signed_mode_to_code_map[MAX_MACHINE_MODE+1]; | |
59 | static enum typecode unsigned_mode_to_code_map[MAX_MACHINE_MODE+1]; | |
60 | ||
61 | #define GET_TYPECODE_SIZE(CODE) GET_MODE_SIZE (GET_TYPECODE_MODE (CODE)) | |
62 | ||
63 | #define BIG_ARBITRARY_NUMBER 100000 | |
64 | ||
65 | /* Table of recipes for conversions among scalar types, to be filled | |
66 | in as needed at run time. */ | |
67 | static struct conversion_recipe | |
68 | { | |
69 | unsigned char *opcodes; /* Bytecodes to emit in order. */ | |
0f41302f MS |
70 | int nopcodes; /* Count of bytecodes. */ |
71 | int cost; /* A rather arbitrary cost function. */ | |
86d7f2db JB |
72 | } conversion_recipe[NUM_TYPECODES][NUM_TYPECODES]; |
73 | ||
74 | /* Binary operator tables. */ | |
75 | struct binary_operator optab_plus_expr[] = { | |
76 | { addSI, SIcode, SIcode, SIcode }, | |
77 | { addDI, DIcode, DIcode, DIcode }, | |
78 | { addSF, SFcode, SFcode, SFcode }, | |
79 | { addDF, DFcode, DFcode, DFcode }, | |
80 | { addXF, XFcode, XFcode, XFcode }, | |
81 | { addPSI, Pcode, Pcode, SIcode }, | |
82 | { -1, -1, -1, -1 }, | |
83 | }; | |
84 | ||
85 | struct binary_operator optab_minus_expr[] = { | |
86 | { subSI, SIcode, SIcode, SIcode }, | |
87 | { subDI, DIcode, DIcode, DIcode }, | |
88 | { subSF, SFcode, SFcode, SFcode }, | |
89 | { subDF, DFcode, DFcode, DFcode }, | |
90 | { subXF, XFcode, XFcode, XFcode }, | |
91 | { subPP, SIcode, Pcode, Pcode }, | |
92 | { -1, -1, -1, -1 }, | |
93 | }; | |
94 | ||
95 | /* The ordering of the tables for multiplicative operators | |
96 | is such that unsigned operations will be preferred to signed | |
97 | operations when one argument is unsigned. */ | |
98 | ||
99 | struct binary_operator optab_mult_expr[] = { | |
100 | { mulSU, SUcode, SUcode, SUcode }, | |
101 | { mulDU, DUcode, DUcode, DUcode }, | |
102 | { mulSI, SIcode, SIcode, SIcode }, | |
103 | { mulDI, DIcode, DIcode, DIcode }, | |
104 | { mulSF, SFcode, SFcode, SFcode }, | |
105 | { mulDF, DFcode, DFcode, DFcode }, | |
106 | { mulXF, XFcode, XFcode, XFcode }, | |
107 | { -1, -1, -1, -1 }, | |
108 | }; | |
109 | ||
110 | struct binary_operator optab_trunc_div_expr[] = { | |
111 | { divSU, SUcode, SUcode, SUcode }, | |
112 | { divDU, DUcode, DUcode, DUcode }, | |
113 | { divSI, SIcode, SIcode, SIcode }, | |
114 | { divDI, DIcode, DIcode, DIcode }, | |
115 | { -1, -1, -1, -1 }, | |
116 | }; | |
117 | ||
118 | struct binary_operator optab_trunc_mod_expr[] = { | |
119 | { modSU, SUcode, SUcode, SUcode }, | |
120 | { modDU, DUcode, DUcode, DUcode }, | |
121 | { modSI, SIcode, SIcode, SIcode }, | |
122 | { modDI, DIcode, DIcode, DIcode }, | |
123 | { -1, -1, -1, -1 }, | |
124 | }; | |
125 | ||
126 | struct binary_operator optab_rdiv_expr[] = { | |
127 | { divSF, SFcode, SFcode, SFcode }, | |
128 | { divDF, DFcode, DFcode, DFcode }, | |
129 | { divXF, XFcode, XFcode, XFcode }, | |
130 | { -1, -1, -1, -1 }, | |
131 | }; | |
132 | ||
133 | struct binary_operator optab_bit_and_expr[] = { | |
134 | { andSI, SIcode, SIcode, SIcode }, | |
135 | { andDI, DIcode, DIcode, DIcode }, | |
136 | { -1, -1, -1, -1 }, | |
137 | }; | |
138 | ||
139 | struct binary_operator optab_bit_ior_expr[] = { | |
140 | { iorSI, SIcode, SIcode, SIcode }, | |
141 | { iorDI, DIcode, DIcode, DIcode }, | |
142 | { -1, -1, -1, -1 }, | |
143 | }; | |
144 | ||
145 | struct binary_operator optab_bit_xor_expr[] = { | |
146 | { xorSI, SIcode, SIcode, SIcode }, | |
147 | { xorDI, DIcode, DIcode, DIcode }, | |
148 | { -1, -1, -1, -1 }, | |
149 | }; | |
150 | ||
151 | struct binary_operator optab_lshift_expr[] = { | |
152 | { lshiftSI, SIcode, SIcode, SIcode }, | |
153 | { lshiftSU, SUcode, SUcode, SIcode }, | |
154 | { lshiftDI, DIcode, DIcode, SIcode }, | |
155 | { lshiftDU, DUcode, DUcode, SIcode }, | |
156 | { -1, -1, -1, -1 }, | |
157 | }; | |
158 | ||
159 | struct binary_operator optab_rshift_expr[] = { | |
160 | { rshiftSI, SIcode, SIcode, SIcode }, | |
161 | { rshiftSU, SUcode, SUcode, SIcode }, | |
162 | { rshiftDI, DIcode, DIcode, SIcode }, | |
163 | { rshiftDU, DUcode, DUcode, SIcode }, | |
164 | { -1, -1, -1, -1 }, | |
165 | }; | |
166 | ||
167 | struct binary_operator optab_truth_and_expr[] = { | |
168 | { andSI, SIcode, Tcode, Tcode }, | |
169 | { -1, -1, -1, -1 }, | |
170 | }; | |
171 | ||
172 | struct binary_operator optab_truth_or_expr[] = { | |
173 | { iorSI, SIcode, Tcode, Tcode }, | |
174 | { -1, -1, -1, -1 }, | |
175 | }; | |
176 | ||
177 | struct binary_operator optab_lt_expr[] = { | |
178 | { ltSI, Tcode, SIcode, SIcode }, | |
179 | { ltSU, Tcode, SUcode, SUcode }, | |
180 | { ltDI, Tcode, DIcode, DIcode }, | |
181 | { ltDU, Tcode, DUcode, DUcode }, | |
182 | { ltSF, Tcode, SFcode, SFcode }, | |
183 | { ltDF, Tcode, DFcode, DFcode }, | |
184 | { ltXF, Tcode, XFcode, XFcode }, | |
185 | { ltP, Tcode, Pcode, Pcode }, | |
186 | { -1, -1, -1, -1 }, | |
187 | }; | |
188 | ||
189 | struct binary_operator optab_le_expr[] = { | |
190 | { leSI, Tcode, SIcode, SIcode }, | |
191 | { leSU, Tcode, SUcode, SUcode }, | |
192 | { leDI, Tcode, DIcode, DIcode }, | |
193 | { leDU, Tcode, DUcode, DUcode }, | |
194 | { leSF, Tcode, SFcode, SFcode }, | |
195 | { leDF, Tcode, DFcode, DFcode }, | |
196 | { leXF, Tcode, XFcode, XFcode }, | |
197 | { leP, Tcode, Pcode, Pcode }, | |
198 | { -1, -1, -1, -1 }, | |
199 | }; | |
200 | ||
201 | struct binary_operator optab_ge_expr[] = { | |
202 | { geSI, Tcode, SIcode, SIcode }, | |
203 | { geSU, Tcode, SUcode, SUcode }, | |
204 | { geDI, Tcode, DIcode, DIcode }, | |
205 | { geDU, Tcode, DUcode, DUcode }, | |
206 | { geSF, Tcode, SFcode, SFcode }, | |
207 | { geDF, Tcode, DFcode, DFcode }, | |
208 | { geXF, Tcode, XFcode, XFcode }, | |
209 | { geP, Tcode, Pcode, Pcode }, | |
210 | { -1, -1, -1, -1 }, | |
211 | }; | |
212 | ||
213 | struct binary_operator optab_gt_expr[] = { | |
214 | { gtSI, Tcode, SIcode, SIcode }, | |
215 | { gtSU, Tcode, SUcode, SUcode }, | |
216 | { gtDI, Tcode, DIcode, DIcode }, | |
217 | { gtDU, Tcode, DUcode, DUcode }, | |
218 | { gtSF, Tcode, SFcode, SFcode }, | |
219 | { gtDF, Tcode, DFcode, DFcode }, | |
220 | { gtXF, Tcode, XFcode, XFcode }, | |
221 | { gtP, Tcode, Pcode, Pcode }, | |
222 | { -1, -1, -1, -1 }, | |
223 | }; | |
224 | ||
225 | struct binary_operator optab_eq_expr[] = { | |
226 | { eqSI, Tcode, SIcode, SIcode }, | |
227 | { eqDI, Tcode, DIcode, DIcode }, | |
228 | { eqSF, Tcode, SFcode, SFcode }, | |
229 | { eqDF, Tcode, DFcode, DFcode }, | |
230 | { eqXF, Tcode, XFcode, XFcode }, | |
231 | { eqP, Tcode, Pcode, Pcode }, | |
232 | { -1, -1, -1, -1 }, | |
233 | }; | |
234 | ||
235 | struct binary_operator optab_ne_expr[] = { | |
236 | { neSI, Tcode, SIcode, SIcode }, | |
237 | { neDI, Tcode, DIcode, DIcode }, | |
238 | { neSF, Tcode, SFcode, SFcode }, | |
239 | { neDF, Tcode, DFcode, DFcode }, | |
240 | { neXF, Tcode, XFcode, XFcode }, | |
241 | { neP, Tcode, Pcode, Pcode }, | |
242 | { -1, -1, -1, -1 }, | |
243 | }; | |
244 | ||
245 | /* Unary operator tables. */ | |
246 | struct unary_operator optab_negate_expr[] = { | |
247 | { negSI, SIcode, SIcode }, | |
248 | { negDI, DIcode, DIcode }, | |
249 | { negSF, SFcode, SFcode }, | |
250 | { negDF, DFcode, DFcode }, | |
251 | { negXF, XFcode, XFcode }, | |
252 | { -1, -1, -1 }, | |
253 | }; | |
254 | ||
255 | struct unary_operator optab_bit_not_expr[] = { | |
256 | { notSI, SIcode, SIcode }, | |
257 | { notDI, DIcode, DIcode }, | |
258 | { -1, -1, -1 }, | |
259 | }; | |
260 | ||
261 | struct unary_operator optab_truth_not_expr[] = { | |
262 | { notT, SIcode, SIcode }, | |
263 | { -1, -1, -1 }, | |
264 | }; | |
265 | ||
266 | /* Increment operator tables. */ | |
267 | struct increment_operator optab_predecrement_expr[] = { | |
268 | { predecQI, QIcode }, | |
269 | { predecQI, QUcode }, | |
270 | { predecHI, HIcode }, | |
271 | { predecHI, HUcode }, | |
272 | { predecSI, SIcode }, | |
273 | { predecSI, SUcode }, | |
274 | { predecDI, DIcode }, | |
275 | { predecDI, DUcode }, | |
276 | { predecP, Pcode }, | |
277 | { predecSF, SFcode }, | |
278 | { predecDF, DFcode }, | |
279 | { predecXF, XFcode }, | |
280 | { -1, -1 }, | |
281 | }; | |
282 | ||
283 | struct increment_operator optab_preincrement_expr[] = { | |
284 | { preincQI, QIcode }, | |
285 | { preincQI, QUcode }, | |
286 | { preincHI, HIcode }, | |
287 | { preincHI, HUcode }, | |
288 | { preincSI, SIcode }, | |
289 | { preincSI, SUcode }, | |
290 | { preincDI, DIcode }, | |
291 | { preincDI, DUcode }, | |
292 | { preincP, Pcode }, | |
293 | { preincSF, SFcode }, | |
294 | { preincDF, DFcode }, | |
295 | { preincXF, XFcode }, | |
296 | { -1, -1 }, | |
297 | }; | |
298 | ||
299 | struct increment_operator optab_postdecrement_expr[] = { | |
300 | { postdecQI, QIcode }, | |
301 | { postdecQI, QUcode }, | |
302 | { postdecHI, HIcode }, | |
303 | { postdecHI, HUcode }, | |
304 | { postdecSI, SIcode }, | |
305 | { postdecSI, SUcode }, | |
306 | { postdecDI, DIcode }, | |
307 | { postdecDI, DUcode }, | |
308 | { postdecP, Pcode }, | |
309 | { postdecSF, SFcode }, | |
310 | { postdecDF, DFcode }, | |
311 | { postdecXF, XFcode }, | |
312 | { -1, -1 }, | |
313 | }; | |
314 | ||
315 | struct increment_operator optab_postincrement_expr[] = { | |
316 | { postincQI, QIcode }, | |
317 | { postincQI, QUcode }, | |
318 | { postincHI, HIcode }, | |
319 | { postincHI, HUcode }, | |
320 | { postincSI, SIcode }, | |
321 | { postincSI, SUcode }, | |
322 | { postincDI, DIcode }, | |
323 | { postincDI, DUcode }, | |
324 | { postincP, Pcode }, | |
325 | { postincSF, SFcode }, | |
326 | { postincDF, DFcode }, | |
327 | { postincXF, XFcode }, | |
328 | { -1, -1 }, | |
329 | }; | |
330 | ||
331 | /* Table of conversions supported by the interpreter. */ | |
332 | static struct conversion_info | |
333 | { | |
334 | enum bytecode_opcode opcode; /* here indicates the conversion needs no opcode. */ | |
335 | enum typecode from; | |
336 | enum typecode to; | |
337 | int cost; /* 1 for no-op conversions, 2 for widening conversions, | |
338 | 4 for int/float conversions, 8 for narrowing conversions. */ | |
339 | } conversion_info[] = { | |
340 | { -1, QIcode, QUcode, 1 }, | |
341 | { -1, HIcode, HUcode, 1 }, | |
342 | { -1, SIcode, SUcode, 1 }, | |
343 | { -1, DIcode, DUcode, 1 }, | |
344 | { -1, QUcode, QIcode, 1 }, | |
345 | { -1, HUcode, HIcode, 1 }, | |
346 | { -1, SUcode, SIcode, 1 }, | |
347 | { -1, DUcode, DIcode, 1 }, | |
348 | { -1, Tcode, SIcode, 1 }, | |
349 | { convertQIHI, QIcode, HIcode, 2 }, | |
350 | { convertQUHU, QUcode, HUcode, 2 }, | |
351 | { convertQUSU, QUcode, SUcode, 2 }, | |
352 | { convertHISI, HIcode, SIcode, 2 }, | |
353 | { convertHUSU, HUcode, SUcode, 2 }, | |
354 | { convertSIDI, SIcode, DIcode, 2 }, | |
355 | { convertSUDU, SUcode, DUcode, 2 }, | |
356 | { convertSFDF, SFcode, DFcode, 2 }, | |
357 | { convertDFXF, DFcode, XFcode, 2 }, | |
358 | { convertHIQI, HIcode, QIcode, 8 }, | |
359 | { convertSIQI, SIcode, QIcode, 8 }, | |
360 | { convertSIHI, SIcode, HIcode, 8 }, | |
361 | { convertSUQU, SUcode, QUcode, 8 }, | |
362 | { convertDISI, DIcode, SIcode, 8 }, | |
363 | { convertDFSF, DFcode, SFcode, 8 }, | |
364 | { convertXFDF, XFcode, DFcode, 8 }, | |
365 | { convertPSI, Pcode, SIcode, 2 }, | |
366 | { convertSIP, SIcode, Pcode, 2 }, | |
367 | { convertSIT, SIcode, Tcode, 2 }, | |
368 | { convertDIT, DIcode, Tcode, 2 }, | |
369 | { convertSFT, SFcode, Tcode, 2 }, | |
370 | { convertDFT, DFcode, Tcode, 2 }, | |
371 | { convertXFT, XFcode, Tcode, 2 }, | |
372 | { convertQISI, QIcode, SIcode, 2 }, | |
373 | { convertPT, Pcode, Tcode, 2 }, | |
374 | { convertSISF, SIcode, SFcode, 4 }, | |
375 | { convertSIDF, SIcode, DFcode, 4 }, | |
376 | { convertSIXF, SIcode, XFcode, 4 }, | |
377 | { convertSUSF, SUcode, SFcode, 4 }, | |
378 | { convertSUDF, SUcode, DFcode, 4 }, | |
379 | { convertSUXF, SUcode, XFcode, 4 }, | |
380 | { convertDISF, DIcode, SFcode, 4 }, | |
381 | { convertDIDF, DIcode, DFcode, 4 }, | |
382 | { convertDIXF, DIcode, XFcode, 4 }, | |
383 | { convertDUSF, DUcode, SFcode, 4 }, | |
384 | { convertDUDF, DUcode, DFcode, 4 }, | |
385 | { convertDUXF, DUcode, XFcode, 4 }, | |
386 | { convertSFSI, SFcode, SIcode, 4 }, | |
387 | { convertDFSI, DFcode, SIcode, 4 }, | |
388 | { convertXFSI, XFcode, SIcode, 4 }, | |
389 | { convertSFSU, SFcode, SUcode, 4 }, | |
390 | { convertDFSU, DFcode, SUcode, 4 }, | |
391 | { convertXFSU, XFcode, SUcode, 4 }, | |
392 | { convertSFDI, SFcode, DIcode, 4 }, | |
393 | { convertDFDI, DFcode, DIcode, 4 }, | |
394 | { convertXFDI, XFcode, DIcode, 4 }, | |
395 | { convertSFDU, SFcode, DUcode, 4 }, | |
396 | { convertDFDU, DFcode, DUcode, 4 }, | |
397 | { convertXFDU, XFcode, DUcode, 4 }, | |
398 | { convertSIQI, SIcode, QIcode, 8 }, | |
399 | }; | |
400 | ||
401 | #define NUM_CONVERSIONS (sizeof conversion_info / sizeof (struct conversion_info)) | |
402 | ||
403 | /* List form of a conversion recipe. */ | |
404 | struct conversion_list | |
405 | { | |
406 | enum bytecode_opcode opcode; | |
407 | enum typecode to; | |
408 | int cost; | |
409 | struct conversion_list *prev; | |
410 | }; | |
411 | ||
412 | /* Determine if it is "reasonable" to add a given conversion to | |
413 | a given list of conversions. The following criteria define | |
414 | "reasonable" conversion lists: | |
415 | * No typecode appears more than once in the sequence (no loops). | |
416 | * At most one conversion from integer to float or vice versa is present. | |
417 | * Either sign extensions or zero extensions may be present, but not both. | |
418 | * No widening conversions occur after a signed/unsigned conversion. | |
419 | * The sequence of sizes must be strict nonincreasing or nondecreasing. */ | |
0f41302f | 420 | |
86d7f2db JB |
421 | static int |
422 | conversion_reasonable_p (conversion, list) | |
423 | struct conversion_info *conversion; | |
424 | struct conversion_list *list; | |
425 | { | |
426 | struct conversion_list *curr; | |
427 | int curr_size, prev_size; | |
428 | int has_int_float, has_float_int; | |
429 | int has_sign_extend, has_zero_extend; | |
430 | int has_signed_unsigned, has_unsigned_signed; | |
431 | ||
432 | has_int_float = 0; | |
433 | has_float_int = 0; | |
434 | has_sign_extend = 0; | |
435 | has_zero_extend = 0; | |
436 | has_signed_unsigned = 0; | |
437 | has_unsigned_signed = 0; | |
438 | ||
439 | /* Make sure the destination typecode doesn't already appear in | |
440 | the list. */ | |
441 | for (curr = list; curr; curr = curr->prev) | |
442 | if (conversion->to == curr->to) | |
443 | return 0; | |
444 | ||
445 | /* Check for certain kinds of conversions. */ | |
446 | if (TYPECODE_INTEGER_P (conversion->from) | |
447 | && TYPECODE_FLOAT_P (conversion->to)) | |
448 | has_int_float = 1; | |
449 | if (TYPECODE_FLOAT_P (conversion->from) | |
450 | && TYPECODE_INTEGER_P (conversion->to)) | |
451 | has_float_int = 1; | |
452 | if (TYPECODE_SIGNED_P (conversion->from) | |
453 | && TYPECODE_SIGNED_P (conversion->to) | |
454 | && GET_TYPECODE_SIZE (conversion->from) | |
455 | < GET_TYPECODE_SIZE (conversion->to)) | |
456 | has_sign_extend = 1; | |
457 | if (TYPECODE_UNSIGNED_P (conversion->from) | |
458 | && TYPECODE_UNSIGNED_P (conversion->to) | |
459 | && GET_TYPECODE_SIZE (conversion->from) | |
460 | < GET_TYPECODE_SIZE (conversion->to)) | |
461 | has_zero_extend = 1; | |
462 | ||
463 | for (curr = list; curr && curr->prev; curr = curr->prev) | |
464 | { | |
465 | if (TYPECODE_INTEGER_P (curr->prev->to) | |
466 | && TYPECODE_FLOAT_P (curr->to)) | |
467 | has_int_float = 1; | |
468 | if (TYPECODE_FLOAT_P (curr->prev->to) | |
469 | && TYPECODE_INTEGER_P (curr->to)) | |
470 | has_float_int = 1; | |
471 | if (TYPECODE_SIGNED_P (curr->prev->to) | |
472 | && TYPECODE_SIGNED_P (curr->to) | |
473 | && GET_TYPECODE_SIZE (curr->prev->to) | |
474 | < GET_TYPECODE_SIZE (curr->to)) | |
475 | has_sign_extend = 1; | |
476 | if (TYPECODE_UNSIGNED_P (curr->prev->to) | |
477 | && TYPECODE_UNSIGNED_P (curr->to) | |
478 | && GET_TYPECODE_SIZE (curr->prev->to) | |
479 | < GET_TYPECODE_SIZE (curr->to)) | |
480 | has_zero_extend = 1; | |
481 | if (TYPECODE_SIGNED_P (curr->prev->to) | |
482 | && TYPECODE_UNSIGNED_P (curr->to)) | |
483 | has_signed_unsigned = 1; | |
484 | if (TYPECODE_UNSIGNED_P (curr->prev->to) | |
485 | && TYPECODE_SIGNED_P (curr->to)) | |
486 | has_unsigned_signed = 1; | |
487 | } | |
488 | ||
489 | if (TYPECODE_INTEGER_P (conversion->from) | |
490 | && TYPECODE_INTEGER_P (conversion->to) | |
491 | && GET_TYPECODE_SIZE (conversion->to) | |
492 | > GET_TYPECODE_SIZE (conversion->from) | |
493 | && (has_signed_unsigned || has_unsigned_signed)) | |
494 | return 0; | |
495 | ||
496 | if (has_float_int && has_int_float || has_sign_extend && has_zero_extend) | |
497 | return 0; | |
498 | ||
499 | /* Make sure the sequence of destination typecode sizes is | |
500 | strictly nondecreasing or strictly nonincreasing. */ | |
501 | prev_size = GET_TYPECODE_SIZE (conversion->to); | |
502 | for (curr = list; curr; curr = curr->prev) | |
503 | { | |
504 | curr_size = GET_TYPECODE_SIZE (curr->to); | |
505 | if (curr_size != prev_size) | |
506 | break; | |
507 | } | |
508 | if (!curr) | |
509 | return 1; | |
510 | ||
511 | if (curr_size < prev_size) | |
512 | for (prev_size = curr_size; curr; curr = curr->prev) | |
513 | { | |
514 | curr_size = GET_TYPECODE_SIZE (curr->to); | |
515 | if (curr_size > prev_size) | |
516 | return 0; | |
517 | prev_size = curr_size; | |
518 | } | |
519 | else | |
520 | for (prev_size = curr_size; curr; curr = curr->prev) | |
521 | { | |
522 | curr_size = GET_TYPECODE_SIZE (curr->to); | |
523 | if (curr_size < prev_size) | |
524 | return 0; | |
525 | prev_size = curr_size; | |
526 | } | |
527 | return 1; | |
528 | } | |
529 | ||
530 | ||
531 | /* Exhaustively search all reasonable conversions to find one to | |
532 | convert the given types. */ | |
0f41302f | 533 | |
86d7f2db JB |
534 | static struct conversion_recipe |
535 | deduce_conversion (from, to) | |
536 | enum typecode from, to; | |
537 | { | |
538 | struct rl | |
539 | { | |
540 | struct conversion_list *list; | |
541 | struct rl *next; | |
542 | } *prev, curr, *good, *temp; | |
543 | struct conversion_list *conv, *best; | |
544 | int i, cost, bestcost; | |
545 | struct conversion_recipe result; | |
546 | struct obstack recipe_obstack; | |
547 | ||
548 | ||
549 | obstack_init (&recipe_obstack); | |
550 | curr.next = (struct rl *) obstack_alloc (&recipe_obstack, sizeof (struct rl)); | |
e3da301d MS |
551 | curr.next->list |
552 | = (struct conversion_list *) obstack_alloc (&recipe_obstack, | |
553 | sizeof (struct conversion_list)); | |
86d7f2db JB |
554 | curr.next->list->opcode = -1; |
555 | curr.next->list->to = from; | |
556 | curr.next->list->cost = 0; | |
557 | curr.next->list->prev = 0; | |
558 | curr.next->next = 0; | |
559 | good = 0; | |
560 | ||
561 | while (curr.next) | |
562 | { | |
563 | /* Remove successful conversions from further consideration. */ | |
564 | for (prev = &curr; prev; prev = prev->next) | |
565 | if (prev->next && prev->next->list->to == to) | |
566 | { | |
567 | temp = prev->next->next; | |
568 | prev->next->next = good; | |
569 | good = prev->next; | |
570 | prev->next = temp; | |
571 | } | |
572 | ||
573 | /* Go through each of the pending conversion chains, trying | |
574 | all possible candidate conversions on them. */ | |
575 | for (prev = curr.next, curr.next = 0; prev; prev = prev->next) | |
576 | for (i = 0; i < NUM_CONVERSIONS; ++i) | |
577 | if (conversion_info[i].from == prev->list->to | |
578 | && conversion_reasonable_p (&conversion_info[i], prev->list)) | |
579 | { | |
580 | temp = (struct rl *) obstack_alloc (&recipe_obstack, | |
581 | sizeof (struct rl)); | |
582 | temp->list = (struct conversion_list *) | |
583 | obstack_alloc (&recipe_obstack, | |
584 | sizeof (struct conversion_list)); | |
585 | temp->list->opcode = conversion_info[i].opcode; | |
586 | temp->list->to = conversion_info[i].to; | |
587 | temp->list->cost = conversion_info[i].cost; | |
588 | temp->list->prev = prev->list; | |
589 | temp->next = curr.next; | |
590 | curr.next = temp; | |
591 | } | |
592 | } | |
593 | ||
594 | bestcost = BIG_ARBITRARY_NUMBER; | |
595 | best = 0; | |
596 | for (temp = good; temp; temp = temp->next) | |
597 | { | |
598 | for (conv = temp->list, cost = 0; conv; conv = conv->prev) | |
599 | cost += conv->cost; | |
600 | if (cost < bestcost) | |
601 | { | |
602 | bestcost = cost; | |
603 | best = temp->list; | |
604 | } | |
605 | } | |
606 | ||
607 | if (!best) | |
608 | abort (); | |
609 | ||
610 | for (i = 0, conv = best; conv; conv = conv->prev) | |
611 | if (conv->opcode != -1) | |
612 | ++i; | |
613 | ||
614 | result.opcodes = (unsigned char *) xmalloc (i); | |
615 | result.nopcodes = i; | |
616 | for (conv = best; conv; conv = conv->prev) | |
617 | if (conv->opcode != -1) | |
618 | result.opcodes[--i] = conv->opcode; | |
619 | result.cost = bestcost; | |
620 | obstack_free (&recipe_obstack, 0); | |
621 | return result; | |
622 | } | |
623 | ||
f0afa4a2 RK |
624 | #define DEDUCE_CONVERSION(FROM, TO) \ |
625 | (conversion_recipe[(int) FROM][(int) TO].opcodes ? 0 \ | |
626 | : (conversion_recipe[(int) FROM][(int) TO] \ | |
627 | = deduce_conversion (FROM, TO), 0)) | |
86d7f2db JB |
628 | |
629 | ||
630 | /* Emit a conversion between the given scalar types. */ | |
0f41302f | 631 | |
86d7f2db JB |
632 | void |
633 | emit_typecode_conversion (from, to) | |
634 | enum typecode from, to; | |
635 | { | |
636 | int i; | |
637 | ||
638 | DEDUCE_CONVERSION (from, to); | |
f0afa4a2 RK |
639 | for (i = 0; i < conversion_recipe[(int) from][(int) to].nopcodes; ++i) |
640 | bc_emit_instruction (conversion_recipe[(int) from][(int) to].opcodes[i]); | |
86d7f2db JB |
641 | } |
642 | ||
643 | ||
644 | /* Initialize mode_to_code_map[] */ | |
0f41302f | 645 | |
86d7f2db JB |
646 | void |
647 | bc_init_mode_to_code_map () | |
648 | { | |
649 | int mode; | |
650 | ||
651 | for (mode = 0; mode < MAX_MACHINE_MODE + 1; mode++) | |
652 | { | |
e3da301d MS |
653 | signed_mode_to_code_map[mode] |
654 | = unsigned_mode_to_code_map[mode] | |
655 | = LAST_AND_UNUSED_TYPECODE; | |
86d7f2db JB |
656 | } |
657 | ||
658 | #define DEF_MODEMAP(SYM, CODE, UCODE, CONST, LOAD, STORE) \ | |
f0afa4a2 RK |
659 | { signed_mode_to_code_map[(int) SYM] = CODE; \ |
660 | unsigned_mode_to_code_map[(int) SYM] = UCODE; } | |
86d7f2db JB |
661 | #include "modemap.def" |
662 | #undef DEF_MODEMAP | |
663 | ||
664 | /* Initialize opcode maps for const, load, and store */ | |
665 | bc_init_mode_to_opcode_maps (); | |
666 | } | |
667 | ||
668 | /* Given a machine mode return the preferred typecode. */ | |
0f41302f | 669 | |
86d7f2db JB |
670 | enum typecode |
671 | preferred_typecode (mode, unsignedp) | |
672 | enum machine_mode mode; | |
673 | int unsignedp; | |
674 | { | |
675 | enum typecode code = (unsignedp | |
676 | ? unsigned_mode_to_code_map | |
f0afa4a2 RK |
677 | : signed_mode_to_code_map) [MIN ((int) mode, |
678 | (int) MAX_MACHINE_MODE)]; | |
86d7f2db JB |
679 | |
680 | if (code == LAST_AND_UNUSED_TYPECODE) | |
681 | abort (); | |
682 | ||
683 | return code; | |
684 | } | |
685 | ||
686 | ||
687 | /* Expand a conversion between the given types. */ | |
0f41302f | 688 | |
86d7f2db JB |
689 | void |
690 | bc_expand_conversion (from, to) | |
691 | tree from, to; | |
692 | { | |
693 | enum typecode fcode, tcode; | |
694 | ||
695 | fcode = preferred_typecode (TYPE_MODE (from), TREE_UNSIGNED (from)); | |
696 | tcode = preferred_typecode (TYPE_MODE (to), TREE_UNSIGNED (to)); | |
697 | ||
698 | emit_typecode_conversion (fcode, tcode); | |
699 | } | |
700 | ||
701 | /* Expand a conversion of the given type to a truth value. */ | |
0f41302f | 702 | |
86d7f2db JB |
703 | void |
704 | bc_expand_truth_conversion (from) | |
705 | tree from; | |
706 | { | |
707 | enum typecode fcode; | |
708 | ||
709 | fcode = preferred_typecode (TYPE_MODE (from), TREE_UNSIGNED (from)); | |
710 | emit_typecode_conversion (fcode, Tcode); | |
711 | } | |
712 | ||
713 | /* Emit an appropriate binary operation. */ | |
0f41302f | 714 | |
86d7f2db JB |
715 | void |
716 | bc_expand_binary_operation (optab, resulttype, arg0, arg1) | |
717 | struct binary_operator optab[]; | |
718 | tree resulttype, arg0, arg1; | |
719 | { | |
720 | int i, besti, cost, bestcost; | |
721 | enum typecode resultcode, arg0code, arg1code; | |
722 | ||
723 | resultcode = preferred_typecode (TYPE_MODE (resulttype), TREE_UNSIGNED (resulttype)); | |
724 | arg0code = preferred_typecode (TYPE_MODE (TREE_TYPE (arg0)), TREE_UNSIGNED (resulttype)); | |
725 | arg1code = preferred_typecode (TYPE_MODE (TREE_TYPE (arg1)), TREE_UNSIGNED (resulttype)); | |
726 | ||
727 | besti = -1; | |
728 | bestcost = BIG_ARBITRARY_NUMBER; | |
729 | ||
730 | for (i = 0; optab[i].opcode != -1; ++i) | |
731 | { | |
732 | cost = 0; | |
733 | DEDUCE_CONVERSION (arg0code, optab[i].arg0); | |
f0afa4a2 | 734 | cost += conversion_recipe[(int) arg0code][(int) optab[i].arg0].cost; |
86d7f2db | 735 | DEDUCE_CONVERSION (arg1code, optab[i].arg1); |
f0afa4a2 | 736 | cost += conversion_recipe[(int) arg1code][(int) optab[i].arg1].cost; |
86d7f2db JB |
737 | if (cost < bestcost) |
738 | { | |
739 | besti = i; | |
740 | bestcost = cost; | |
741 | } | |
742 | } | |
743 | ||
744 | if (besti == -1) | |
745 | abort (); | |
746 | ||
542ed971 | 747 | expand_expr (arg1, 0, VOIDmode, 0); |
86d7f2db | 748 | emit_typecode_conversion (arg1code, optab[besti].arg1); |
542ed971 | 749 | expand_expr (arg0, 0, VOIDmode, 0); |
86d7f2db JB |
750 | emit_typecode_conversion (arg0code, optab[besti].arg0); |
751 | bc_emit_instruction (optab[besti].opcode); | |
752 | emit_typecode_conversion (optab[besti].result, resultcode); | |
753 | } | |
754 | ||
755 | /* Emit an appropriate unary operation. */ | |
0f41302f | 756 | |
86d7f2db JB |
757 | void |
758 | bc_expand_unary_operation (optab, resulttype, arg0) | |
759 | struct unary_operator optab[]; | |
760 | tree resulttype, arg0; | |
761 | { | |
762 | int i, besti, cost, bestcost; | |
763 | enum typecode resultcode, arg0code; | |
764 | ||
765 | resultcode = preferred_typecode (TYPE_MODE (resulttype), TREE_UNSIGNED (resulttype)); | |
766 | arg0code = preferred_typecode (TYPE_MODE (TREE_TYPE (arg0)), TREE_UNSIGNED (TREE_TYPE (arg0))); | |
767 | ||
768 | besti = -1; | |
769 | bestcost = BIG_ARBITRARY_NUMBER; | |
770 | ||
771 | for (i = 0; optab[i].opcode != -1; ++i) | |
772 | { | |
773 | DEDUCE_CONVERSION (arg0code, optab[i].arg0); | |
f0afa4a2 | 774 | cost = conversion_recipe[(int) arg0code][(int) optab[i].arg0].cost; |
86d7f2db JB |
775 | if (cost < bestcost) |
776 | { | |
777 | besti = i; | |
778 | bestcost = cost; | |
779 | } | |
780 | } | |
781 | ||
782 | if (besti == -1) | |
783 | abort (); | |
784 | ||
542ed971 | 785 | expand_expr (arg0, 0, VOIDmode, 0); |
86d7f2db JB |
786 | emit_typecode_conversion (arg0code, optab[besti].arg0); |
787 | bc_emit_instruction (optab[besti].opcode); | |
788 | emit_typecode_conversion (optab[besti].result, resultcode); | |
789 | } | |
790 | ||
791 | ||
792 | /* Emit an appropriate increment. */ | |
0f41302f | 793 | |
86d7f2db JB |
794 | void |
795 | bc_expand_increment (optab, type) | |
796 | struct increment_operator optab[]; | |
797 | tree type; | |
798 | { | |
799 | enum typecode code; | |
800 | int i; | |
801 | ||
802 | code = preferred_typecode (TYPE_MODE (type), TREE_UNSIGNED (type)); | |
f0afa4a2 | 803 | for (i = 0; (int) optab[i].opcode >= 0; ++i) |
86d7f2db JB |
804 | if (code == optab[i].arg) |
805 | { | |
806 | bc_emit_instruction (optab[i].opcode); | |
807 | return; | |
808 | } | |
809 | abort (); | |
810 | } |