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
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 2, or (at your option)
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 COPYING. If not, write to
20 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
23 Java and all Java-based marks are trademarks or registered trademarks
24 of Sun Microsystems, Inc. in the United States and other countries.
25 The Free Software Foundation is independent of Sun Microsystems, Inc. */
27 /* Written by Per Bothner <bothner@cygnus.com> */
31 #include "coretypes.h"
35 #include "java-tree.h"
39 #include "langhooks-def.h"
41 static void mangle_class_field (tree);
42 static void mangle_vtable (tree);
43 static void mangle_field_decl (tree);
44 static void mangle_method_decl (tree);
45 static void mangle_local_cni_method_decl (tree);
47 static void mangle_type (tree);
48 static void mangle_pointer_type (tree);
49 static void mangle_array_type (tree);
50 static int mangle_record_type (tree, int);
52 static int find_compression_pointer_match (tree);
53 static int find_compression_array_match (tree);
54 static int find_compression_record_match (tree, tree *);
55 static int find_compression_array_template_match (tree);
57 static void set_type_package_list (tree);
58 static int entry_match_pointer_p (tree, int);
59 static void emit_compression_string (int);
61 static void init_mangling (void);
62 static tree finish_mangling (void);
63 static void compression_table_add (tree);
65 static void mangle_member_name (tree);
67 static struct obstack mangle_obstack_1;
68 struct obstack *mangle_obstack;
70 #define MANGLE_RAW_STRING(S) \
71 obstack_grow (mangle_obstack, (S), sizeof (S)-1)
73 /* atms: array template mangled string. */
74 static GTY(()) tree atms;
77 utf8_cmp (const unsigned char *str, int length, const char *name)
79 const unsigned char *limit = str + length;
82 for (i = 0; name[i]; ++i)
84 int ch = UTF8_GET (str, limit);
89 return str == limit ? 0 : 1;
92 /* A sorted list of all C++ keywords. */
93 static const char *const cxx_keywords[] =
201 /* Return true if NAME is a C++ keyword. */
203 cxx_keyword_p (const char *name, int length)
205 int last = ARRAY_SIZE (cxx_keywords);
207 int mid = (last + first) / 2;
210 for (mid = (last + first) / 2;
212 old = mid, mid = (last + first) / 2)
214 int kwl = strlen (cxx_keywords[mid]);
215 int min_length = kwl > length ? length : kwl;
216 int r = utf8_cmp ((const unsigned char *) name, min_length, cxx_keywords[mid]);
221 /* We've found a match if all the remaining characters are `$'. */
222 for (i = min_length; i < length && name[i] == '$'; ++i)
237 /* This is the mangling interface: a decl, a class field (.class) and
241 java_mangle_decl (tree decl)
243 if (TREE_CODE (decl) == RECORD_TYPE)
246 /* A copy of the check from the beginning of lhd_set_decl_assembler_name.
247 Only FUNCTION_DECLs and VAR_DECLs for variables with static storage
248 duration need a real DECL_ASSEMBLER_NAME. */
249 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
250 || (TREE_CODE (decl) == VAR_DECL
251 && (TREE_STATIC (decl)
252 || DECL_EXTERNAL (decl)
253 || TREE_PUBLIC (decl))));
255 /* Mangling only applies to class members. */
256 if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
259 switch (TREE_CODE (decl))
262 if (DECL_LANG_SPECIFIC (decl))
264 if (DECL_CLASS_FIELD_P (decl))
266 mangle_class_field (decl);
269 else if (DECL_VTABLE_P (decl))
271 mangle_vtable (DECL_CONTEXT (decl));
275 mangle_field_decl (decl);
279 if (DECL_LANG_SPECIFIC (decl) && DECL_LOCAL_CNI_METHOD_P (decl))
280 mangle_local_cni_method_decl (decl);
282 mangle_method_decl (decl);
288 SET_DECL_ASSEMBLER_NAME (decl, finish_mangling ());
291 lhd_set_decl_assembler_name (decl);
294 /* Beginning of the helper functions */
297 mangle_class_field (tree decl)
299 tree type = DECL_CONTEXT (decl);
300 mangle_record_type (type, /* for_pointer = */ 0);
301 if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
302 MANGLE_RAW_STRING ("6class$");
304 MANGLE_RAW_STRING ("7class$$");
305 obstack_1grow (mangle_obstack, 'E');
309 mangle_vtable (tree type)
311 MANGLE_RAW_STRING ("TV");
312 mangle_record_type (type, /* for_pointer = */ 0);
313 obstack_1grow (mangle_obstack, 'E');
316 /* This mangles a field decl */
319 mangle_field_decl (tree decl)
321 /* Mangle the name of the this the field belongs to */
322 mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
324 /* Mangle the name of the field */
325 mangle_member_name (DECL_NAME (decl));
327 /* Terminate the mangled name */
328 obstack_1grow (mangle_obstack, 'E');
331 /* This mangles a method decl, first mangling its name and then all
335 mangle_method_decl (tree mdecl)
337 tree method_name = DECL_NAME (mdecl);
340 /* Mangle the name of the type that contains mdecl */
341 mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
343 /* Mangle the function name. There are two cases:
344 - mdecl is a constructor, use `C1' for its name, (denotes a
345 complete object constructor.)
346 - mdecl is not a constructor, standard mangling is performed.
347 We terminate the mangled function name with a `E'. */
348 if (ID_INIT_P (method_name))
349 obstack_grow (mangle_obstack, "C1", 2);
351 mangle_member_name (method_name);
352 obstack_1grow (mangle_obstack, 'E');
354 /* We mangled type.methodName. Now onto the arguments. */
355 arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
356 if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
357 arglist = TREE_CHAIN (arglist);
359 /* Output literal 'J' and mangle the return type IF not a
361 if (!ID_INIT_P (method_name))
363 obstack_1grow (mangle_obstack, 'J');
364 mangle_type(TREE_TYPE(TREE_TYPE(mdecl)));
367 /* No arguments is easy. We shortcut it. */
368 if (arglist == end_params_node)
369 obstack_1grow (mangle_obstack, 'v');
373 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
374 mangle_type (TREE_VALUE (arg));
378 /* This mangles a CNI method for a local class. If the target supports
379 hidden aliases, then G++ will have generated one for us. It is the
380 responsibility of java_mark_class_local to check target support, since
381 we need to set DECL_VISIBILITY (or not) much earlier. */
384 mangle_local_cni_method_decl (tree decl)
386 MANGLE_RAW_STRING ("GA");
387 mangle_method_decl (decl);
390 /* This mangles a member name, like a function name or a field
391 name. Handle cases were `name' is a C++ keyword. Return a nonzero
392 value if unicode encoding was required. */
395 mangle_member_name (tree name)
397 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
398 IDENTIFIER_LENGTH (name));
400 /* If NAME happens to be a C++ keyword, add `$'. */
401 if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
402 obstack_1grow (mangle_obstack, '$');
405 /* Append the mangled name of TYPE onto OBSTACK. */
408 mangle_type (tree type)
410 switch (TREE_CODE (type))
413 case BOOLEAN_TYPE: code = 'b'; goto primitive;
414 case VOID_TYPE: code = 'v'; goto primitive;
416 if (type == char_type_node || type == promoted_char_type_node)
421 /* Get the original type instead of the arguments promoted type.
422 Avoid symbol name clashes. Should call a function to do that.
424 if (type == promoted_short_type_node)
425 type = short_type_node;
426 if (type == promoted_byte_type_node)
427 type = byte_type_node;
428 switch (TYPE_PRECISION (type))
430 case 8: code = 'c'; goto primitive;
431 case 16: code = 's'; goto primitive;
432 case 32: code = 'i'; goto primitive;
433 case 64: code = 'x'; goto primitive;
434 default: goto bad_type;
437 obstack_1grow (mangle_obstack, code);
441 switch (TYPE_PRECISION (type))
443 case 32: code = 'f'; goto primitive;
444 case 64: code = 'd'; goto primitive;
445 default: goto bad_type;
448 if (TYPE_ARRAY_P (TREE_TYPE (type)))
449 mangle_array_type (type);
451 mangle_pointer_type (type);
459 /* The compression table is a vector that keeps track of things we've
460 already seen, so they can be reused. For example, java.lang.Object
461 would generate three entries: two package names and a type. If
462 java.lang.String is presented next, the java.lang will be matched
463 against the first two entries (and kept for compression as S0_), and
464 type String would be added to the table. See mangle_record_type.
465 COMPRESSION_NEXT is the index to the location of the next insertion
468 static GTY(()) tree compression_table;
469 static int compression_next;
471 /* Find a POINTER_TYPE in the compression table. Use a special
472 function to match pointer entries and start from the end */
475 find_compression_pointer_match (tree type)
479 for (i = compression_next-1; i >= 0; i--)
480 if (entry_match_pointer_p (type, i))
485 /* Already recorder arrays are handled like pointer as they're always
486 associated with it. */
489 find_compression_array_match (tree type)
491 return find_compression_pointer_match (type);
494 /* Match the table of type against STRING. */
497 find_compression_array_template_match (tree string)
500 for (i = 0; i < compression_next; i++)
501 if (TREE_VEC_ELT (compression_table, i) == string)
506 /* We go through the compression table and try to find a complete or
507 partial match. The function returns the compression table entry
508 that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
509 to the rest of TYPE to be mangled. */
512 find_compression_record_match (tree type, tree *next_current)
515 tree current, saved_current = NULL_TREE;
517 current = TYPE_PACKAGE_LIST (type);
519 for (i = 0; i < compression_next; i++)
521 tree compression_entry = TREE_VEC_ELT (compression_table, i);
522 if (current && compression_entry == TREE_PURPOSE (current))
525 saved_current = current;
526 current = TREE_CHAIN (current);
529 /* We don't want to match an element that appears in the middle
530 of a package name, so skip forward to the next complete type name.
531 IDENTIFIER_NODEs (except for a "6JArray") are partial package
532 names while RECORD_TYPEs represent complete type names. */
533 while (i < compression_next
534 && TREE_CODE (compression_entry) == IDENTIFIER_NODE
535 && compression_entry != atms)
536 compression_entry = TREE_VEC_ELT (compression_table, ++i);
542 /* If we have a match, set next_current to the item next to the last
545 *next_current = TREE_CHAIN (saved_current);
546 /* We had no match: we'll have to start from the beginning. */
548 *next_current = TYPE_PACKAGE_LIST (type);
553 /* Mangle a record type. If a nonzero value is returned, it means
554 that a 'N' was emitted (so that a matching 'E' can be emitted if
555 necessary.) FOR_POINTER indicates that this element is for a pointer
556 symbol, meaning it was preceded by a 'P'. */
559 mangle_record_type (tree type, int for_pointer)
566 /* Does this name have a package qualifier? */
567 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
570 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
572 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
574 if (!TYPE_PACKAGE_LIST (type))
575 set_type_package_list (type);
577 match = find_compression_record_match (type, ¤t);
580 /* If we had a pointer, and there's more, we need to emit
581 'N' after 'P' (for_pointer tells us we already emitted it.) */
582 if (for_pointer && current)
584 emit_compression_string (match);
588 /* Add the new type to the table */
589 compression_table_add (TREE_PURPOSE (current));
590 /* Add 'N' if we never got a chance to, but only if we have a qualified
591 name. For non-pointer elements, the name is always qualified. */
592 if ((qualified || !for_pointer) && !nadded_p)
594 /* Use the bare type name for the mangle. */
595 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
596 IDENTIFIER_LENGTH (TREE_VALUE (current)));
597 current = TREE_CHAIN (current);
603 /* Mangle a pointer type. There are two cases: the pointer is already
604 in the compression table: the compression is emitted sans 'P'
605 indicator. Otherwise, a 'P' is emitted and, depending on the type,
606 a partial compression or/plus the rest of the mangling. */
609 mangle_pointer_type (tree type)
614 /* Search for the type already in the compression table */
615 if ((match = find_compression_pointer_match (type)) >= 0)
617 emit_compression_string (match);
621 /* This didn't work. We start by mangling the pointed-to type */
623 type = TREE_TYPE (type);
624 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
626 obstack_1grow (mangle_obstack, 'P');
627 if (mangle_record_type (type, /* for_pointer = */ 1))
628 obstack_1grow (mangle_obstack, 'E');
630 /* Don't forget to insert the pointer type in the table */
631 compression_table_add (pointer_type);
634 /* Mangle an array type. Search for an easy solution first, then go
635 through the process of finding out whether the bare array type or even
636 the template indicator were already used and compressed appropriately.
637 It handles pointers. */
640 mangle_array_type (tree p_type)
645 type = TREE_TYPE (p_type);
648 elt_type = TYPE_ARRAY_ELEMENT (type);
650 /* We cache a bit of the Jarray <> mangle. */
653 atms = get_identifier ("6JArray");
656 /* Maybe we have what we're looking for in the compression table. */
657 if ((match = find_compression_array_match (p_type)) >= 0)
659 emit_compression_string (match);
663 /* We know for a fact that all arrays are pointers */
664 obstack_1grow (mangle_obstack, 'P');
665 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
666 if ((match = find_compression_record_match (type, NULL)) > 0)
668 emit_compression_string (match);
672 /* Maybe we already have just JArray somewhere */
673 if ((match = find_compression_array_template_match (atms)) > 0)
674 emit_compression_string (match);
677 /* Start the template mangled name */
678 obstack_grow (mangle_obstack,
679 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
680 /* Insert in the compression table */
681 compression_table_add (atms);
684 /* Mangle Jarray <elt_type> */
685 obstack_1grow (mangle_obstack, 'I');
686 mangle_type (elt_type);
687 obstack_1grow (mangle_obstack, 'E');
689 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
690 compression_table_add (type);
691 compression_table_add (p_type);
694 /* Write a substitution string for entry I. Substitution string starts a
695 -1 (encoded S_.) The base is 36, and the code shamelessly taken from
699 emit_compression_string (int i)
702 obstack_1grow (mangle_obstack, 'S');
705 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
706 unsigned HOST_WIDE_INT n;
707 unsigned HOST_WIDE_INT m=1;
708 /* How many digits for I in base 36? */
709 for (n = i; n >= 36; n /= 36, m *=36);
710 /* Write the digits out */
714 obstack_1grow (mangle_obstack, digits [digit]);
719 obstack_1grow (mangle_obstack, '_');
722 /* If search the compression table at index I for a pointer type
723 equivalent to TYPE (meaning that after all the indirection, which
724 might all be unique, we find the same RECORD_TYPE.) */
727 entry_match_pointer_p (tree type, int i)
729 tree t = TREE_VEC_ELT (compression_table, i);
731 while (TREE_CODE (type) == POINTER_TYPE
732 && TREE_CODE (t) == POINTER_TYPE)
735 type = TREE_TYPE (type);
737 return (TREE_CODE (type) == RECORD_TYPE
738 && TREE_CODE (t) == RECORD_TYPE
742 /* Go through all qualification of type and build a list of list node
743 elements containings as a purpose what should be used for a match and
744 inserted in the compression table; and as it value the raw name of the
745 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
748 set_type_package_list (tree type)
751 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
754 tree list = NULL_TREE, elt;
756 for (ptr = type_string, qualifications = 0; *ptr; ptr++)
760 for (ptr = type_string, i = 0; i < qualifications; ptr++)
764 tree const identifier
765 = get_identifier_with_length (type_string, ptr - type_string);
767 elt = build_tree_list (identifier, identifier);
768 TREE_CHAIN (elt) = list;
775 elt = build_tree_list (type, get_identifier (type_string));
776 TREE_CHAIN (elt) = list;
778 TYPE_PACKAGE_LIST (type) = nreverse (list);
781 /* Add TYPE as the last element of the compression table. Resize the
782 compression table if necessary. */
785 compression_table_add (tree type)
787 if (compression_next == TREE_VEC_LENGTH (compression_table))
789 tree new = make_tree_vec (2*compression_next);
792 for (i = 0; i < compression_next; i++)
793 TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
795 compression_table = new;
797 TREE_VEC_ELT (compression_table, compression_next++) = type;
800 /* Mangling initialization routine. */
807 mangle_obstack = &mangle_obstack_1;
808 gcc_obstack_init (mangle_obstack);
811 gcc_assert (compression_table == NULL);
812 compression_table = make_tree_vec (10);
814 /* Mangled name are to be suffixed */
815 MANGLE_RAW_STRING ("_Z");
818 /* Mangling finalization routine. The mangled name is returned as a
822 finish_mangling (void)
826 gcc_assert (compression_table);
828 compression_table = NULL_TREE;
829 compression_next = 0;
830 obstack_1grow (mangle_obstack, '\0');
831 result = get_identifier (obstack_base (mangle_obstack));
832 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
837 #include "gt-java-mangle.h"