]>
Commit | Line | Data |
---|---|---|
377029eb | 1 | /* Handle types for the GNU compiler for the Java(TM) language. |
f060a027 | 2 | Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 |
3 | Free Software Foundation, Inc. | |
377029eb | 4 | |
5 | This file is part of GNU CC. | |
6 | ||
7 | GNU CC is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GNU CC is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GNU CC; see the file COPYING. If not, write to | |
19 | the Free Software Foundation, 59 Temple Place - Suite 330, | |
20 | Boston, MA 02111-1307, USA. | |
21 | ||
22 | Java and all Java-based marks are trademarks or registered trademarks | |
23 | of Sun Microsystems, Inc. in the United States and other countries. | |
24 | The Free Software Foundation is independent of Sun Microsystems, Inc. */ | |
25 | ||
26 | /* Written by Per Bothner <bothner@cygnus.com> */ | |
27 | ||
28 | #include "config.h" | |
014e6e0c | 29 | #include "system.h" |
377029eb | 30 | #include "tree.h" |
31 | #include "obstack.h" | |
5bc73f94 | 32 | #include "flags.h" |
377029eb | 33 | #include "java-tree.h" |
34 | #include "jcf.h" | |
35 | #include "convert.h" | |
014e6e0c | 36 | #include "toplev.h" |
a4e59c31 | 37 | #include "ggc.h" |
377029eb | 38 | |
fa334f7d | 39 | static tree convert_ieee_real_to_integer PARAMS ((tree, tree)); |
40 | static tree parse_signature_type PARAMS ((const unsigned char **, | |
68ddcc2a | 41 | const unsigned char *)); |
a536b5f2 | 42 | static tree lookup_do PARAMS ((tree, tree, tree, tree, tree (*)(tree))); |
6d81beba | 43 | static tree build_null_signature PARAMS ((tree)); |
68ddcc2a | 44 | |
377029eb | 45 | tree * type_map; |
46 | extern struct obstack permanent_obstack; | |
47 | ||
48 | /* Set the type of the local variable with index SLOT to TYPE. */ | |
49 | ||
50 | void | |
51 | set_local_type (slot, type) | |
52 | int slot; | |
53 | tree type; | |
54 | { | |
55 | int max_locals = DECL_MAX_LOCALS(current_function_decl); | |
56 | int nslots = TYPE_IS_WIDE (type) ? 2 : 1; | |
f060a027 | 57 | |
377029eb | 58 | if (slot < 0 || slot + nslots - 1 >= max_locals) |
f060a027 | 59 | abort (); |
60 | ||
377029eb | 61 | type_map[slot] = type; |
62 | while (--nslots > 0) | |
63 | type_map[++slot] = void_type_node; | |
64 | } | |
65 | ||
5bc73f94 | 66 | /* Convert an IEEE real to an integer type. The result of such a |
67 | conversion when the source operand is a NaN isn't defined by | |
e2416019 | 68 | IEEE754, but by the Java language standard: it must be zero. Also, |
69 | overflows must be clipped to within range. This conversion | |
70 | produces something like: | |
71 | ||
72 | ((expr >= (float)MAX_INT) | |
73 | ? MAX_INT | |
74 | : ((expr <= (float)MIN_INT) | |
75 | ? MIN_INT | |
76 | : ((expr != expr) | |
77 | ? 0 | |
78 | : (int)expr))) */ | |
5bc73f94 | 79 | |
80 | static tree | |
81 | convert_ieee_real_to_integer (type, expr) | |
82 | tree type, expr; | |
83 | { | |
e2416019 | 84 | tree result; |
504ffe42 | 85 | expr = save_expr (expr); |
5bc73f94 | 86 | |
e2416019 | 87 | result = build (COND_EXPR, type, |
88 | build (NE_EXPR, boolean_type_node, expr, expr), | |
89 | convert (type, integer_zero_node), | |
90 | convert_to_integer (type, expr)); | |
91 | ||
92 | result = build (COND_EXPR, type, | |
93 | build (LE_EXPR, boolean_type_node, expr, | |
94 | convert (TREE_TYPE (expr), TYPE_MIN_VALUE (type))), | |
95 | TYPE_MIN_VALUE (type), | |
96 | result); | |
97 | ||
98 | result = build (COND_EXPR, type, | |
99 | build (GE_EXPR, boolean_type_node, expr, | |
100 | convert (TREE_TYPE (expr), TYPE_MAX_VALUE (type))), | |
101 | TYPE_MAX_VALUE (type), | |
102 | result); | |
103 | ||
104 | return result; | |
5bc73f94 | 105 | } |
106 | ||
377029eb | 107 | /* Create an expression whose value is that of EXPR, |
108 | converted to type TYPE. The TREE_TYPE of the value | |
109 | is always TYPE. This function implements all reasonable | |
110 | conversions; callers should filter out those that are | |
111 | not permitted by the language being compiled. */ | |
112 | ||
113 | tree | |
114 | convert (type, expr) | |
115 | tree type, expr; | |
116 | { | |
117 | register enum tree_code code = TREE_CODE (type); | |
118 | ||
d95aff3a | 119 | if (!expr) |
120 | return error_mark_node; | |
121 | ||
ff752ab9 | 122 | if (do_not_fold) |
123 | return build1 (NOP_EXPR, type, expr); | |
124 | ||
377029eb | 125 | if (type == TREE_TYPE (expr) |
126 | || TREE_CODE (expr) == ERROR_MARK) | |
127 | return expr; | |
128 | if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) | |
129 | return error_mark_node; | |
5bc73f94 | 130 | if (code == VOID_TYPE) |
131 | return build1 (CONVERT_EXPR, type, expr); | |
377029eb | 132 | if (code == BOOLEAN_TYPE) |
133 | return fold (convert_to_boolean (type, expr)); | |
134 | if (code == INTEGER_TYPE) | |
5bc73f94 | 135 | { |
7f3be425 | 136 | if (! flag_unsafe_math_optimizations |
e2416019 | 137 | && ! flag_emit_class_files |
138 | && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE | |
5bc73f94 | 139 | && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) |
140 | return fold (convert_ieee_real_to_integer (type, expr)); | |
141 | else | |
142 | return fold (convert_to_integer (type, expr)); | |
143 | } | |
377029eb | 144 | if (code == REAL_TYPE) |
145 | return fold (convert_to_real (type, expr)); | |
146 | if (code == CHAR_TYPE) | |
147 | return fold (convert_to_char (type, expr)); | |
148 | if (code == POINTER_TYPE) | |
149 | return fold (convert_to_pointer (type, expr)); | |
150 | error ("conversion to non-scalar type requested"); | |
151 | return error_mark_node; | |
152 | } | |
153 | ||
5bc73f94 | 154 | |
377029eb | 155 | tree |
156 | convert_to_char (type, expr) | |
157 | tree type, expr; | |
158 | { | |
159 | return build1 (NOP_EXPR, type, expr); | |
160 | } | |
161 | ||
162 | tree | |
163 | convert_to_boolean (type, expr) | |
164 | tree type, expr; | |
165 | { | |
166 | return build1 (NOP_EXPR, type, expr); | |
167 | } | |
168 | ||
377029eb | 169 | /* Return a data type that has machine mode MODE. |
170 | If the mode is an integer, | |
171 | then UNSIGNEDP selects between signed and unsigned types. */ | |
172 | ||
173 | tree | |
771d21fa | 174 | java_type_for_mode (mode, unsignedp) |
377029eb | 175 | enum machine_mode mode; |
176 | int unsignedp; | |
177 | { | |
178 | if (mode == TYPE_MODE (int_type_node)) | |
179 | return unsignedp ? unsigned_int_type_node : int_type_node; | |
180 | if (mode == TYPE_MODE (long_type_node)) | |
181 | return unsignedp ? unsigned_long_type_node : long_type_node; | |
182 | if (mode == TYPE_MODE (short_type_node)) | |
183 | return unsignedp ? unsigned_short_type_node : short_type_node; | |
184 | if (mode == TYPE_MODE (byte_type_node)) | |
185 | return unsignedp ? unsigned_byte_type_node : byte_type_node; | |
186 | if (mode == TYPE_MODE (float_type_node)) | |
187 | return float_type_node; | |
188 | if (mode == TYPE_MODE (double_type_node)) | |
189 | return double_type_node; | |
190 | ||
377029eb | 191 | return 0; |
192 | } | |
193 | ||
194 | /* Return an integer type with BITS bits of precision, | |
195 | that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */ | |
196 | ||
197 | tree | |
771d21fa | 198 | java_type_for_size (bits, unsignedp) |
377029eb | 199 | unsigned bits; |
200 | int unsignedp; | |
201 | { | |
202 | if (bits <= TYPE_PRECISION (byte_type_node)) | |
203 | return unsignedp ? unsigned_byte_type_node : byte_type_node; | |
204 | if (bits <= TYPE_PRECISION (short_type_node)) | |
205 | return unsignedp ? unsigned_short_type_node : short_type_node; | |
206 | if (bits <= TYPE_PRECISION (int_type_node)) | |
207 | return unsignedp ? unsigned_int_type_node : int_type_node; | |
208 | if (bits <= TYPE_PRECISION (long_type_node)) | |
209 | return unsignedp ? unsigned_long_type_node : long_type_node; | |
210 | return 0; | |
211 | } | |
212 | ||
213 | /* Return a type the same as TYPE except unsigned or | |
214 | signed according to UNSIGNEDP. */ | |
215 | ||
216 | tree | |
4070745f | 217 | java_signed_or_unsigned_type (unsignedp, type) |
377029eb | 218 | int unsignedp; |
219 | tree type; | |
220 | { | |
221 | if (! INTEGRAL_TYPE_P (type)) | |
222 | return type; | |
223 | if (TYPE_PRECISION (type) == TYPE_PRECISION (int_type_node)) | |
224 | return unsignedp ? unsigned_int_type_node : int_type_node; | |
225 | if (TYPE_PRECISION (type) == TYPE_PRECISION (byte_type_node)) | |
226 | return unsignedp ? unsigned_byte_type_node : byte_type_node; | |
227 | if (TYPE_PRECISION (type) == TYPE_PRECISION (short_type_node)) | |
228 | return unsignedp ? unsigned_short_type_node : short_type_node; | |
229 | if (TYPE_PRECISION (type) == TYPE_PRECISION (long_type_node)) | |
230 | return unsignedp ? unsigned_long_type_node : long_type_node; | |
231 | return type; | |
232 | } | |
233 | ||
234 | /* Return a signed type the same as TYPE in other respects. */ | |
235 | ||
236 | tree | |
4070745f | 237 | java_signed_type (type) |
377029eb | 238 | tree type; |
239 | { | |
4070745f | 240 | return java_signed_or_unsigned_type (0, type); |
377029eb | 241 | } |
242 | ||
243 | /* Return an unsigned type the same as TYPE in other respects. */ | |
244 | ||
245 | tree | |
4070745f | 246 | java_unsigned_type (type) |
377029eb | 247 | tree type; |
248 | { | |
4070745f | 249 | return java_signed_or_unsigned_type (1, type); |
377029eb | 250 | } |
251 | ||
252 | /* Mark EXP saying that we need to be able to take the | |
253 | address of it; it should not be allocated in a register. | |
9b86eec0 | 254 | Value is true if successful. */ |
377029eb | 255 | |
9b86eec0 | 256 | bool |
257 | java_mark_addressable (exp) | |
377029eb | 258 | tree exp; |
259 | { | |
260 | register tree x = exp; | |
261 | while (1) | |
262 | switch (TREE_CODE (x)) | |
263 | { | |
264 | case ADDR_EXPR: | |
265 | case COMPONENT_REF: | |
266 | case ARRAY_REF: | |
267 | case REALPART_EXPR: | |
268 | case IMAGPART_EXPR: | |
269 | x = TREE_OPERAND (x, 0); | |
270 | break; | |
271 | ||
272 | case TRUTH_ANDIF_EXPR: | |
273 | case TRUTH_ORIF_EXPR: | |
274 | case COMPOUND_EXPR: | |
275 | x = TREE_OPERAND (x, 1); | |
276 | break; | |
277 | ||
278 | case COND_EXPR: | |
9b86eec0 | 279 | return java_mark_addressable (TREE_OPERAND (x, 1)) |
280 | && java_mark_addressable (TREE_OPERAND (x, 2)); | |
377029eb | 281 | |
282 | case CONSTRUCTOR: | |
283 | TREE_ADDRESSABLE (x) = 1; | |
9b86eec0 | 284 | return true; |
377029eb | 285 | |
286 | case INDIRECT_REF: | |
287 | /* We sometimes add a cast *(TYPE*)&FOO to handle type and mode | |
288 | incompatibility problems. Handle this case by marking FOO. */ | |
289 | if (TREE_CODE (TREE_OPERAND (x, 0)) == NOP_EXPR | |
290 | && TREE_CODE (TREE_OPERAND (TREE_OPERAND (x, 0), 0)) == ADDR_EXPR) | |
291 | { | |
292 | x = TREE_OPERAND (TREE_OPERAND (x, 0), 0); | |
293 | break; | |
294 | } | |
295 | if (TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR) | |
296 | { | |
297 | x = TREE_OPERAND (x, 0); | |
298 | break; | |
299 | } | |
9b86eec0 | 300 | return true; |
377029eb | 301 | |
302 | case VAR_DECL: | |
303 | case CONST_DECL: | |
304 | case PARM_DECL: | |
305 | case RESULT_DECL: | |
306 | case FUNCTION_DECL: | |
307 | TREE_ADDRESSABLE (x) = 1; | |
308 | #if 0 /* poplevel deals with this now. */ | |
309 | if (DECL_CONTEXT (x) == 0) | |
310 | TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1; | |
311 | #endif | |
312 | /* drops through */ | |
313 | default: | |
9b86eec0 | 314 | return true; |
377029eb | 315 | } |
316 | } | |
317 | ||
318 | /* Thorough checking of the arrayness of TYPE. */ | |
319 | ||
320 | int | |
321 | is_array_type_p (type) | |
322 | tree type; | |
323 | { | |
324 | return TREE_CODE (type) == POINTER_TYPE | |
325 | && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE | |
326 | && TYPE_ARRAY_P (TREE_TYPE (type)); | |
327 | } | |
328 | ||
329 | /* Return the length of a Java array type. | |
330 | Return -1 if the length is unknown or non-constant. */ | |
331 | ||
332 | HOST_WIDE_INT | |
333 | java_array_type_length (array_type) | |
334 | tree array_type; | |
335 | { | |
336 | tree arfld; | |
337 | if (TREE_CODE (array_type) == POINTER_TYPE) | |
338 | array_type = TREE_TYPE (array_type); | |
339 | arfld = TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (array_type))); | |
340 | if (arfld != NULL_TREE) | |
341 | { | |
342 | tree index_type = TYPE_DOMAIN (TREE_TYPE (arfld)); | |
0b241033 | 343 | if (index_type != NULL_TREE) |
344 | { | |
345 | tree high = TYPE_MAX_VALUE (index_type); | |
346 | if (TREE_CODE (high) == INTEGER_CST) | |
347 | return TREE_INT_CST_LOW (high) + 1; | |
348 | } | |
377029eb | 349 | } |
350 | return -1; | |
351 | } | |
352 | ||
7158d1b0 | 353 | /* An array of unknown length will be ultimately given an length of |
354 | -2, so that we can still have `length' producing a negative value | |
355 | even if found. This was part of an optimization amaing at removing | |
356 | `length' from static arrays. We could restore it, FIXME. */ | |
357 | ||
377029eb | 358 | tree |
359 | build_prim_array_type (element_type, length) | |
360 | tree element_type; | |
361 | HOST_WIDE_INT length; | |
362 | { | |
0b241033 | 363 | tree index = NULL; |
364 | ||
365 | if (length != -1) | |
366 | { | |
367 | tree max_index = build_int_2 (length - 1, (0 == length ? -1 : 0)); | |
368 | TREE_TYPE (max_index) = sizetype; | |
369 | index = build_index_type (max_index); | |
370 | } | |
371 | return build_array_type (element_type, index); | |
377029eb | 372 | } |
373 | ||
374 | /* Return a Java array type with a given ELEMENT_TYPE and LENGTH. | |
375 | These are hashed (shared) using IDENTIFIER_SIGNATURE_TYPE. | |
376 | The LENGTH is -1 if the length is unknown. */ | |
377 | ||
378 | tree | |
379 | build_java_array_type (element_type, length) | |
380 | tree element_type; | |
381 | HOST_WIDE_INT length; | |
382 | { | |
7158d1b0 | 383 | tree sig, t, fld, atype, arfld; |
377029eb | 384 | char buf[12]; |
385 | tree elsig = build_java_signature (element_type); | |
386 | tree el_name = element_type; | |
3f35e9ca | 387 | buf[0] = '['; |
388 | if (length >= 0) | |
389 | sprintf (buf+1, HOST_WIDE_INT_PRINT_DEC, length); | |
390 | else | |
391 | buf[1] = '\0'; | |
377029eb | 392 | sig = ident_subst (IDENTIFIER_POINTER (elsig), IDENTIFIER_LENGTH (elsig), |
393 | buf, 0, 0, ""); | |
394 | t = IDENTIFIER_SIGNATURE_TYPE (sig); | |
395 | if (t != NULL_TREE) | |
eae37fcb | 396 | return TREE_TYPE (t); |
377029eb | 397 | t = make_class (); |
eae37fcb | 398 | IDENTIFIER_SIGNATURE_TYPE (sig) = build_pointer_type (t); |
377029eb | 399 | TYPE_ARRAY_P (t) = 1; |
400 | ||
401 | if (TREE_CODE (el_name) == POINTER_TYPE) | |
402 | el_name = TREE_TYPE (el_name); | |
403 | el_name = TYPE_NAME (el_name); | |
404 | if (TREE_CODE (el_name) == TYPE_DECL) | |
405 | el_name = DECL_NAME (el_name); | |
61080c29 | 406 | TYPE_NAME (t) = build_decl (TYPE_DECL, |
407 | identifier_subst (el_name, "", '.', '.', "[]"), | |
408 | t); | |
377029eb | 409 | |
410 | set_java_signature (t, sig); | |
411 | set_super_info (0, t, object_type_node, 0); | |
eae37fcb | 412 | if (TREE_CODE (element_type) == RECORD_TYPE) |
413 | element_type = promote_type (element_type); | |
377029eb | 414 | TYPE_ARRAY_ELEMENT (t) = element_type; |
415 | ||
416 | /* Add length pseudo-field. */ | |
377029eb | 417 | fld = build_decl (FIELD_DECL, get_identifier ("length"), int_type_node); |
418 | TYPE_FIELDS (t) = fld; | |
419 | DECL_CONTEXT (fld) = t; | |
420 | FIELD_PUBLIC (fld) = 1; | |
421 | FIELD_FINAL (fld) = 1; | |
61080c29 | 422 | TREE_READONLY (fld) = 1; |
423 | ||
7158d1b0 | 424 | atype = build_prim_array_type (element_type, length); |
425 | arfld = build_decl (FIELD_DECL, get_identifier ("data"), atype); | |
426 | DECL_CONTEXT (arfld) = t; | |
427 | TREE_CHAIN (fld) = arfld; | |
428 | DECL_ALIGN (arfld) = TYPE_ALIGN (element_type); | |
377029eb | 429 | |
36393fed | 430 | /* We could layout_class, but that loads java.lang.Object prematurely. |
431 | * This is called by the parser, and it is a bad idea to do load_class | |
432 | * in the middle of parsing, because of possible circularity problems. */ | |
433 | push_super_field (t, object_type_node); | |
434 | layout_type (t); | |
435 | ||
377029eb | 436 | return t; |
437 | } | |
438 | ||
439 | /* Promote TYPE to the type actually used for fields and parameters. */ | |
440 | ||
441 | tree | |
442 | promote_type (type) | |
443 | tree type; | |
444 | { | |
445 | switch (TREE_CODE (type)) | |
446 | { | |
447 | case RECORD_TYPE: | |
448 | return build_pointer_type (CLASS_TO_HANDLE_TYPE (type)); | |
449 | case BOOLEAN_TYPE: | |
450 | if (type == boolean_type_node) | |
451 | return promoted_boolean_type_node; | |
452 | goto handle_int; | |
453 | case CHAR_TYPE: | |
454 | if (type == char_type_node) | |
455 | return promoted_char_type_node; | |
456 | goto handle_int; | |
457 | case INTEGER_TYPE: | |
458 | handle_int: | |
459 | if (TYPE_PRECISION (type) < TYPE_PRECISION (int_type_node)) | |
460 | { | |
461 | if (type == short_type_node) | |
462 | return promoted_short_type_node; | |
463 | if (type == byte_type_node) | |
464 | return promoted_byte_type_node; | |
465 | return int_type_node; | |
466 | } | |
467 | /* ... else fall through ... */ | |
468 | default: | |
469 | return type; | |
470 | } | |
471 | } | |
472 | ||
473 | /* Parse a signature string, starting at *PTR and ending at LIMIT. | |
474 | Return the seen TREE_TYPE, updating *PTR. */ | |
475 | ||
476 | static tree | |
477 | parse_signature_type (ptr, limit) | |
478 | const unsigned char **ptr, *limit; | |
479 | { | |
eae37fcb | 480 | tree type; |
f060a027 | 481 | |
482 | if (*ptr >= limit) | |
483 | abort (); | |
484 | ||
485 | switch (**ptr) | |
377029eb | 486 | { |
487 | case 'B': (*ptr)++; return byte_type_node; | |
488 | case 'C': (*ptr)++; return char_type_node; | |
489 | case 'D': (*ptr)++; return double_type_node; | |
490 | case 'F': (*ptr)++; return float_type_node; | |
491 | case 'S': (*ptr)++; return short_type_node; | |
492 | case 'I': (*ptr)++; return int_type_node; | |
493 | case 'J': (*ptr)++; return long_type_node; | |
494 | case 'Z': (*ptr)++; return boolean_type_node; | |
495 | case 'V': (*ptr)++; return void_type_node; | |
496 | case '[': | |
65c439eb | 497 | for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); ) (*ptr)++; |
eae37fcb | 498 | type = parse_signature_type (ptr, limit); |
499 | type = build_java_array_type (type, -1); | |
500 | break; | |
377029eb | 501 | case 'L': |
502 | { | |
503 | const unsigned char *start = ++(*ptr); | |
504 | register const unsigned char *str = start; | |
505 | for ( ; ; str++) | |
506 | { | |
507 | if (str >= limit) | |
f060a027 | 508 | abort (); |
377029eb | 509 | if (*str == ';') |
510 | break; | |
511 | } | |
512 | *ptr = str+1; | |
eae37fcb | 513 | type = lookup_class (unmangle_classname (start, str - start)); |
514 | break; | |
377029eb | 515 | } |
516 | default: | |
f060a027 | 517 | abort (); |
377029eb | 518 | } |
eae37fcb | 519 | return promote_type (type); |
377029eb | 520 | } |
521 | ||
522 | /* Parse a Java "mangled" signature string, starting at SIG_STRING, | |
523 | and SIG_LENGTH bytes long. | |
524 | Return a gcc type node. */ | |
525 | ||
526 | tree | |
527 | parse_signature_string (sig_string, sig_length) | |
528 | const unsigned char *sig_string; | |
529 | int sig_length; | |
530 | { | |
531 | tree result_type; | |
532 | const unsigned char *str = sig_string; | |
533 | const unsigned char *limit = str + sig_length; | |
534 | ||
377029eb | 535 | if (str < limit && str[0] == '(') |
536 | { | |
537 | tree argtype_list = NULL_TREE; | |
538 | str++; | |
539 | while (str < limit && str[0] != ')') | |
540 | { | |
eae37fcb | 541 | tree argtype = parse_signature_type (&str, limit); |
377029eb | 542 | argtype_list = tree_cons (NULL_TREE, argtype, argtype_list); |
543 | } | |
544 | if (str++, str >= limit) | |
f060a027 | 545 | abort (); |
eae37fcb | 546 | result_type = parse_signature_type (&str, limit); |
53bfc53e | 547 | argtype_list = chainon (nreverse (argtype_list), end_params_node); |
548 | result_type = build_function_type (result_type, argtype_list); | |
377029eb | 549 | } |
550 | else | |
551 | result_type = parse_signature_type (&str, limit); | |
552 | if (str != limit) | |
553 | error ("junk at end of signature string"); | |
377029eb | 554 | return result_type; |
555 | } | |
556 | ||
557 | /* Convert a signature to its type. | |
558 | * Uses IDENTIFIER_SIGNATURE_TYPE as a cache (except for primitive types). | |
559 | */ | |
560 | ||
561 | tree | |
562 | get_type_from_signature (tree signature) | |
563 | { | |
68ddcc2a | 564 | const unsigned char *sig = (const unsigned char *) IDENTIFIER_POINTER (signature); |
377029eb | 565 | int len = IDENTIFIER_LENGTH (signature); |
566 | tree type; | |
567 | /* Primitive types aren't cached. */ | |
568 | if (len <= 1) | |
569 | return parse_signature_string (sig, len); | |
570 | type = IDENTIFIER_SIGNATURE_TYPE (signature); | |
571 | if (type == NULL_TREE) | |
572 | { | |
573 | type = parse_signature_string (sig, len); | |
574 | IDENTIFIER_SIGNATURE_TYPE (signature) = type; | |
575 | } | |
576 | return type; | |
577 | } | |
578 | ||
2aec32e1 | 579 | /* Ignore signature and always return null. Used by has_method. */ |
580 | ||
6d81beba | 581 | static tree |
83b0a282 | 582 | build_null_signature (type) |
6d81beba | 583 | tree type ATTRIBUTE_UNUSED; |
83b0a282 | 584 | { |
585 | return NULL_TREE; | |
586 | } | |
587 | ||
377029eb | 588 | /* Return the signature string for the arguments of method type TYPE. */ |
589 | ||
590 | tree | |
591 | build_java_argument_signature (type) | |
592 | tree type; | |
593 | { | |
594 | extern struct obstack temporary_obstack; | |
595 | tree sig = TYPE_ARGUMENT_SIGNATURE (type); | |
596 | if (sig == NULL_TREE) | |
597 | { | |
598 | tree args = TYPE_ARG_TYPES (type); | |
599 | if (TREE_CODE (type) == METHOD_TYPE) | |
600 | args = TREE_CHAIN (args); /* Skip "this" argument. */ | |
53bfc53e | 601 | for (; args != end_params_node; args = TREE_CHAIN (args)) |
377029eb | 602 | { |
603 | tree t = build_java_signature (TREE_VALUE (args)); | |
604 | obstack_grow (&temporary_obstack, | |
605 | IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t)); | |
606 | } | |
607 | obstack_1grow (&temporary_obstack, '\0'); | |
608 | ||
609 | sig = get_identifier (obstack_base (&temporary_obstack)); | |
610 | TYPE_ARGUMENT_SIGNATURE (type) = sig; | |
611 | obstack_free (&temporary_obstack, obstack_base (&temporary_obstack)); | |
612 | } | |
613 | return sig; | |
614 | } | |
615 | ||
616 | /* Return the signature of the given TYPE. */ | |
617 | ||
618 | tree | |
619 | build_java_signature (type) | |
620 | tree type; | |
621 | { | |
622 | tree sig, t; | |
377029eb | 623 | while (TREE_CODE (type) == POINTER_TYPE) |
624 | type = TREE_TYPE (type); | |
4654e794 | 625 | MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type); |
626 | sig = TYPE_SIGNATURE (type); | |
377029eb | 627 | if (sig == NULL_TREE) |
628 | { | |
629 | char sg[2]; | |
630 | switch (TREE_CODE (type)) | |
631 | { | |
632 | case BOOLEAN_TYPE: sg[0] = 'Z'; goto native; | |
633 | case CHAR_TYPE: sg[0] = 'C'; goto native; | |
634 | case VOID_TYPE: sg[0] = 'V'; goto native; | |
635 | case INTEGER_TYPE: | |
636 | switch (TYPE_PRECISION (type)) | |
637 | { | |
638 | case 8: sg[0] = 'B'; goto native; | |
639 | case 16: sg[0] = 'S'; goto native; | |
640 | case 32: sg[0] = 'I'; goto native; | |
641 | case 64: sg[0] = 'J'; goto native; | |
642 | default: goto bad_type; | |
643 | } | |
644 | case REAL_TYPE: | |
645 | switch (TYPE_PRECISION (type)) | |
646 | { | |
647 | case 32: sg[0] = 'F'; goto native; | |
648 | case 64: sg[0] = 'D'; goto native; | |
649 | default: goto bad_type; | |
650 | } | |
651 | native: | |
652 | sg[1] = 0; | |
653 | sig = get_identifier (sg); | |
654 | break; | |
655 | case RECORD_TYPE: | |
656 | if (TYPE_ARRAY_P (type)) | |
657 | { | |
658 | t = build_java_signature (TYPE_ARRAY_ELEMENT (type)); | |
659 | sig = ident_subst (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t), | |
660 | "[", 0, 0, ""); | |
661 | } | |
662 | else | |
663 | { | |
664 | t = DECL_NAME (TYPE_NAME (type)); | |
665 | sig = ident_subst (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t), | |
666 | "L", '.', '/', ";"); | |
667 | } | |
668 | break; | |
669 | case METHOD_TYPE: | |
670 | case FUNCTION_TYPE: | |
671 | { | |
672 | extern struct obstack temporary_obstack; | |
673 | sig = build_java_argument_signature (type); | |
674 | obstack_1grow (&temporary_obstack, '('); | |
675 | obstack_grow (&temporary_obstack, | |
676 | IDENTIFIER_POINTER (sig), IDENTIFIER_LENGTH (sig)); | |
677 | obstack_1grow (&temporary_obstack, ')'); | |
a31ac40f | 678 | |
377029eb | 679 | t = build_java_signature (TREE_TYPE (type)); |
680 | obstack_grow0 (&temporary_obstack, | |
681 | IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t)); | |
682 | ||
683 | sig = get_identifier (obstack_base (&temporary_obstack)); | |
684 | obstack_free (&temporary_obstack, | |
685 | obstack_base (&temporary_obstack)); | |
686 | } | |
687 | break; | |
688 | bad_type: | |
689 | default: | |
f060a027 | 690 | abort (); |
377029eb | 691 | } |
4654e794 | 692 | TYPE_SIGNATURE (type) = sig; |
377029eb | 693 | } |
377029eb | 694 | return sig; |
695 | } | |
696 | ||
697 | /* Save signature string SIG (an IDENTIFIER_NODE) in TYPE for future use. */ | |
698 | ||
699 | void | |
700 | set_java_signature (type, sig) | |
701 | tree type; | |
702 | tree sig; | |
703 | { | |
704 | tree old_sig; | |
705 | while (TREE_CODE (type) == POINTER_TYPE) | |
706 | type = TREE_TYPE (type); | |
4654e794 | 707 | MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type); |
708 | old_sig = TYPE_SIGNATURE (type); | |
377029eb | 709 | if (old_sig != NULL_TREE && old_sig != sig) |
f060a027 | 710 | abort (); |
4654e794 | 711 | TYPE_SIGNATURE (type) = sig; |
377029eb | 712 | #if 0 /* careful about METHOD_TYPE */ |
713 | if (IDENTIFIER_SIGNATURE_TYPE (sig) == NULL_TREE && TREE_PERMANENT (type)) | |
714 | IDENTIFIER_SIGNATURE_TYPE (sig) = type; | |
715 | #endif | |
716 | } | |
717 | ||
a536b5f2 | 718 | /* Search in class SEARCHED_CLASS (and its superclasses) for a method |
719 | matching METHOD_NAME and signature SIGNATURE. If SEARCHED_INTERFACE is | |
720 | not NULL_TREE then first search its superinterfaces for a similar match. | |
721 | Return the matched method DECL or NULL_TREE. SIGNATURE_BUILDER is | |
722 | used on method candidates to build their (sometimes partial) | |
723 | signature. */ | |
377029eb | 724 | |
725 | tree | |
a536b5f2 | 726 | lookup_argument_method (searched_class, method_name, method_signature) |
727 | tree searched_class, method_name, method_signature; | |
377029eb | 728 | { |
a536b5f2 | 729 | return lookup_do (searched_class, NULL_TREE, method_name, method_signature, |
730 | build_java_argument_signature); | |
377029eb | 731 | } |
732 | ||
a536b5f2 | 733 | /* Search in class SEARCHED_CLASS (and its superclasses and |
734 | implemented interfaces) for a method matching METHOD_NAME and | |
735 | argument signature METHOD_SIGNATURE. Return a FUNCTION_DECL on | |
736 | success, or NULL_TREE if none found. (Contrast lookup_java_method, | |
737 | which takes into account return type.) */ | |
377029eb | 738 | |
739 | tree | |
a536b5f2 | 740 | lookup_argument_method2 (searched_class, method_name, method_signature) |
e47ee8bc | 741 | tree searched_class, method_name, method_signature; |
377029eb | 742 | { |
a536b5f2 | 743 | return lookup_do (CLASSTYPE_SUPER (searched_class), searched_class, |
744 | method_name, method_signature, | |
745 | build_java_argument_signature); | |
746 | } | |
e47ee8bc | 747 | |
a536b5f2 | 748 | /* Search in class SEARCHED_CLASS (and its superclasses) for a method |
749 | matching METHOD_NAME and signature METHOD_SIGNATURE. Return a | |
750 | FUNCTION_DECL on success, or NULL_TREE if none found. (Contrast | |
751 | lookup_argument_method, which ignores return type.) If | |
752 | SEARCHED_CLASS is an interface, search it too. */ | |
a2cad990 | 753 | |
a536b5f2 | 754 | tree |
755 | lookup_java_method (searched_class, method_name, method_signature) | |
756 | tree searched_class, method_name, method_signature; | |
757 | { | |
758 | tree searched_interface; | |
759 | ||
760 | /* If this class is an interface class, search its superinterfaces | |
761 | * first. A superinterface is not an interface's superclass: a super | |
762 | * interface is implemented by the interface. */ | |
763 | ||
764 | searched_interface = (CLASS_INTERFACE (TYPE_NAME (searched_class)) ? | |
765 | searched_class : NULL_TREE); | |
766 | return lookup_do (searched_class, searched_interface, method_name, | |
767 | method_signature, build_java_signature); | |
768 | } | |
e47ee8bc | 769 | |
83b0a282 | 770 | /* Return true iff CLASS (or its ancestors) has a method METHOD_NAME. */ |
771 | ||
772 | int | |
773 | has_method (class, method_name) | |
774 | tree class; | |
775 | tree method_name; | |
776 | { | |
777 | return lookup_do (class, class, method_name, | |
778 | NULL_TREE, build_null_signature) != NULL_TREE; | |
779 | } | |
780 | ||
781 | /* Search in class SEARCHED_CLASS (and its superclasses) for a method | |
a536b5f2 | 782 | matching METHOD_NAME and signature SIGNATURE. Also search in |
83b0a282 | 783 | SEARCHED_INTERFACE (and its superinterfaces) for a similar match. |
a536b5f2 | 784 | Return the matched method DECL or NULL_TREE. SIGNATURE_BUILDER is |
785 | used on method candidates to build their (sometimes partial) | |
786 | signature. */ | |
e47ee8bc | 787 | |
a536b5f2 | 788 | static tree |
789 | lookup_do (searched_class, searched_interface, method_name, signature, signature_builder) | |
790 | tree searched_class, searched_interface, method_name, signature; | |
791 | tree (*signature_builder) PARAMS ((tree)); | |
792 | { | |
793 | tree method; | |
794 | ||
795 | if (searched_interface) | |
e47ee8bc | 796 | { |
797 | int i; | |
798 | int interface_len = | |
a536b5f2 | 799 | TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (searched_interface)) - 1; |
e47ee8bc | 800 | |
801 | for (i = interface_len; i > 0; i--) | |
802 | { | |
803 | tree child = | |
a536b5f2 | 804 | TREE_VEC_ELT (TYPE_BINFO_BASETYPES (searched_interface), i); |
e47ee8bc | 805 | tree iclass = BINFO_TYPE (child); |
806 | ||
807 | /* If the superinterface hasn't been loaded yet, do so now. */ | |
a536b5f2 | 808 | if (CLASS_FROM_SOURCE_P (iclass)) |
809 | safe_layout_class (iclass); | |
810 | else if (!CLASS_LOADED_P (iclass)) | |
811 | load_class (iclass, 1); | |
e47ee8bc | 812 | |
813 | for (method = TYPE_METHODS (iclass); | |
814 | method != NULL_TREE; method = TREE_CHAIN (method)) | |
815 | { | |
a536b5f2 | 816 | tree method_sig = (*signature_builder) (TREE_TYPE (method)); |
e47ee8bc | 817 | |
cbce943b | 818 | if (DECL_NAME (method) == method_name && method_sig == signature) |
e47ee8bc | 819 | return method; |
820 | } | |
821 | ||
822 | /* it could be defined in a supersuperinterface */ | |
823 | if (CLASS_INTERFACE (TYPE_NAME (iclass))) | |
824 | { | |
a536b5f2 | 825 | method = lookup_do (iclass, iclass, method_name, |
826 | signature, signature_builder); | |
e47ee8bc | 827 | if (method != NULL_TREE) |
828 | return method; | |
829 | } | |
830 | } | |
377029eb | 831 | } |
a536b5f2 | 832 | |
833 | while (searched_class != NULL_TREE) | |
834 | { | |
835 | for (method = TYPE_METHODS (searched_class); | |
836 | method != NULL_TREE; method = TREE_CHAIN (method)) | |
837 | { | |
838 | tree method_sig = (*signature_builder) (TREE_TYPE (method)); | |
cbce943b | 839 | if (DECL_NAME (method) == method_name && method_sig == signature) |
a536b5f2 | 840 | return method; |
841 | } | |
842 | searched_class = CLASSTYPE_SUPER (searched_class); | |
843 | } | |
844 | ||
377029eb | 845 | return NULL_TREE; |
846 | } | |
847 | ||
377029eb | 848 | /* Search in class CLAS for a constructor matching METHOD_SIGNATURE. |
849 | Return a FUNCTION_DECL on success, or NULL_TREE if none found. */ | |
850 | ||
851 | tree | |
852 | lookup_java_constructor (clas, method_signature) | |
853 | tree clas, method_signature; | |
854 | { | |
855 | tree method = TYPE_METHODS (clas); | |
856 | for ( ; method != NULL_TREE; method = TREE_CHAIN (method)) | |
857 | { | |
858 | tree method_sig = build_java_signature (TREE_TYPE (method)); | |
859 | if (DECL_CONSTRUCTOR_P (method) && method_sig == method_signature) | |
860 | return method; | |
861 | } | |
862 | return NULL_TREE; | |
863 | } | |
864 | ||
865 | /* Return a type which is the Binary Numeric Promotion of the pair T1, | |
866 | T2 and convert EXP1 and/or EXP2. See 5.6.2 Binary Numeric | |
583cfadb | 867 | Promotion. It assumes that both T1 and T2 are eligible to BNP. */ |
377029eb | 868 | |
869 | tree | |
870 | binary_numeric_promotion (t1, t2, exp1, exp2) | |
871 | tree t1; | |
872 | tree t2; | |
873 | tree *exp1; | |
874 | tree *exp2; | |
875 | { | |
876 | if (t1 == double_type_node || t2 == double_type_node) | |
877 | { | |
878 | if (t1 != double_type_node) | |
879 | *exp1 = convert (double_type_node, *exp1); | |
880 | if (t2 != double_type_node) | |
881 | *exp2 = convert (double_type_node, *exp2); | |
882 | return double_type_node; | |
883 | } | |
884 | if (t1 == float_type_node || t2 == float_type_node) | |
885 | { | |
886 | if (t1 != float_type_node) | |
887 | *exp1 = convert (float_type_node, *exp1); | |
888 | if (t2 != float_type_node) | |
889 | *exp2 = convert (float_type_node, *exp2); | |
890 | return float_type_node; | |
891 | } | |
892 | if (t1 == long_type_node || t2 == long_type_node) | |
893 | { | |
894 | if (t1 != long_type_node) | |
895 | *exp1 = convert (long_type_node, *exp1); | |
896 | if (t2 != long_type_node) | |
897 | *exp2 = convert (long_type_node, *exp2); | |
898 | return long_type_node; | |
899 | } | |
900 | ||
901 | if (t1 != int_type_node) | |
902 | *exp1 = convert (int_type_node, *exp1); | |
903 | if (t2 != int_type_node) | |
904 | *exp2 = convert (int_type_node, *exp2); | |
905 | return int_type_node; | |
906 | } |