1 /* Functions related to mangling class names for the GNU compiler
2 for the Java(TM) language.
3 Copyright (C) 1998-2015 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
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.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>.
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. */
25 /* Written by Per Bothner <bothner@cygnus.com> */
29 #include "coretypes.h"
35 #include "stringpool.h"
36 #include "java-tree.h"
38 #include "diagnostic-core.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
;
76 /* This is the mangling interface: a decl, a class field (.class) and
80 java_mangle_decl (tree decl
)
82 /* A copy of the check from the beginning of lhd_set_decl_assembler_name.
83 Only FUNCTION_DECLs and VAR_DECLs for variables with static storage
84 duration need a real DECL_ASSEMBLER_NAME. */
85 gcc_assert (TREE_CODE (decl
) == FUNCTION_DECL
86 || (TREE_CODE (decl
) == VAR_DECL
87 && (TREE_STATIC (decl
)
88 || DECL_EXTERNAL (decl
)
89 || TREE_PUBLIC (decl
))));
91 /* Mangling only applies to class members. */
92 if (DECL_CONTEXT (decl
) && TYPE_P (DECL_CONTEXT (decl
)))
95 switch (TREE_CODE (decl
))
98 if (DECL_LANG_SPECIFIC (decl
))
100 if (DECL_CLASS_FIELD_P (decl
))
102 mangle_class_field (decl
);
105 else if (DECL_VTABLE_P (decl
))
107 mangle_vtable (DECL_CONTEXT (decl
));
111 mangle_field_decl (decl
);
115 if (DECL_LANG_SPECIFIC (decl
) && DECL_LOCAL_CNI_METHOD_P (decl
))
116 mangle_local_cni_method_decl (decl
);
118 mangle_method_decl (decl
);
124 SET_DECL_ASSEMBLER_NAME (decl
, finish_mangling ());
127 lhd_set_decl_assembler_name (decl
);
130 /* Beginning of the helper functions */
133 mangle_class_field (tree decl
)
135 tree type
= DECL_CONTEXT (decl
);
136 mangle_record_type (type
, /* for_pointer = */ 0);
137 if (TREE_CODE (TREE_TYPE (decl
)) == RECORD_TYPE
)
138 MANGLE_RAW_STRING ("6class$");
140 MANGLE_RAW_STRING ("7class$$");
141 obstack_1grow (mangle_obstack
, 'E');
145 mangle_vtable (tree type
)
147 MANGLE_RAW_STRING ("TV");
148 mangle_record_type (type
, /* for_pointer = */ 0);
149 obstack_1grow (mangle_obstack
, 'E');
152 /* This mangles a field decl */
155 mangle_field_decl (tree decl
)
157 /* Mangle the name of the this the field belongs to */
158 mangle_record_type (DECL_CONTEXT (decl
), /* for_pointer = */ 0);
160 /* Mangle the name of the field */
161 mangle_member_name (DECL_NAME (decl
));
163 /* Terminate the mangled name */
164 obstack_1grow (mangle_obstack
, 'E');
167 /* This mangles a method decl, first mangling its name and then all
171 mangle_method_decl (tree mdecl
)
173 tree method_name
= DECL_NAME (mdecl
);
176 /* Mangle the name of the type that contains mdecl */
177 mangle_record_type (DECL_CONTEXT (mdecl
), /* for_pointer = */ 0);
179 /* Mangle the function name. There are two cases:
180 - mdecl is a constructor, use `C1' for its name, (denotes a
181 complete object constructor.)
182 - mdecl is not a constructor, standard mangling is performed.
183 We terminate the mangled function name with a `E'. */
184 if (ID_INIT_P (method_name
))
185 obstack_grow (mangle_obstack
, "C1", 2);
187 mangle_member_name (method_name
);
188 obstack_1grow (mangle_obstack
, 'E');
190 /* We mangled type.methodName. Now onto the arguments. */
191 arglist
= TYPE_ARG_TYPES (TREE_TYPE (mdecl
));
192 if (TREE_CODE (TREE_TYPE (mdecl
)) == METHOD_TYPE
)
193 arglist
= TREE_CHAIN (arglist
);
195 /* Output literal 'J' and mangle the return type IF not a
197 if (!ID_INIT_P (method_name
))
199 obstack_1grow (mangle_obstack
, 'J');
200 mangle_type(TREE_TYPE(TREE_TYPE(mdecl
)));
203 /* No arguments is easy. We shortcut it. */
204 if (arglist
== end_params_node
)
205 obstack_1grow (mangle_obstack
, 'v');
209 for (arg
= arglist
; arg
!= end_params_node
; arg
= TREE_CHAIN (arg
))
210 mangle_type (TREE_VALUE (arg
));
214 /* This mangles a CNI method for a local class. If the target supports
215 hidden aliases, then G++ will have generated one for us. It is the
216 responsibility of java_mark_class_local to check target support, since
217 we need to set DECL_VISIBILITY (or not) much earlier. */
220 mangle_local_cni_method_decl (tree decl
)
222 MANGLE_RAW_STRING ("GA");
223 mangle_method_decl (decl
);
226 /* This mangles a member name, like a function name or a field
227 name. Handle cases were `name' is a C++ keyword. Return a nonzero
228 value if unicode encoding was required. */
231 mangle_member_name (tree name
)
233 append_gpp_mangled_name (IDENTIFIER_POINTER (name
),
234 IDENTIFIER_LENGTH (name
));
237 /* Append the mangled name of TYPE onto OBSTACK. */
240 mangle_type (tree type
)
242 switch (TREE_CODE (type
))
245 case BOOLEAN_TYPE
: code
= 'b'; goto primitive
;
246 case VOID_TYPE
: code
= 'v'; goto primitive
;
248 if (type
== char_type_node
|| type
== promoted_char_type_node
)
253 /* Get the original type instead of the arguments promoted type.
254 Avoid symbol name clashes. Should call a function to do that.
256 if (type
== promoted_short_type_node
)
257 type
= short_type_node
;
258 if (type
== promoted_byte_type_node
)
259 type
= byte_type_node
;
260 switch (TYPE_PRECISION (type
))
262 case 8: code
= 'c'; goto primitive
;
263 case 16: code
= 's'; goto primitive
;
264 case 32: code
= 'i'; goto primitive
;
265 case 64: code
= 'x'; goto primitive
;
266 default: goto bad_type
;
269 obstack_1grow (mangle_obstack
, code
);
273 switch (TYPE_PRECISION (type
))
275 case 32: code
= 'f'; goto primitive
;
276 case 64: code
= 'd'; goto primitive
;
277 default: goto bad_type
;
280 if (TYPE_ARRAY_P (TREE_TYPE (type
)))
281 mangle_array_type (type
);
283 mangle_pointer_type (type
);
291 /* The compression table is a vector that keeps track of things we've
292 already seen, so they can be reused. For example, java.lang.Object
293 would generate three entries: two package names and a type. If
294 java.lang.String is presented next, the java.lang will be matched
295 against the first two entries (and kept for compression as S0_), and
296 type String would be added to the table. See mangle_record_type.
297 COMPRESSION_NEXT is the index to the location of the next insertion
300 static GTY(()) tree compression_table
;
301 static int compression_next
;
303 /* Find a POINTER_TYPE in the compression table. Use a special
304 function to match pointer entries and start from the end */
307 find_compression_pointer_match (tree type
)
311 for (i
= compression_next
-1; i
>= 0; i
--)
312 if (entry_match_pointer_p (type
, i
))
317 /* Already recorder arrays are handled like pointer as they're always
318 associated with it. */
321 find_compression_array_match (tree type
)
323 return find_compression_pointer_match (type
);
326 /* Match the table of type against STRING. */
329 find_compression_array_template_match (tree string
)
332 for (i
= 0; i
< compression_next
; i
++)
333 if (TREE_VEC_ELT (compression_table
, i
) == string
)
338 /* We go through the compression table and try to find a complete or
339 partial match. The function returns the compression table entry
340 that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
341 to the rest of TYPE to be mangled. */
344 find_compression_record_match (tree type
, tree
*next_current
)
347 tree current
, saved_current
= NULL_TREE
;
349 current
= TYPE_PACKAGE_LIST (type
);
351 for (i
= 0; i
< compression_next
; i
++)
353 tree compression_entry
= TREE_VEC_ELT (compression_table
, i
);
354 if (current
&& compression_entry
== TREE_PURPOSE (current
))
357 saved_current
= current
;
358 current
= TREE_CHAIN (current
);
361 /* We don't want to match an element that appears in the middle
362 of a package name, so skip forward to the next complete type name.
363 IDENTIFIER_NODEs (except for a "6JArray") are partial package
364 names while RECORD_TYPEs represent complete type names. */
365 while (i
< compression_next
366 && TREE_CODE (compression_entry
) == IDENTIFIER_NODE
367 && compression_entry
!= atms
)
368 compression_entry
= TREE_VEC_ELT (compression_table
, ++i
);
374 /* If we have a match, set next_current to the item next to the last
377 *next_current
= TREE_CHAIN (saved_current
);
378 /* We had no match: we'll have to start from the beginning. */
380 *next_current
= TYPE_PACKAGE_LIST (type
);
385 /* Mangle a record type. If a nonzero value is returned, it means
386 that a 'N' was emitted (so that a matching 'E' can be emitted if
387 necessary.) FOR_POINTER indicates that this element is for a pointer
388 symbol, meaning it was preceded by a 'P'. */
391 mangle_record_type (tree type
, int for_pointer
)
398 /* Does this name have a package qualifier? */
399 qualified
= QUALIFIED_P (DECL_NAME (TYPE_NAME (type
)));
402 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
404 gcc_assert (TREE_CODE (type
) == RECORD_TYPE
);
406 if (!TYPE_PACKAGE_LIST (type
))
407 set_type_package_list (type
);
409 match
= find_compression_record_match (type
, ¤t
);
412 /* If we had a pointer, and there's more, we need to emit
413 'N' after 'P' (for_pointer tells us we already emitted it.) */
414 if (for_pointer
&& current
)
416 emit_compression_string (match
);
420 /* Add the new type to the table */
421 compression_table_add (TREE_PURPOSE (current
));
422 /* Add 'N' if we never got a chance to, but only if we have a qualified
423 name. For non-pointer elements, the name is always qualified. */
424 if ((qualified
|| !for_pointer
) && !nadded_p
)
426 /* Use the bare type name for the mangle. */
427 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current
)),
428 IDENTIFIER_LENGTH (TREE_VALUE (current
)));
429 current
= TREE_CHAIN (current
);
435 /* Mangle a pointer type. There are two cases: the pointer is already
436 in the compression table: the compression is emitted sans 'P'
437 indicator. Otherwise, a 'P' is emitted and, depending on the type,
438 a partial compression or/plus the rest of the mangling. */
441 mangle_pointer_type (tree type
)
446 /* Search for the type already in the compression table */
447 if ((match
= find_compression_pointer_match (type
)) >= 0)
449 emit_compression_string (match
);
453 /* This didn't work. We start by mangling the pointed-to type */
455 type
= TREE_TYPE (type
);
456 gcc_assert (TREE_CODE (type
) == RECORD_TYPE
);
458 obstack_1grow (mangle_obstack
, 'P');
459 if (mangle_record_type (type
, /* for_pointer = */ 1))
460 obstack_1grow (mangle_obstack
, 'E');
462 /* Don't forget to insert the pointer type in the table */
463 compression_table_add (pointer_type
);
466 /* Mangle an array type. Search for an easy solution first, then go
467 through the process of finding out whether the bare array type or even
468 the template indicator were already used and compressed appropriately.
469 It handles pointers. */
472 mangle_array_type (tree p_type
)
477 type
= TREE_TYPE (p_type
);
480 elt_type
= TYPE_ARRAY_ELEMENT (type
);
482 /* We cache a bit of the Jarray <> mangle. */
485 atms
= get_identifier ("6JArray");
488 /* Maybe we have what we're looking for in the compression table. */
489 if ((match
= find_compression_array_match (p_type
)) >= 0)
491 emit_compression_string (match
);
495 /* We know for a fact that all arrays are pointers */
496 obstack_1grow (mangle_obstack
, 'P');
497 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
498 if ((match
= find_compression_record_match (type
, NULL
)) > 0)
500 emit_compression_string (match
);
504 /* Maybe we already have just JArray somewhere */
505 if ((match
= find_compression_array_template_match (atms
)) > 0)
506 emit_compression_string (match
);
509 /* Start the template mangled name */
510 obstack_grow (mangle_obstack
,
511 IDENTIFIER_POINTER (atms
), IDENTIFIER_LENGTH (atms
));
512 /* Insert in the compression table */
513 compression_table_add (atms
);
516 /* Mangle Jarray <elt_type> */
517 obstack_1grow (mangle_obstack
, 'I');
518 mangle_type (elt_type
);
519 obstack_1grow (mangle_obstack
, 'E');
521 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
522 compression_table_add (type
);
523 compression_table_add (p_type
);
526 /* Write a substitution string for entry I. Substitution string starts a
527 -1 (encoded S_.) The base is 36, and the code shamelessly taken from
531 emit_compression_string (int i
)
534 obstack_1grow (mangle_obstack
, 'S');
537 static const char digits
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
538 unsigned HOST_WIDE_INT n
;
539 unsigned HOST_WIDE_INT m
=1;
540 /* How many digits for I in base 36? */
541 for (n
= i
; n
>= 36; n
/= 36, m
*=36);
542 /* Write the digits out */
546 obstack_1grow (mangle_obstack
, digits
[digit
]);
551 obstack_1grow (mangle_obstack
, '_');
554 /* If search the compression table at index I for a pointer type
555 equivalent to TYPE (meaning that after all the indirection, which
556 might all be unique, we find the same RECORD_TYPE.) */
559 entry_match_pointer_p (tree type
, int i
)
561 tree t
= TREE_VEC_ELT (compression_table
, i
);
563 while (TREE_CODE (type
) == POINTER_TYPE
564 && TREE_CODE (t
) == POINTER_TYPE
)
567 type
= TREE_TYPE (type
);
569 return (TREE_CODE (type
) == RECORD_TYPE
570 && TREE_CODE (t
) == RECORD_TYPE
574 /* Go through all qualification of type and build a list of list node
575 elements containings as a purpose what should be used for a match and
576 inserted in the compression table; and as it value the raw name of the
577 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
580 set_type_package_list (tree type
)
583 const char *type_string
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type
)));
586 tree list
= NULL_TREE
, elt
;
588 for (ptr
= type_string
, qualifications
= 0; *ptr
; ptr
++)
592 for (ptr
= type_string
, i
= 0; i
< qualifications
; ptr
++)
596 tree
const identifier
597 = get_identifier_with_length (type_string
, ptr
- type_string
);
599 elt
= build_tree_list (identifier
, identifier
);
600 TREE_CHAIN (elt
) = list
;
607 elt
= build_tree_list (type
, get_identifier (type_string
));
608 TREE_CHAIN (elt
) = list
;
610 TYPE_PACKAGE_LIST (type
) = nreverse (list
);
613 /* Add TYPE as the last element of the compression table. Resize the
614 compression table if necessary. */
617 compression_table_add (tree type
)
619 if (compression_next
== TREE_VEC_LENGTH (compression_table
))
621 tree new_table
= make_tree_vec (2*compression_next
);
624 for (i
= 0; i
< compression_next
; i
++)
625 TREE_VEC_ELT (new_table
, i
) = TREE_VEC_ELT (compression_table
, i
);
627 compression_table
= new_table
;
629 TREE_VEC_ELT (compression_table
, compression_next
++) = type
;
632 /* Mangle an embedded resource file name. "_ZGr" is the prefix. A
633 '_' is prepended to the name so that names starting with a digit
634 can be demangled. The length and then the resulting name itself
635 are appended while escaping '$', '.', and '/' to: "$$", "$_", and
639 java_mangle_resource_name (const char *name
)
641 int len
= strlen (name
);
642 char *buf
= (char *) alloca (2 * len
+ 1);
644 const unsigned char *w1
= (const unsigned char *) name
;
645 const unsigned char *w2
;
646 const unsigned char *limit
= w1
+ len
;
651 MANGLE_RAW_STRING ("Gr");
658 ch
= UTF8_GET (w1
, limit
);
675 memcpy (pos
, w2
, w1
- w2
);
680 append_gpp_mangled_name (buf
, pos
- buf
);
682 return finish_mangling ();
685 /* Mangling initialization routine. */
692 mangle_obstack
= &mangle_obstack_1
;
693 gcc_obstack_init (mangle_obstack
);
696 gcc_assert (compression_table
== NULL
);
697 compression_table
= make_tree_vec (10);
699 /* Mangled name are to be suffixed */
700 MANGLE_RAW_STRING ("_Z");
703 /* Mangling finalization routine. The mangled name is returned as a
707 finish_mangling (void)
711 gcc_assert (compression_table
);
713 compression_table
= NULL_TREE
;
714 compression_next
= 0;
715 obstack_1grow (mangle_obstack
, '\0');
716 result
= get_identifier ((char *) obstack_base (mangle_obstack
));
717 obstack_free (mangle_obstack
, obstack_base (mangle_obstack
));
722 #include "gt-java-mangle.h"