PR testsuite/44195
[official-gcc.git] / gcc / java / mangle.c
blobc6a753fa61d8e49cf8b2e16165d256f7b25c3394
1 /* Functions related to mangling class names for the GNU compiler
2 for the Java(TM) language.
3 Copyright (C) 1998, 1999, 2001, 2002, 2003, 2006, 2007, 2008
4 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>.
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. */
26 /* Written by Per Bothner <bothner@cygnus.com> */
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "jcf.h"
32 #include "tree.h"
33 #include "java-tree.h"
34 #include "obstack.h"
35 #include "toplev.h"
36 #include "ggc.h"
37 #include "langhooks-def.h"
38 #include "tm.h" /* FIXME: For gcc_obstack_init from defaults.h. */
40 static void mangle_class_field (tree);
41 static void mangle_vtable (tree);
42 static void mangle_field_decl (tree);
43 static void mangle_method_decl (tree);
44 static void mangle_local_cni_method_decl (tree);
46 static void mangle_type (tree);
47 static void mangle_pointer_type (tree);
48 static void mangle_array_type (tree);
49 static int mangle_record_type (tree, int);
51 static int find_compression_pointer_match (tree);
52 static int find_compression_array_match (tree);
53 static int find_compression_record_match (tree, tree *);
54 static int find_compression_array_template_match (tree);
56 static void set_type_package_list (tree);
57 static int entry_match_pointer_p (tree, int);
58 static void emit_compression_string (int);
60 static void init_mangling (void);
61 static tree finish_mangling (void);
62 static void compression_table_add (tree);
64 static void mangle_member_name (tree);
66 static struct obstack mangle_obstack_1;
67 struct obstack *mangle_obstack;
69 #define MANGLE_RAW_STRING(S) \
70 obstack_grow (mangle_obstack, (S), sizeof (S)-1)
72 /* atms: array template mangled string. */
73 static GTY(()) tree atms;
75 /* This is the mangling interface: a decl, a class field (.class) and
76 the vtable. */
78 void
79 java_mangle_decl (tree decl)
81 /* A copy of the check from the beginning of lhd_set_decl_assembler_name.
82 Only FUNCTION_DECLs and VAR_DECLs for variables with static storage
83 duration need a real DECL_ASSEMBLER_NAME. */
84 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
85 || (TREE_CODE (decl) == VAR_DECL
86 && (TREE_STATIC (decl)
87 || DECL_EXTERNAL (decl)
88 || TREE_PUBLIC (decl))));
90 /* Mangling only applies to class members. */
91 if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
93 init_mangling ();
94 switch (TREE_CODE (decl))
96 case VAR_DECL:
97 if (DECL_LANG_SPECIFIC (decl))
99 if (DECL_CLASS_FIELD_P (decl))
101 mangle_class_field (decl);
102 break;
104 else if (DECL_VTABLE_P (decl))
106 mangle_vtable (DECL_CONTEXT (decl));
107 break;
110 mangle_field_decl (decl);
111 break;
113 case FUNCTION_DECL:
114 if (DECL_LANG_SPECIFIC (decl) && DECL_LOCAL_CNI_METHOD_P (decl))
115 mangle_local_cni_method_decl (decl);
116 else
117 mangle_method_decl (decl);
118 break;
120 default:
121 gcc_unreachable ();
123 SET_DECL_ASSEMBLER_NAME (decl, finish_mangling ());
125 else
126 lhd_set_decl_assembler_name (decl);
129 /* Beginning of the helper functions */
131 static void
132 mangle_class_field (tree decl)
134 tree type = DECL_CONTEXT (decl);
135 mangle_record_type (type, /* for_pointer = */ 0);
136 if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
137 MANGLE_RAW_STRING ("6class$");
138 else
139 MANGLE_RAW_STRING ("7class$$");
140 obstack_1grow (mangle_obstack, 'E');
143 static void
144 mangle_vtable (tree type)
146 MANGLE_RAW_STRING ("TV");
147 mangle_record_type (type, /* for_pointer = */ 0);
148 obstack_1grow (mangle_obstack, 'E');
151 /* This mangles a field decl */
153 static void
154 mangle_field_decl (tree decl)
156 /* Mangle the name of the this the field belongs to */
157 mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
159 /* Mangle the name of the field */
160 mangle_member_name (DECL_NAME (decl));
162 /* Terminate the mangled name */
163 obstack_1grow (mangle_obstack, 'E');
166 /* This mangles a method decl, first mangling its name and then all
167 its arguments. */
169 static void
170 mangle_method_decl (tree mdecl)
172 tree method_name = DECL_NAME (mdecl);
173 tree arglist;
175 /* Mangle the name of the type that contains mdecl */
176 mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
178 /* Mangle the function name. There are two cases:
179 - mdecl is a constructor, use `C1' for its name, (denotes a
180 complete object constructor.)
181 - mdecl is not a constructor, standard mangling is performed.
182 We terminate the mangled function name with a `E'. */
183 if (ID_INIT_P (method_name))
184 obstack_grow (mangle_obstack, "C1", 2);
185 else
186 mangle_member_name (method_name);
187 obstack_1grow (mangle_obstack, 'E');
189 /* We mangled type.methodName. Now onto the arguments. */
190 arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
191 if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
192 arglist = TREE_CHAIN (arglist);
194 /* Output literal 'J' and mangle the return type IF not a
195 constructor. */
196 if (!ID_INIT_P (method_name))
198 obstack_1grow (mangle_obstack, 'J');
199 mangle_type(TREE_TYPE(TREE_TYPE(mdecl)));
202 /* No arguments is easy. We shortcut it. */
203 if (arglist == end_params_node)
204 obstack_1grow (mangle_obstack, 'v');
205 else
207 tree arg;
208 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
209 mangle_type (TREE_VALUE (arg));
213 /* This mangles a CNI method for a local class. If the target supports
214 hidden aliases, then G++ will have generated one for us. It is the
215 responsibility of java_mark_class_local to check target support, since
216 we need to set DECL_VISIBILITY (or not) much earlier. */
218 static void
219 mangle_local_cni_method_decl (tree decl)
221 MANGLE_RAW_STRING ("GA");
222 mangle_method_decl (decl);
225 /* This mangles a member name, like a function name or a field
226 name. Handle cases were `name' is a C++ keyword. Return a nonzero
227 value if unicode encoding was required. */
229 static void
230 mangle_member_name (tree name)
232 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
233 IDENTIFIER_LENGTH (name));
236 /* Append the mangled name of TYPE onto OBSTACK. */
238 static void
239 mangle_type (tree type)
241 switch (TREE_CODE (type))
243 char code;
244 case BOOLEAN_TYPE: code = 'b'; goto primitive;
245 case VOID_TYPE: code = 'v'; goto primitive;
246 case INTEGER_TYPE:
247 if (type == char_type_node || type == promoted_char_type_node)
249 code = 'w';
250 goto primitive;
252 /* Get the original type instead of the arguments promoted type.
253 Avoid symbol name clashes. Should call a function to do that.
254 FIXME. */
255 if (type == promoted_short_type_node)
256 type = short_type_node;
257 if (type == promoted_byte_type_node)
258 type = byte_type_node;
259 switch (TYPE_PRECISION (type))
261 case 8: code = 'c'; goto primitive;
262 case 16: code = 's'; goto primitive;
263 case 32: code = 'i'; goto primitive;
264 case 64: code = 'x'; goto primitive;
265 default: goto bad_type;
267 primitive:
268 obstack_1grow (mangle_obstack, code);
269 break;
271 case REAL_TYPE:
272 switch (TYPE_PRECISION (type))
274 case 32: code = 'f'; goto primitive;
275 case 64: code = 'd'; goto primitive;
276 default: goto bad_type;
278 case POINTER_TYPE:
279 if (TYPE_ARRAY_P (TREE_TYPE (type)))
280 mangle_array_type (type);
281 else
282 mangle_pointer_type (type);
283 break;
284 bad_type:
285 default:
286 gcc_unreachable ();
290 /* The compression table is a vector that keeps track of things we've
291 already seen, so they can be reused. For example, java.lang.Object
292 would generate three entries: two package names and a type. If
293 java.lang.String is presented next, the java.lang will be matched
294 against the first two entries (and kept for compression as S0_), and
295 type String would be added to the table. See mangle_record_type.
296 COMPRESSION_NEXT is the index to the location of the next insertion
297 of an element. */
299 static GTY(()) tree compression_table;
300 static int compression_next;
302 /* Find a POINTER_TYPE in the compression table. Use a special
303 function to match pointer entries and start from the end */
305 static int
306 find_compression_pointer_match (tree type)
308 int i;
310 for (i = compression_next-1; i >= 0; i--)
311 if (entry_match_pointer_p (type, i))
312 return i;
313 return -1;
316 /* Already recorder arrays are handled like pointer as they're always
317 associated with it. */
319 static int
320 find_compression_array_match (tree type)
322 return find_compression_pointer_match (type);
325 /* Match the table of type against STRING. */
327 static int
328 find_compression_array_template_match (tree string)
330 int i;
331 for (i = 0; i < compression_next; i++)
332 if (TREE_VEC_ELT (compression_table, i) == string)
333 return i;
334 return -1;
337 /* We go through the compression table and try to find a complete or
338 partial match. The function returns the compression table entry
339 that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
340 to the rest of TYPE to be mangled. */
342 static int
343 find_compression_record_match (tree type, tree *next_current)
345 int i, match = -1;
346 tree current, saved_current = NULL_TREE;
348 current = TYPE_PACKAGE_LIST (type);
350 for (i = 0; i < compression_next; i++)
352 tree compression_entry = TREE_VEC_ELT (compression_table, i);
353 if (current && compression_entry == TREE_PURPOSE (current))
355 match = i;
356 saved_current = current;
357 current = TREE_CHAIN (current);
359 else
360 /* We don't want to match an element that appears in the middle
361 of a package name, so skip forward to the next complete type name.
362 IDENTIFIER_NODEs (except for a "6JArray") are partial package
363 names while RECORD_TYPEs represent complete type names. */
364 while (i < compression_next
365 && TREE_CODE (compression_entry) == IDENTIFIER_NODE
366 && compression_entry != atms)
367 compression_entry = TREE_VEC_ELT (compression_table, ++i);
370 if (!next_current)
371 return match;
373 /* If we have a match, set next_current to the item next to the last
374 matched value. */
375 if (match >= 0)
376 *next_current = TREE_CHAIN (saved_current);
377 /* We had no match: we'll have to start from the beginning. */
378 if (match < 0)
379 *next_current = TYPE_PACKAGE_LIST (type);
381 return match;
384 /* Mangle a record type. If a nonzero value is returned, it means
385 that a 'N' was emitted (so that a matching 'E' can be emitted if
386 necessary.) FOR_POINTER indicates that this element is for a pointer
387 symbol, meaning it was preceded by a 'P'. */
389 static int
390 mangle_record_type (tree type, int for_pointer)
392 tree current;
393 int match;
394 int nadded_p = 0;
395 int qualified;
397 /* Does this name have a package qualifier? */
398 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
400 #define ADD_N() \
401 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
403 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
405 if (!TYPE_PACKAGE_LIST (type))
406 set_type_package_list (type);
408 match = find_compression_record_match (type, &current);
409 if (match >= 0)
411 /* If we had a pointer, and there's more, we need to emit
412 'N' after 'P' (for_pointer tells us we already emitted it.) */
413 if (for_pointer && current)
414 ADD_N();
415 emit_compression_string (match);
417 while (current)
419 /* Add the new type to the table */
420 compression_table_add (TREE_PURPOSE (current));
421 /* Add 'N' if we never got a chance to, but only if we have a qualified
422 name. For non-pointer elements, the name is always qualified. */
423 if ((qualified || !for_pointer) && !nadded_p)
424 ADD_N();
425 /* Use the bare type name for the mangle. */
426 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
427 IDENTIFIER_LENGTH (TREE_VALUE (current)));
428 current = TREE_CHAIN (current);
430 return nadded_p;
431 #undef ADD_N
434 /* Mangle a pointer type. There are two cases: the pointer is already
435 in the compression table: the compression is emitted sans 'P'
436 indicator. Otherwise, a 'P' is emitted and, depending on the type,
437 a partial compression or/plus the rest of the mangling. */
439 static void
440 mangle_pointer_type (tree type)
442 int match;
443 tree pointer_type;
445 /* Search for the type already in the compression table */
446 if ((match = find_compression_pointer_match (type)) >= 0)
448 emit_compression_string (match);
449 return;
452 /* This didn't work. We start by mangling the pointed-to type */
453 pointer_type = type;
454 type = TREE_TYPE (type);
455 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
457 obstack_1grow (mangle_obstack, 'P');
458 if (mangle_record_type (type, /* for_pointer = */ 1))
459 obstack_1grow (mangle_obstack, 'E');
461 /* Don't forget to insert the pointer type in the table */
462 compression_table_add (pointer_type);
465 /* Mangle an array type. Search for an easy solution first, then go
466 through the process of finding out whether the bare array type or even
467 the template indicator were already used and compressed appropriately.
468 It handles pointers. */
470 static void
471 mangle_array_type (tree p_type)
473 tree type, elt_type;
474 int match;
476 type = TREE_TYPE (p_type);
477 gcc_assert (type);
479 elt_type = TYPE_ARRAY_ELEMENT (type);
481 /* We cache a bit of the Jarray <> mangle. */
482 if (!atms)
484 atms = get_identifier ("6JArray");
487 /* Maybe we have what we're looking for in the compression table. */
488 if ((match = find_compression_array_match (p_type)) >= 0)
490 emit_compression_string (match);
491 return;
494 /* We know for a fact that all arrays are pointers */
495 obstack_1grow (mangle_obstack, 'P');
496 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
497 if ((match = find_compression_record_match (type, NULL)) > 0)
499 emit_compression_string (match);
500 return;
503 /* Maybe we already have just JArray somewhere */
504 if ((match = find_compression_array_template_match (atms)) > 0)
505 emit_compression_string (match);
506 else
508 /* Start the template mangled name */
509 obstack_grow (mangle_obstack,
510 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
511 /* Insert in the compression table */
512 compression_table_add (atms);
515 /* Mangle Jarray <elt_type> */
516 obstack_1grow (mangle_obstack, 'I');
517 mangle_type (elt_type);
518 obstack_1grow (mangle_obstack, 'E');
520 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
521 compression_table_add (type);
522 compression_table_add (p_type);
525 /* Write a substitution string for entry I. Substitution string starts a
526 -1 (encoded S_.) The base is 36, and the code shamelessly taken from
527 cp/mangle.c. */
529 static void
530 emit_compression_string (int i)
532 i -= 1; /* Adjust */
533 obstack_1grow (mangle_obstack, 'S');
534 if (i >= 0)
536 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
537 unsigned HOST_WIDE_INT n;
538 unsigned HOST_WIDE_INT m=1;
539 /* How many digits for I in base 36? */
540 for (n = i; n >= 36; n /= 36, m *=36);
541 /* Write the digits out */
542 while (m > 0)
544 int digit = i / m;
545 obstack_1grow (mangle_obstack, digits [digit]);
546 i -= digit * m;
547 m /= 36;
550 obstack_1grow (mangle_obstack, '_');
553 /* If search the compression table at index I for a pointer type
554 equivalent to TYPE (meaning that after all the indirection, which
555 might all be unique, we find the same RECORD_TYPE.) */
557 static int
558 entry_match_pointer_p (tree type, int i)
560 tree t = TREE_VEC_ELT (compression_table, i);
562 while (TREE_CODE (type) == POINTER_TYPE
563 && TREE_CODE (t) == POINTER_TYPE)
565 t = TREE_TYPE (t);
566 type = TREE_TYPE (type);
568 return (TREE_CODE (type) == RECORD_TYPE
569 && TREE_CODE (t) == RECORD_TYPE
570 && t == type);
573 /* Go through all qualification of type and build a list of list node
574 elements containings as a purpose what should be used for a match and
575 inserted in the compression table; and as it value the raw name of the
576 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
578 static void
579 set_type_package_list (tree type)
581 int i;
582 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
583 const char *ptr;
584 int qualifications;
585 tree list = NULL_TREE, elt;
587 for (ptr = type_string, qualifications = 0; *ptr; ptr++)
588 if (*ptr == '.')
589 qualifications += 1;
591 for (ptr = type_string, i = 0; i < qualifications; ptr++)
593 if (ptr [0] == '.')
595 tree const identifier
596 = get_identifier_with_length (type_string, ptr - type_string);
598 elt = build_tree_list (identifier, identifier);
599 TREE_CHAIN (elt) = list;
600 list = elt;
601 type_string = ptr+1;
602 i += 1;
606 elt = build_tree_list (type, get_identifier (type_string));
607 TREE_CHAIN (elt) = list;
608 list = elt;
609 TYPE_PACKAGE_LIST (type) = nreverse (list);
612 /* Add TYPE as the last element of the compression table. Resize the
613 compression table if necessary. */
615 static void
616 compression_table_add (tree type)
618 if (compression_next == TREE_VEC_LENGTH (compression_table))
620 tree new_table = make_tree_vec (2*compression_next);
621 int i;
623 for (i = 0; i < compression_next; i++)
624 TREE_VEC_ELT (new_table, i) = TREE_VEC_ELT (compression_table, i);
626 compression_table = new_table;
628 TREE_VEC_ELT (compression_table, compression_next++) = type;
631 /* Mangle an embedded resource file name. "_ZGr" is the prefix. A
632 '_' is prepended to the name so that names starting with a digit
633 can be demangled. The length and then the resulting name itself
634 are appended while escaping '$', '.', and '/' to: "$$", "$_", and
635 "$S". */
637 tree
638 java_mangle_resource_name (const char *name)
640 int len = strlen (name);
641 char *buf = (char *) alloca (2 * len + 1);
642 char *pos;
643 const unsigned char *w1 = (const unsigned char *) name;
644 const unsigned char *w2;
645 const unsigned char *limit = w1 + len;
647 pos = buf;
649 init_mangling ();
650 MANGLE_RAW_STRING ("Gr");
652 *pos++ = '_';
653 while (w1 < limit)
655 int ch;
656 w2 = w1;
657 ch = UTF8_GET (w1, limit);
658 gcc_assert (ch > 0);
659 switch (ch)
661 case '$':
662 *pos++ = '$';
663 *pos++ = '$';
664 break;
665 case '.':
666 *pos++ = '$';
667 *pos++ = '_';
668 break;
669 case '/':
670 *pos++ = '$';
671 *pos++ = 'S';
672 break;
673 default:
674 memcpy (pos, w2, w1 - w2);
675 pos += w1 - w2;
676 break;
679 append_gpp_mangled_name (buf, pos - buf);
681 return finish_mangling ();
684 /* Mangling initialization routine. */
686 static void
687 init_mangling (void)
689 if (!mangle_obstack)
691 mangle_obstack = &mangle_obstack_1;
692 gcc_obstack_init (mangle_obstack);
695 gcc_assert (compression_table == NULL);
696 compression_table = make_tree_vec (10);
698 /* Mangled name are to be suffixed */
699 MANGLE_RAW_STRING ("_Z");
702 /* Mangling finalization routine. The mangled name is returned as a
703 IDENTIFIER_NODE. */
705 static tree
706 finish_mangling (void)
708 tree result;
710 gcc_assert (compression_table);
712 compression_table = NULL_TREE;
713 compression_next = 0;
714 obstack_1grow (mangle_obstack, '\0');
715 result = get_identifier (obstack_base (mangle_obstack));
716 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
718 return result;
721 #include "gt-java-mangle.h"