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