]>
Commit | Line | Data |
---|---|---|
377029eb | 1 | /* Handle types for the GNU compiler for the Java(TM) language. |
ead29d98 | 2 | Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008 |
f060a027 | 3 | Free Software Foundation, Inc. |
377029eb | 4 | |
7d82ed5e | 5 | This file is part of GCC. |
377029eb | 6 | |
7d82ed5e | 7 | GCC is free software; you can redistribute it and/or modify |
377029eb | 8 | it under the terms of the GNU General Public License as published by |
e4b52719 | 9 | the Free Software Foundation; either version 3, or (at your option) |
377029eb | 10 | any later version. |
11 | ||
7d82ed5e | 12 | GCC is distributed in the hope that it will be useful, |
377029eb | 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 | |
e4b52719 | 18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. | |
377029eb | 20 | |
21 | Java and all Java-based marks are trademarks or registered trademarks | |
22 | of Sun Microsystems, Inc. in the United States and other countries. | |
23 | The Free Software Foundation is independent of Sun Microsystems, Inc. */ | |
24 | ||
25 | /* Written by Per Bothner <bothner@cygnus.com> */ | |
26 | ||
27 | #include "config.h" | |
014e6e0c | 28 | #include "system.h" |
805e22b2 | 29 | #include "coretypes.h" |
30 | #include "tm.h" | |
377029eb | 31 | #include "tree.h" |
ef258422 | 32 | #include "real.h" |
377029eb | 33 | #include "obstack.h" |
5bc73f94 | 34 | #include "flags.h" |
377029eb | 35 | #include "java-tree.h" |
36 | #include "jcf.h" | |
37 | #include "convert.h" | |
014e6e0c | 38 | #include "toplev.h" |
a4e59c31 | 39 | #include "ggc.h" |
377029eb | 40 | |
6852521a | 41 | static tree convert_ieee_real_to_integer (tree, tree); |
42 | static tree parse_signature_type (const unsigned char **, | |
43 | const unsigned char *); | |
af74ab68 | 44 | static tree lookup_do (tree, int, tree, tree, tree (*)(tree)); |
6852521a | 45 | static tree build_null_signature (tree); |
68ddcc2a | 46 | |
377029eb | 47 | tree * type_map; |
377029eb | 48 | |
49 | /* Set the type of the local variable with index SLOT to TYPE. */ | |
50 | ||
51 | void | |
2883a3ed | 52 | set_local_type (int slot, tree type) |
377029eb | 53 | { |
54 | int max_locals = DECL_MAX_LOCALS(current_function_decl); | |
55 | int nslots = TYPE_IS_WIDE (type) ? 2 : 1; | |
f060a027 | 56 | |
bc031ffe | 57 | gcc_assert (slot >= 0 && (slot + nslots - 1 < max_locals)); |
f060a027 | 58 | |
377029eb | 59 | type_map[slot] = type; |
60 | while (--nslots > 0) | |
61 | type_map[++slot] = void_type_node; | |
62 | } | |
63 | ||
5bc73f94 | 64 | /* Convert an IEEE real to an integer type. The result of such a |
65 | conversion when the source operand is a NaN isn't defined by | |
e2416019 | 66 | IEEE754, but by the Java language standard: it must be zero. Also, |
67 | overflows must be clipped to within range. This conversion | |
68 | produces something like: | |
69 | ||
70 | ((expr >= (float)MAX_INT) | |
71 | ? MAX_INT | |
72 | : ((expr <= (float)MIN_INT) | |
73 | ? MIN_INT | |
74 | : ((expr != expr) | |
75 | ? 0 | |
76 | : (int)expr))) */ | |
5bc73f94 | 77 | |
78 | static tree | |
2883a3ed | 79 | convert_ieee_real_to_integer (tree type, tree expr) |
5bc73f94 | 80 | { |
e2416019 | 81 | tree result; |
504ffe42 | 82 | expr = save_expr (expr); |
5bc73f94 | 83 | |
7662002a | 84 | result = fold_build3 (COND_EXPR, type, |
85 | fold_build2 (NE_EXPR, boolean_type_node, expr, expr), | |
01e7db56 | 86 | convert (type, integer_zero_node), |
7662002a | 87 | convert_to_integer (type, expr)); |
01e7db56 | 88 | |
7662002a | 89 | result = fold_build3 (COND_EXPR, type, |
90 | fold_build2 (LE_EXPR, boolean_type_node, expr, | |
91 | convert (TREE_TYPE (expr), | |
92 | TYPE_MIN_VALUE (type))), | |
93 | TYPE_MIN_VALUE (type), | |
94 | result); | |
01e7db56 | 95 | |
7662002a | 96 | result = fold_build3 (COND_EXPR, type, |
97 | fold_build2 (GE_EXPR, boolean_type_node, expr, | |
98 | convert (TREE_TYPE (expr), | |
99 | TYPE_MAX_VALUE (type))), | |
100 | TYPE_MAX_VALUE (type), | |
101 | result); | |
e2416019 | 102 | |
103 | return result; | |
5bc73f94 | 104 | } |
105 | ||
377029eb | 106 | /* Create an expression whose value is that of EXPR, |
107 | converted to type TYPE. The TREE_TYPE of the value | |
108 | is always TYPE. This function implements all reasonable | |
109 | conversions; callers should filter out those that are | |
110 | not permitted by the language being compiled. */ | |
111 | ||
112 | tree | |
2883a3ed | 113 | convert (tree type, tree expr) |
377029eb | 114 | { |
fdbb243d | 115 | enum tree_code code = TREE_CODE (type); |
377029eb | 116 | |
d95aff3a | 117 | if (!expr) |
118 | return error_mark_node; | |
119 | ||
377029eb | 120 | if (type == TREE_TYPE (expr) |
121 | || TREE_CODE (expr) == ERROR_MARK) | |
122 | return expr; | |
123 | if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) | |
124 | return error_mark_node; | |
5bc73f94 | 125 | if (code == VOID_TYPE) |
126 | return build1 (CONVERT_EXPR, type, expr); | |
ea347d91 | 127 | if (code == BOOLEAN_TYPE) |
322f4e4e | 128 | return fold_convert (type, expr); |
377029eb | 129 | if (code == INTEGER_TYPE) |
5bc73f94 | 130 | { |
ea347d91 | 131 | if (type == char_type_node || type == promoted_char_type_node) |
132 | return fold_convert (type, expr); | |
6548e808 | 133 | if ((really_constant_p (expr) || ! flag_unsafe_math_optimizations) |
95117350 | 134 | && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE) |
7662002a | 135 | return convert_ieee_real_to_integer (type, expr); |
5bc73f94 | 136 | else |
4cf8321f | 137 | { |
138 | /* fold very helpfully sets the overflow status if a type | |
139 | overflows in a narrowing integer conversion, but Java | |
140 | doesn't care. */ | |
141 | tree tmp = fold (convert_to_integer (type, expr)); | |
46fb328e | 142 | if (TREE_CODE (tmp) == INTEGER_CST) |
143 | TREE_OVERFLOW (tmp) = 0; | |
4cf8321f | 144 | return tmp; |
145 | } | |
5bc73f94 | 146 | } |
377029eb | 147 | if (code == REAL_TYPE) |
148 | return fold (convert_to_real (type, expr)); | |
377029eb | 149 | if (code == POINTER_TYPE) |
150 | return fold (convert_to_pointer (type, expr)); | |
151 | error ("conversion to non-scalar type requested"); | |
152 | return error_mark_node; | |
153 | } | |
154 | ||
5bc73f94 | 155 | |
377029eb | 156 | /* Return a data type that has machine mode MODE. |
157 | If the mode is an integer, | |
158 | then UNSIGNEDP selects between signed and unsigned types. */ | |
159 | ||
160 | tree | |
2883a3ed | 161 | java_type_for_mode (enum machine_mode mode, int unsignedp) |
377029eb | 162 | { |
163 | if (mode == TYPE_MODE (int_type_node)) | |
164 | return unsignedp ? unsigned_int_type_node : int_type_node; | |
165 | if (mode == TYPE_MODE (long_type_node)) | |
166 | return unsignedp ? unsigned_long_type_node : long_type_node; | |
167 | if (mode == TYPE_MODE (short_type_node)) | |
168 | return unsignedp ? unsigned_short_type_node : short_type_node; | |
169 | if (mode == TYPE_MODE (byte_type_node)) | |
170 | return unsignedp ? unsigned_byte_type_node : byte_type_node; | |
171 | if (mode == TYPE_MODE (float_type_node)) | |
172 | return float_type_node; | |
173 | if (mode == TYPE_MODE (double_type_node)) | |
174 | return double_type_node; | |
175 | ||
377029eb | 176 | return 0; |
177 | } | |
178 | ||
179 | /* Return an integer type with BITS bits of precision, | |
180 | that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */ | |
181 | ||
182 | tree | |
2883a3ed | 183 | java_type_for_size (unsigned bits, int unsignedp) |
377029eb | 184 | { |
185 | if (bits <= TYPE_PRECISION (byte_type_node)) | |
186 | return unsignedp ? unsigned_byte_type_node : byte_type_node; | |
187 | if (bits <= TYPE_PRECISION (short_type_node)) | |
188 | return unsignedp ? unsigned_short_type_node : short_type_node; | |
189 | if (bits <= TYPE_PRECISION (int_type_node)) | |
190 | return unsignedp ? unsigned_int_type_node : int_type_node; | |
191 | if (bits <= TYPE_PRECISION (long_type_node)) | |
192 | return unsignedp ? unsigned_long_type_node : long_type_node; | |
193 | return 0; | |
194 | } | |
195 | ||
377029eb | 196 | /* Mark EXP saying that we need to be able to take the |
197 | address of it; it should not be allocated in a register. | |
9b86eec0 | 198 | Value is true if successful. */ |
377029eb | 199 | |
9b86eec0 | 200 | bool |
2883a3ed | 201 | java_mark_addressable (tree exp) |
377029eb | 202 | { |
fdbb243d | 203 | tree x = exp; |
377029eb | 204 | while (1) |
205 | switch (TREE_CODE (x)) | |
206 | { | |
207 | case ADDR_EXPR: | |
208 | case COMPONENT_REF: | |
209 | case ARRAY_REF: | |
210 | case REALPART_EXPR: | |
211 | case IMAGPART_EXPR: | |
212 | x = TREE_OPERAND (x, 0); | |
213 | break; | |
214 | ||
215 | case TRUTH_ANDIF_EXPR: | |
216 | case TRUTH_ORIF_EXPR: | |
217 | case COMPOUND_EXPR: | |
218 | x = TREE_OPERAND (x, 1); | |
219 | break; | |
220 | ||
221 | case COND_EXPR: | |
9b86eec0 | 222 | return java_mark_addressable (TREE_OPERAND (x, 1)) |
223 | && java_mark_addressable (TREE_OPERAND (x, 2)); | |
377029eb | 224 | |
225 | case CONSTRUCTOR: | |
226 | TREE_ADDRESSABLE (x) = 1; | |
9b86eec0 | 227 | return true; |
377029eb | 228 | |
229 | case INDIRECT_REF: | |
230 | /* We sometimes add a cast *(TYPE*)&FOO to handle type and mode | |
231 | incompatibility problems. Handle this case by marking FOO. */ | |
232 | if (TREE_CODE (TREE_OPERAND (x, 0)) == NOP_EXPR | |
233 | && TREE_CODE (TREE_OPERAND (TREE_OPERAND (x, 0), 0)) == ADDR_EXPR) | |
234 | { | |
235 | x = TREE_OPERAND (TREE_OPERAND (x, 0), 0); | |
236 | break; | |
237 | } | |
238 | if (TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR) | |
239 | { | |
240 | x = TREE_OPERAND (x, 0); | |
241 | break; | |
242 | } | |
9b86eec0 | 243 | return true; |
377029eb | 244 | |
245 | case VAR_DECL: | |
246 | case CONST_DECL: | |
247 | case PARM_DECL: | |
248 | case RESULT_DECL: | |
249 | case FUNCTION_DECL: | |
250 | TREE_ADDRESSABLE (x) = 1; | |
251 | #if 0 /* poplevel deals with this now. */ | |
252 | if (DECL_CONTEXT (x) == 0) | |
253 | TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1; | |
254 | #endif | |
255 | /* drops through */ | |
256 | default: | |
9b86eec0 | 257 | return true; |
377029eb | 258 | } |
259 | } | |
260 | ||
261 | /* Thorough checking of the arrayness of TYPE. */ | |
262 | ||
263 | int | |
2883a3ed | 264 | is_array_type_p (tree type) |
377029eb | 265 | { |
266 | return TREE_CODE (type) == POINTER_TYPE | |
267 | && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE | |
268 | && TYPE_ARRAY_P (TREE_TYPE (type)); | |
269 | } | |
270 | ||
271 | /* Return the length of a Java array type. | |
272 | Return -1 if the length is unknown or non-constant. */ | |
273 | ||
274 | HOST_WIDE_INT | |
2883a3ed | 275 | java_array_type_length (tree array_type) |
377029eb | 276 | { |
277 | tree arfld; | |
278 | if (TREE_CODE (array_type) == POINTER_TYPE) | |
279 | array_type = TREE_TYPE (array_type); | |
280 | arfld = TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (array_type))); | |
281 | if (arfld != NULL_TREE) | |
282 | { | |
283 | tree index_type = TYPE_DOMAIN (TREE_TYPE (arfld)); | |
0b241033 | 284 | if (index_type != NULL_TREE) |
285 | { | |
286 | tree high = TYPE_MAX_VALUE (index_type); | |
287 | if (TREE_CODE (high) == INTEGER_CST) | |
288 | return TREE_INT_CST_LOW (high) + 1; | |
289 | } | |
377029eb | 290 | } |
291 | return -1; | |
292 | } | |
293 | ||
7a974467 | 294 | /* An array of unknown length will be ultimately given a length of |
7158d1b0 | 295 | -2, so that we can still have `length' producing a negative value |
4f9026a9 | 296 | even if found. This was part of an optimization aiming at removing |
7158d1b0 | 297 | `length' from static arrays. We could restore it, FIXME. */ |
298 | ||
377029eb | 299 | tree |
2883a3ed | 300 | build_prim_array_type (tree element_type, HOST_WIDE_INT length) |
377029eb | 301 | { |
0b241033 | 302 | tree index = NULL; |
303 | ||
304 | if (length != -1) | |
305 | { | |
7016c612 | 306 | tree max_index = build_int_cst (sizetype, length - 1); |
0b241033 | 307 | index = build_index_type (max_index); |
308 | } | |
309 | return build_array_type (element_type, index); | |
377029eb | 310 | } |
311 | ||
312 | /* Return a Java array type with a given ELEMENT_TYPE and LENGTH. | |
313 | These are hashed (shared) using IDENTIFIER_SIGNATURE_TYPE. | |
314 | The LENGTH is -1 if the length is unknown. */ | |
315 | ||
316 | tree | |
2883a3ed | 317 | build_java_array_type (tree element_type, HOST_WIDE_INT length) |
377029eb | 318 | { |
7158d1b0 | 319 | tree sig, t, fld, atype, arfld; |
65bf3316 | 320 | char buf[23]; |
377029eb | 321 | tree elsig = build_java_signature (element_type); |
322 | tree el_name = element_type; | |
3f35e9ca | 323 | buf[0] = '['; |
324 | if (length >= 0) | |
325 | sprintf (buf+1, HOST_WIDE_INT_PRINT_DEC, length); | |
326 | else | |
327 | buf[1] = '\0'; | |
377029eb | 328 | sig = ident_subst (IDENTIFIER_POINTER (elsig), IDENTIFIER_LENGTH (elsig), |
329 | buf, 0, 0, ""); | |
330 | t = IDENTIFIER_SIGNATURE_TYPE (sig); | |
331 | if (t != NULL_TREE) | |
eae37fcb | 332 | return TREE_TYPE (t); |
377029eb | 333 | t = make_class (); |
eae37fcb | 334 | IDENTIFIER_SIGNATURE_TYPE (sig) = build_pointer_type (t); |
377029eb | 335 | TYPE_ARRAY_P (t) = 1; |
336 | ||
337 | if (TREE_CODE (el_name) == POINTER_TYPE) | |
338 | el_name = TREE_TYPE (el_name); | |
339 | el_name = TYPE_NAME (el_name); | |
340 | if (TREE_CODE (el_name) == TYPE_DECL) | |
341 | el_name = DECL_NAME (el_name); | |
469e4af3 | 342 | { |
d71e1701 | 343 | char suffix[23]; |
469e4af3 | 344 | if (length >= 0) |
345 | sprintf (suffix, "[%d]", (int)length); | |
346 | else | |
347 | strcpy (suffix, "[]"); | |
348 | TYPE_NAME (t) | |
f7220491 | 349 | = TYPE_STUB_DECL (t) |
e60a6f7b | 350 | = build_decl (input_location, TYPE_DECL, |
469e4af3 | 351 | identifier_subst (el_name, "", '.', '.', suffix), |
61080c29 | 352 | t); |
f7220491 | 353 | TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (t)) = true; |
469e4af3 | 354 | } |
377029eb | 355 | |
356 | set_java_signature (t, sig); | |
357 | set_super_info (0, t, object_type_node, 0); | |
eae37fcb | 358 | if (TREE_CODE (element_type) == RECORD_TYPE) |
359 | element_type = promote_type (element_type); | |
377029eb | 360 | TYPE_ARRAY_ELEMENT (t) = element_type; |
361 | ||
362 | /* Add length pseudo-field. */ | |
e60a6f7b | 363 | fld = build_decl (input_location, |
364 | FIELD_DECL, get_identifier ("length"), int_type_node); | |
377029eb | 365 | TYPE_FIELDS (t) = fld; |
366 | DECL_CONTEXT (fld) = t; | |
367 | FIELD_PUBLIC (fld) = 1; | |
368 | FIELD_FINAL (fld) = 1; | |
61080c29 | 369 | TREE_READONLY (fld) = 1; |
370 | ||
7158d1b0 | 371 | atype = build_prim_array_type (element_type, length); |
e60a6f7b | 372 | arfld = build_decl (input_location, |
373 | FIELD_DECL, get_identifier ("data"), atype); | |
7158d1b0 | 374 | DECL_CONTEXT (arfld) = t; |
375 | TREE_CHAIN (fld) = arfld; | |
376 | DECL_ALIGN (arfld) = TYPE_ALIGN (element_type); | |
377029eb | 377 | |
36393fed | 378 | /* We could layout_class, but that loads java.lang.Object prematurely. |
379 | * This is called by the parser, and it is a bad idea to do load_class | |
380 | * in the middle of parsing, because of possible circularity problems. */ | |
381 | push_super_field (t, object_type_node); | |
382 | layout_type (t); | |
383 | ||
377029eb | 384 | return t; |
385 | } | |
386 | ||
387 | /* Promote TYPE to the type actually used for fields and parameters. */ | |
388 | ||
389 | tree | |
2883a3ed | 390 | promote_type (tree type) |
377029eb | 391 | { |
392 | switch (TREE_CODE (type)) | |
393 | { | |
394 | case RECORD_TYPE: | |
e6ec293d | 395 | return build_pointer_type (type); |
377029eb | 396 | case BOOLEAN_TYPE: |
397 | if (type == boolean_type_node) | |
398 | return promoted_boolean_type_node; | |
399 | goto handle_int; | |
ea347d91 | 400 | case INTEGER_TYPE: |
377029eb | 401 | if (type == char_type_node) |
402 | return promoted_char_type_node; | |
377029eb | 403 | handle_int: |
404 | if (TYPE_PRECISION (type) < TYPE_PRECISION (int_type_node)) | |
405 | { | |
406 | if (type == short_type_node) | |
407 | return promoted_short_type_node; | |
408 | if (type == byte_type_node) | |
409 | return promoted_byte_type_node; | |
410 | return int_type_node; | |
411 | } | |
412 | /* ... else fall through ... */ | |
413 | default: | |
414 | return type; | |
415 | } | |
416 | } | |
417 | ||
418 | /* Parse a signature string, starting at *PTR and ending at LIMIT. | |
419 | Return the seen TREE_TYPE, updating *PTR. */ | |
420 | ||
421 | static tree | |
2883a3ed | 422 | parse_signature_type (const unsigned char **ptr, const unsigned char *limit) |
377029eb | 423 | { |
eae37fcb | 424 | tree type; |
bc031ffe | 425 | gcc_assert (*ptr < limit); |
f060a027 | 426 | |
427 | switch (**ptr) | |
377029eb | 428 | { |
429 | case 'B': (*ptr)++; return byte_type_node; | |
430 | case 'C': (*ptr)++; return char_type_node; | |
431 | case 'D': (*ptr)++; return double_type_node; | |
432 | case 'F': (*ptr)++; return float_type_node; | |
433 | case 'S': (*ptr)++; return short_type_node; | |
434 | case 'I': (*ptr)++; return int_type_node; | |
435 | case 'J': (*ptr)++; return long_type_node; | |
436 | case 'Z': (*ptr)++; return boolean_type_node; | |
437 | case 'V': (*ptr)++; return void_type_node; | |
438 | case '[': | |
65c439eb | 439 | for ((*ptr)++; (*ptr) < limit && ISDIGIT (**ptr); ) (*ptr)++; |
eae37fcb | 440 | type = parse_signature_type (ptr, limit); |
441 | type = build_java_array_type (type, -1); | |
442 | break; | |
377029eb | 443 | case 'L': |
444 | { | |
445 | const unsigned char *start = ++(*ptr); | |
fdbb243d | 446 | const unsigned char *str = start; |
377029eb | 447 | for ( ; ; str++) |
448 | { | |
bc031ffe | 449 | gcc_assert (str < limit); |
377029eb | 450 | if (*str == ';') |
451 | break; | |
452 | } | |
453 | *ptr = str+1; | |
8e452f9c | 454 | type = lookup_class (unmangle_classname ((const char *) start, str - start)); |
eae37fcb | 455 | break; |
377029eb | 456 | } |
457 | default: | |
bc031ffe | 458 | gcc_unreachable (); |
377029eb | 459 | } |
eae37fcb | 460 | return promote_type (type); |
377029eb | 461 | } |
462 | ||
463 | /* Parse a Java "mangled" signature string, starting at SIG_STRING, | |
464 | and SIG_LENGTH bytes long. | |
465 | Return a gcc type node. */ | |
466 | ||
467 | tree | |
2883a3ed | 468 | parse_signature_string (const unsigned char *sig_string, int sig_length) |
377029eb | 469 | { |
470 | tree result_type; | |
471 | const unsigned char *str = sig_string; | |
472 | const unsigned char *limit = str + sig_length; | |
473 | ||
377029eb | 474 | if (str < limit && str[0] == '(') |
475 | { | |
476 | tree argtype_list = NULL_TREE; | |
477 | str++; | |
478 | while (str < limit && str[0] != ')') | |
479 | { | |
eae37fcb | 480 | tree argtype = parse_signature_type (&str, limit); |
377029eb | 481 | argtype_list = tree_cons (NULL_TREE, argtype, argtype_list); |
482 | } | |
483 | if (str++, str >= limit) | |
f060a027 | 484 | abort (); |
eae37fcb | 485 | result_type = parse_signature_type (&str, limit); |
53bfc53e | 486 | argtype_list = chainon (nreverse (argtype_list), end_params_node); |
487 | result_type = build_function_type (result_type, argtype_list); | |
377029eb | 488 | } |
489 | else | |
490 | result_type = parse_signature_type (&str, limit); | |
491 | if (str != limit) | |
492 | error ("junk at end of signature string"); | |
377029eb | 493 | return result_type; |
494 | } | |
495 | ||
496 | /* Convert a signature to its type. | |
497 | * Uses IDENTIFIER_SIGNATURE_TYPE as a cache (except for primitive types). | |
498 | */ | |
499 | ||
500 | tree | |
501 | get_type_from_signature (tree signature) | |
502 | { | |
68ddcc2a | 503 | const unsigned char *sig = (const unsigned char *) IDENTIFIER_POINTER (signature); |
377029eb | 504 | int len = IDENTIFIER_LENGTH (signature); |
505 | tree type; | |
506 | /* Primitive types aren't cached. */ | |
507 | if (len <= 1) | |
508 | return parse_signature_string (sig, len); | |
509 | type = IDENTIFIER_SIGNATURE_TYPE (signature); | |
510 | if (type == NULL_TREE) | |
511 | { | |
512 | type = parse_signature_string (sig, len); | |
513 | IDENTIFIER_SIGNATURE_TYPE (signature) = type; | |
514 | } | |
515 | return type; | |
516 | } | |
517 | ||
2aec32e1 | 518 | /* Ignore signature and always return null. Used by has_method. */ |
519 | ||
6d81beba | 520 | static tree |
2883a3ed | 521 | build_null_signature (tree type ATTRIBUTE_UNUSED) |
83b0a282 | 522 | { |
523 | return NULL_TREE; | |
524 | } | |
525 | ||
377029eb | 526 | /* Return the signature string for the arguments of method type TYPE. */ |
527 | ||
528 | tree | |
2883a3ed | 529 | build_java_argument_signature (tree type) |
377029eb | 530 | { |
531 | extern struct obstack temporary_obstack; | |
532 | tree sig = TYPE_ARGUMENT_SIGNATURE (type); | |
533 | if (sig == NULL_TREE) | |
534 | { | |
535 | tree args = TYPE_ARG_TYPES (type); | |
536 | if (TREE_CODE (type) == METHOD_TYPE) | |
537 | args = TREE_CHAIN (args); /* Skip "this" argument. */ | |
53bfc53e | 538 | for (; args != end_params_node; args = TREE_CHAIN (args)) |
377029eb | 539 | { |
540 | tree t = build_java_signature (TREE_VALUE (args)); | |
541 | obstack_grow (&temporary_obstack, | |
542 | IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t)); | |
543 | } | |
544 | obstack_1grow (&temporary_obstack, '\0'); | |
545 | ||
546 | sig = get_identifier (obstack_base (&temporary_obstack)); | |
547 | TYPE_ARGUMENT_SIGNATURE (type) = sig; | |
548 | obstack_free (&temporary_obstack, obstack_base (&temporary_obstack)); | |
549 | } | |
550 | return sig; | |
551 | } | |
552 | ||
553 | /* Return the signature of the given TYPE. */ | |
554 | ||
555 | tree | |
2883a3ed | 556 | build_java_signature (tree type) |
377029eb | 557 | { |
558 | tree sig, t; | |
377029eb | 559 | while (TREE_CODE (type) == POINTER_TYPE) |
560 | type = TREE_TYPE (type); | |
4654e794 | 561 | MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type); |
562 | sig = TYPE_SIGNATURE (type); | |
377029eb | 563 | if (sig == NULL_TREE) |
564 | { | |
565 | char sg[2]; | |
566 | switch (TREE_CODE (type)) | |
567 | { | |
568 | case BOOLEAN_TYPE: sg[0] = 'Z'; goto native; | |
377029eb | 569 | case VOID_TYPE: sg[0] = 'V'; goto native; |
570 | case INTEGER_TYPE: | |
ea347d91 | 571 | if (type == char_type_node || type == promoted_char_type_node) |
572 | { | |
573 | sg[0] = 'C'; | |
574 | goto native; | |
575 | } | |
377029eb | 576 | switch (TYPE_PRECISION (type)) |
577 | { | |
578 | case 8: sg[0] = 'B'; goto native; | |
579 | case 16: sg[0] = 'S'; goto native; | |
580 | case 32: sg[0] = 'I'; goto native; | |
581 | case 64: sg[0] = 'J'; goto native; | |
582 | default: goto bad_type; | |
583 | } | |
584 | case REAL_TYPE: | |
585 | switch (TYPE_PRECISION (type)) | |
586 | { | |
587 | case 32: sg[0] = 'F'; goto native; | |
588 | case 64: sg[0] = 'D'; goto native; | |
589 | default: goto bad_type; | |
590 | } | |
591 | native: | |
592 | sg[1] = 0; | |
593 | sig = get_identifier (sg); | |
594 | break; | |
595 | case RECORD_TYPE: | |
596 | if (TYPE_ARRAY_P (type)) | |
597 | { | |
598 | t = build_java_signature (TYPE_ARRAY_ELEMENT (type)); | |
599 | sig = ident_subst (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t), | |
600 | "[", 0, 0, ""); | |
601 | } | |
602 | else | |
603 | { | |
604 | t = DECL_NAME (TYPE_NAME (type)); | |
605 | sig = ident_subst (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t), | |
606 | "L", '.', '/', ";"); | |
607 | } | |
608 | break; | |
609 | case METHOD_TYPE: | |
610 | case FUNCTION_TYPE: | |
611 | { | |
612 | extern struct obstack temporary_obstack; | |
613 | sig = build_java_argument_signature (type); | |
614 | obstack_1grow (&temporary_obstack, '('); | |
615 | obstack_grow (&temporary_obstack, | |
616 | IDENTIFIER_POINTER (sig), IDENTIFIER_LENGTH (sig)); | |
617 | obstack_1grow (&temporary_obstack, ')'); | |
a31ac40f | 618 | |
377029eb | 619 | t = build_java_signature (TREE_TYPE (type)); |
620 | obstack_grow0 (&temporary_obstack, | |
621 | IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t)); | |
622 | ||
623 | sig = get_identifier (obstack_base (&temporary_obstack)); | |
624 | obstack_free (&temporary_obstack, | |
625 | obstack_base (&temporary_obstack)); | |
626 | } | |
627 | break; | |
628 | bad_type: | |
629 | default: | |
bc031ffe | 630 | gcc_unreachable (); |
377029eb | 631 | } |
4654e794 | 632 | TYPE_SIGNATURE (type) = sig; |
377029eb | 633 | } |
377029eb | 634 | return sig; |
635 | } | |
636 | ||
637 | /* Save signature string SIG (an IDENTIFIER_NODE) in TYPE for future use. */ | |
638 | ||
639 | void | |
2883a3ed | 640 | set_java_signature (tree type, tree sig) |
377029eb | 641 | { |
642 | tree old_sig; | |
643 | while (TREE_CODE (type) == POINTER_TYPE) | |
644 | type = TREE_TYPE (type); | |
4654e794 | 645 | MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type); |
646 | old_sig = TYPE_SIGNATURE (type); | |
377029eb | 647 | if (old_sig != NULL_TREE && old_sig != sig) |
f060a027 | 648 | abort (); |
4654e794 | 649 | TYPE_SIGNATURE (type) = sig; |
377029eb | 650 | #if 0 /* careful about METHOD_TYPE */ |
651 | if (IDENTIFIER_SIGNATURE_TYPE (sig) == NULL_TREE && TREE_PERMANENT (type)) | |
652 | IDENTIFIER_SIGNATURE_TYPE (sig) = type; | |
653 | #endif | |
654 | } | |
655 | ||
af74ab68 | 656 | /* Search in SEARCHED_CLASS and its superclasses for a method matching |
657 | METHOD_NAME and signature METHOD_SIGNATURE. This function will | |
658 | only search for methods declared in the class hierarchy; interfaces | |
659 | will not be considered. Returns NULL_TREE if the method is not | |
660 | found. */ | |
377029eb | 661 | tree |
af74ab68 | 662 | lookup_argument_method (tree searched_class, tree method_name, |
663 | tree method_signature) | |
377029eb | 664 | { |
af74ab68 | 665 | return lookup_do (searched_class, 0, |
666 | method_name, method_signature, | |
a536b5f2 | 667 | build_java_argument_signature); |
377029eb | 668 | } |
669 | ||
af74ab68 | 670 | /* Like lookup_argument_method, but lets the caller set any flags |
671 | desired. */ | |
377029eb | 672 | tree |
af74ab68 | 673 | lookup_argument_method_generic (tree searched_class, tree method_name, |
674 | tree method_signature, int flags) | |
377029eb | 675 | { |
af74ab68 | 676 | return lookup_do (searched_class, flags, |
a536b5f2 | 677 | method_name, method_signature, |
678 | build_java_argument_signature); | |
679 | } | |
e47ee8bc | 680 | |
af74ab68 | 681 | |
a536b5f2 | 682 | /* Search in class SEARCHED_CLASS (and its superclasses) for a method |
683 | matching METHOD_NAME and signature METHOD_SIGNATURE. Return a | |
684 | FUNCTION_DECL on success, or NULL_TREE if none found. (Contrast | |
af74ab68 | 685 | lookup_argument_method, which ignores return type.) If |
a536b5f2 | 686 | SEARCHED_CLASS is an interface, search it too. */ |
a536b5f2 | 687 | tree |
af74ab68 | 688 | lookup_java_method (tree searched_class, tree method_name, |
689 | tree method_signature) | |
a536b5f2 | 690 | { |
af74ab68 | 691 | return lookup_do (searched_class, SEARCH_INTERFACE, method_name, |
a536b5f2 | 692 | method_signature, build_java_signature); |
693 | } | |
e47ee8bc | 694 | |
ead29d98 | 695 | Content-type: text/html ]>