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 3, 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 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> */
30 #include "coretypes.h"
34 #include "java-tree.h"
38 #include "langhooks-def.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
;
76 utf8_cmp (const unsigned char *str
, int length
, const char *name
)
78 const unsigned char *limit
= str
+ length
;
81 for (i
= 0; name
[i
]; ++i
)
83 int ch
= UTF8_GET (str
, limit
);
88 return str
== limit
? 0 : 1;
91 /* A sorted list of all C++ keywords. */
92 static const char *const cxx_keywords
[] =
200 /* Return true if NAME is a C++ keyword. */
202 cxx_keyword_p (const char *name
, int length
)
204 int last
= ARRAY_SIZE (cxx_keywords
);
206 int mid
= (last
+ first
) / 2;
209 for (mid
= (last
+ first
) / 2;
211 old
= mid
, mid
= (last
+ first
) / 2)
213 int kwl
= strlen (cxx_keywords
[mid
]);
214 int min_length
= kwl
> length
? length
: kwl
;
215 int r
= utf8_cmp ((const unsigned char *) name
, min_length
, cxx_keywords
[mid
]);
220 /* We've found a match if all the remaining characters are `$'. */
221 for (i
= min_length
; i
< length
&& name
[i
] == '$'; ++i
)
236 /* This is the mangling interface: a decl, a class field (.class) and
240 java_mangle_decl (tree decl
)
242 if (TREE_CODE (decl
) == RECORD_TYPE
)
245 /* A copy of the check from the beginning of lhd_set_decl_assembler_name.
246 Only FUNCTION_DECLs and VAR_DECLs for variables with static storage
247 duration need a real DECL_ASSEMBLER_NAME. */
248 gcc_assert (TREE_CODE (decl
) == FUNCTION_DECL
249 || (TREE_CODE (decl
) == VAR_DECL
250 && (TREE_STATIC (decl
)
251 || DECL_EXTERNAL (decl
)
252 || TREE_PUBLIC (decl
))));
254 /* Mangling only applies to class members. */
255 if (DECL_CONTEXT (decl
) && TYPE_P (DECL_CONTEXT (decl
)))
258 switch (TREE_CODE (decl
))
261 if (DECL_LANG_SPECIFIC (decl
))
263 if (DECL_CLASS_FIELD_P (decl
))
265 mangle_class_field (decl
);
268 else if (DECL_VTABLE_P (decl
))
270 mangle_vtable (DECL_CONTEXT (decl
));
274 mangle_field_decl (decl
);
278 if (DECL_LANG_SPECIFIC (decl
) && DECL_LOCAL_CNI_METHOD_P (decl
))
279 mangle_local_cni_method_decl (decl
);
281 mangle_method_decl (decl
);
287 SET_DECL_ASSEMBLER_NAME (decl
, finish_mangling ());
290 lhd_set_decl_assembler_name (decl
);
293 /* Beginning of the helper functions */
296 mangle_class_field (tree decl
)
298 tree type
= DECL_CONTEXT (decl
);
299 mangle_record_type (type
, /* for_pointer = */ 0);
300 if (TREE_CODE (TREE_TYPE (decl
)) == RECORD_TYPE
)
301 MANGLE_RAW_STRING ("6class$");
303 MANGLE_RAW_STRING ("7class$$");
304 obstack_1grow (mangle_obstack
, 'E');
308 mangle_vtable (tree type
)
310 MANGLE_RAW_STRING ("TV");
311 mangle_record_type (type
, /* for_pointer = */ 0);
312 obstack_1grow (mangle_obstack
, 'E');
315 /* This mangles a field decl */
318 mangle_field_decl (tree decl
)
320 /* Mangle the name of the this the field belongs to */
321 mangle_record_type (DECL_CONTEXT (decl
), /* for_pointer = */ 0);
323 /* Mangle the name of the field */
324 mangle_member_name (DECL_NAME (decl
));
326 /* Terminate the mangled name */
327 obstack_1grow (mangle_obstack
, 'E');
330 /* This mangles a method decl, first mangling its name and then all
334 mangle_method_decl (tree mdecl
)
336 tree method_name
= DECL_NAME (mdecl
);
339 /* Mangle the name of the type that contains mdecl */
340 mangle_record_type (DECL_CONTEXT (mdecl
), /* for_pointer = */ 0);
342 /* Mangle the function name. There are two cases:
343 - mdecl is a constructor, use `C1' for its name, (denotes a
344 complete object constructor.)
345 - mdecl is not a constructor, standard mangling is performed.
346 We terminate the mangled function name with a `E'. */
347 if (ID_INIT_P (method_name
))
348 obstack_grow (mangle_obstack
, "C1", 2);
350 mangle_member_name (method_name
);
351 obstack_1grow (mangle_obstack
, 'E');
353 /* We mangled type.methodName. Now onto the arguments. */
354 arglist
= TYPE_ARG_TYPES (TREE_TYPE (mdecl
));
355 if (TREE_CODE (TREE_TYPE (mdecl
)) == METHOD_TYPE
)
356 arglist
= TREE_CHAIN (arglist
);
358 /* Output literal 'J' and mangle the return type IF not a
360 if (!ID_INIT_P (method_name
))
362 obstack_1grow (mangle_obstack
, 'J');
363 mangle_type(TREE_TYPE(TREE_TYPE(mdecl
)));
366 /* No arguments is easy. We shortcut it. */
367 if (arglist
== end_params_node
)
368 obstack_1grow (mangle_obstack
, 'v');
372 for (arg
= arglist
; arg
!= end_params_node
; arg
= TREE_CHAIN (arg
))
373 mangle_type (TREE_VALUE (arg
));
377 /* This mangles a CNI method for a local class. If the target supports
378 hidden aliases, then G++ will have generated one for us. It is the
379 responsibility of java_mark_class_local to check target support, since
380 we need to set DECL_VISIBILITY (or not) much earlier. */
383 mangle_local_cni_method_decl (tree decl
)
385 MANGLE_RAW_STRING ("GA");
386 mangle_method_decl (decl
);
389 /* This mangles a member name, like a function name or a field
390 name. Handle cases were `name' is a C++ keyword. Return a nonzero
391 value if unicode encoding was required. */
394 mangle_member_name (tree name
)
396 append_gpp_mangled_name (IDENTIFIER_POINTER (name
),
397 IDENTIFIER_LENGTH (name
));
399 /* If NAME happens to be a C++ keyword, add `$'. */
400 if (cxx_keyword_p (IDENTIFIER_POINTER (name
), IDENTIFIER_LENGTH (name
)))
401 obstack_1grow (mangle_obstack
, '$');
404 /* Append the mangled name of TYPE onto OBSTACK. */
407 mangle_type (tree type
)
409 switch (TREE_CODE (type
))
412 case BOOLEAN_TYPE
: code
= 'b'; goto primitive
;
413 case VOID_TYPE
: code
= 'v'; goto primitive
;
415 if (type
== char_type_node
|| type
== promoted_char_type_node
)
420 /* Get the original type instead of the arguments promoted type.
421 Avoid symbol name clashes. Should call a function to do that.
423 if (type
== promoted_short_type_node
)
424 type
= short_type_node
;
425 if (type
== promoted_byte_type_node
)
426 type
= byte_type_node
;
427 switch (TYPE_PRECISION (type
))
429 case 8: code
= 'c'; goto primitive
;
430 case 16: code
= 's'; goto primitive
;
431 case 32: code
= 'i'; goto primitive
;
432 case 64: code
= 'x'; goto primitive
;
433 default: goto bad_type
;
436 obstack_1grow (mangle_obstack
, code
);
440 switch (TYPE_PRECISION (type
))
442 case 32: code
= 'f'; goto primitive
;
443 case 64: code
= 'd'; goto primitive
;
444 default: goto bad_type
;
447 if (TYPE_ARRAY_P (TREE_TYPE (type
)))
448 mangle_array_type (type
);
450 mangle_pointer_type (type
);
458 /* The compression table is a vector that keeps track of things we've
459 already seen, so they can be reused. For example, java.lang.Object
460 would generate three entries: two package names and a type. If
461 java.lang.String is presented next, the java.lang will be matched
462 against the first two entries (and kept for compression as S0_), and
463 type String would be added to the table. See mangle_record_type.
464 COMPRESSION_NEXT is the index to the location of the next insertion
467 static GTY(()) tree compression_table
;
468 static int compression_next
;
470 /* Find a POINTER_TYPE in the compression table. Use a special
471 function to match pointer entries and start from the end */
474 find_compression_pointer_match (tree type
)
478 for (i
= compression_next
-1; i
>= 0; i
--)
479 if (entry_match_pointer_p (type
, i
))
484 /* Already recorder arrays are handled like pointer as they're always
485 associated with it. */
488 find_compression_array_match (tree type
)
490 return find_compression_pointer_match (type
);
493 /* Match the table of type against STRING. */
496 find_compression_array_template_match (tree string
)
499 for (i
= 0; i
< compression_next
; i
++)
500 if (TREE_VEC_ELT (compression_table
, i
) == string
)
505 /* We go through the compression table and try to find a complete or
506 partial match. The function returns the compression table entry
507 that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
508 to the rest of TYPE to be mangled. */
511 find_compression_record_match (tree type
, tree
*next_current
)
514 tree current
, saved_current
= NULL_TREE
;
516 current
= TYPE_PACKAGE_LIST (type
);
518 for (i
= 0; i
< compression_next
; i
++)
520 tree compression_entry
= TREE_VEC_ELT (compression_table
, i
);
521 if (current
&& compression_entry
== TREE_PURPOSE (current
))
524 saved_current
= current
;
525 current
= TREE_CHAIN (current
);
528 /* We don't want to match an element that appears in the middle
529 of a package name, so skip forward to the next complete type name.
530 IDENTIFIER_NODEs (except for a "6JArray") are partial package
531 names while RECORD_TYPEs represent complete type names. */
532 while (i
< compression_next
533 && TREE_CODE (compression_entry
) == IDENTIFIER_NODE
534 && compression_entry
!= atms
)
535 compression_entry
= TREE_VEC_ELT (compression_table
, ++i
);
541 /* If we have a match, set next_current to the item next to the last
544 *next_current
= TREE_CHAIN (saved_current
);
545 /* We had no match: we'll have to start from the beginning. */
547 *next_current
= TYPE_PACKAGE_LIST (type
);
552 /* Mangle a record type. If a nonzero value is returned, it means
553 that a 'N' was emitted (so that a matching 'E' can be emitted if
554 necessary.) FOR_POINTER indicates that this element is for a pointer
555 symbol, meaning it was preceded by a 'P'. */
558 mangle_record_type (tree type
, int for_pointer
)
565 /* Does this name have a package qualifier? */
566 qualified
= QUALIFIED_P (DECL_NAME (TYPE_NAME (type
)));
569 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
571 gcc_assert (TREE_CODE (type
) == RECORD_TYPE
);
573 if (!TYPE_PACKAGE_LIST (type
))
574 set_type_package_list (type
);
576 match
= find_compression_record_match (type
, ¤t
);
579 /* If we had a pointer, and there's more, we need to emit
580 'N' after 'P' (for_pointer tells us we already emitted it.) */
581 if (for_pointer
&& current
)
583 emit_compression_string (match
);
587 /* Add the new type to the table */
588 compression_table_add (TREE_PURPOSE (current
));
589 /* Add 'N' if we never got a chance to, but only if we have a qualified
590 name. For non-pointer elements, the name is always qualified. */
591 if ((qualified
|| !for_pointer
) && !nadded_p
)
593 /* Use the bare type name for the mangle. */
594 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current
)),
595 IDENTIFIER_LENGTH (TREE_VALUE (current
)));
596 current
= TREE_CHAIN (current
);
602 /* Mangle a pointer type. There are two cases: the pointer is already
603 in the compression table: the compression is emitted sans 'P'
604 indicator. Otherwise, a 'P' is emitted and, depending on the type,
605 a partial compression or/plus the rest of the mangling. */
608 mangle_pointer_type (tree type
)
613 /* Search for the type already in the compression table */
614 if ((match
= find_compression_pointer_match (type
)) >= 0)
616 emit_compression_string (match
);
620 /* This didn't work. We start by mangling the pointed-to type */
622 type
= TREE_TYPE (type
);
623 gcc_assert (TREE_CODE (type
) == RECORD_TYPE
);
625 obstack_1grow (mangle_obstack
, 'P');
626 if (mangle_record_type (type
, /* for_pointer = */ 1))
627 obstack_1grow (mangle_obstack
, 'E');
629 /* Don't forget to insert the pointer type in the table */
630 compression_table_add (pointer_type
);
633 /* Mangle an array type. Search for an easy solution first, then go
634 through the process of finding out whether the bare array type or even
635 the template indicator were already used and compressed appropriately.
636 It handles pointers. */
639 mangle_array_type (tree p_type
)
644 type
= TREE_TYPE (p_type
);
647 elt_type
= TYPE_ARRAY_ELEMENT (type
);
649 /* We cache a bit of the Jarray <> mangle. */
652 atms
= get_identifier ("6JArray");
655 /* Maybe we have what we're looking for in the compression table. */
656 if ((match
= find_compression_array_match (p_type
)) >= 0)
658 emit_compression_string (match
);
662 /* We know for a fact that all arrays are pointers */
663 obstack_1grow (mangle_obstack
, 'P');
664 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
665 if ((match
= find_compression_record_match (type
, NULL
)) > 0)
667 emit_compression_string (match
);
671 /* Maybe we already have just JArray somewhere */
672 if ((match
= find_compression_array_template_match (atms
)) > 0)
673 emit_compression_string (match
);
676 /* Start the template mangled name */
677 obstack_grow (mangle_obstack
,
678 IDENTIFIER_POINTER (atms
), IDENTIFIER_LENGTH (atms
));
679 /* Insert in the compression table */
680 compression_table_add (atms
);
683 /* Mangle Jarray <elt_type> */
684 obstack_1grow (mangle_obstack
, 'I');
685 mangle_type (elt_type
);
686 obstack_1grow (mangle_obstack
, 'E');
688 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
689 compression_table_add (type
);
690 compression_table_add (p_type
);
693 /* Write a substitution string for entry I. Substitution string starts a
694 -1 (encoded S_.) The base is 36, and the code shamelessly taken from
698 emit_compression_string (int i
)
701 obstack_1grow (mangle_obstack
, 'S');
704 static const char digits
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
705 unsigned HOST_WIDE_INT n
;
706 unsigned HOST_WIDE_INT m
=1;
707 /* How many digits for I in base 36? */
708 for (n
= i
; n
>= 36; n
/= 36, m
*=36);
709 /* Write the digits out */
713 obstack_1grow (mangle_obstack
, digits
[digit
]);
718 obstack_1grow (mangle_obstack
, '_');
721 /* If search the compression table at index I for a pointer type
722 equivalent to TYPE (meaning that after all the indirection, which
723 might all be unique, we find the same RECORD_TYPE.) */
726 entry_match_pointer_p (tree type
, int i
)
728 tree t
= TREE_VEC_ELT (compression_table
, i
);
730 while (TREE_CODE (type
) == POINTER_TYPE
731 && TREE_CODE (t
) == POINTER_TYPE
)
734 type
= TREE_TYPE (type
);
736 return (TREE_CODE (type
) == RECORD_TYPE
737 && TREE_CODE (t
) == RECORD_TYPE
741 /* Go through all qualification of type and build a list of list node
742 elements containings as a purpose what should be used for a match and
743 inserted in the compression table; and as it value the raw name of the
744 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
747 set_type_package_list (tree type
)
750 const char *type_string
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type
)));
753 tree list
= NULL_TREE
, elt
;
755 for (ptr
= type_string
, qualifications
= 0; *ptr
; ptr
++)
759 for (ptr
= type_string
, i
= 0; i
< qualifications
; ptr
++)
763 tree
const identifier
764 = get_identifier_with_length (type_string
, ptr
- type_string
);
766 elt
= build_tree_list (identifier
, identifier
);
767 TREE_CHAIN (elt
) = list
;
774 elt
= build_tree_list (type
, get_identifier (type_string
));
775 TREE_CHAIN (elt
) = list
;
777 TYPE_PACKAGE_LIST (type
) = nreverse (list
);
780 /* Add TYPE as the last element of the compression table. Resize the
781 compression table if necessary. */
784 compression_table_add (tree type
)
786 if (compression_next
== TREE_VEC_LENGTH (compression_table
))
788 tree
new = make_tree_vec (2*compression_next
);
791 for (i
= 0; i
< compression_next
; i
++)
792 TREE_VEC_ELT (new, i
) = TREE_VEC_ELT (compression_table
, i
);
794 compression_table
= new;
796 TREE_VEC_ELT (compression_table
, compression_next
++) = type
;
799 /* Mangling initialization routine. */
806 mangle_obstack
= &mangle_obstack_1
;
807 gcc_obstack_init (mangle_obstack
);
810 gcc_assert (compression_table
== NULL
);
811 compression_table
= make_tree_vec (10);
813 /* Mangled name are to be suffixed */
814 MANGLE_RAW_STRING ("_Z");
817 /* Mangling finalization routine. The mangled name is returned as a
821 finish_mangling (void)
825 gcc_assert (compression_table
);
827 compression_table
= NULL_TREE
;
828 compression_next
= 0;
829 obstack_1grow (mangle_obstack
, '\0');
830 result
= get_identifier (obstack_base (mangle_obstack
));
831 obstack_free (mangle_obstack
, obstack_base (mangle_obstack
));
836 #include "gt-java-mangle.h"