2015-05-22 Pascal Obry <obry@adacore.com>
[official-gcc.git] / gcc / java / mangle.c
blob8c0c00906b964195ce15a42a08a290f613d8c630
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)
10 any later version.
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> */
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "jcf.h"
31 #include "hash-set.h"
32 #include "machmode.h"
33 #include "vec.h"
34 #include "double-int.h"
35 #include "input.h"
36 #include "alias.h"
37 #include "symtab.h"
38 #include "options.h"
39 #include "wide-int.h"
40 #include "inchash.h"
41 #include "tree.h"
42 #include "stringpool.h"
43 #include "java-tree.h"
44 #include "obstack.h"
45 #include "diagnostic-core.h"
46 #include "ggc.h"
47 #include "langhooks-def.h"
49 static void mangle_class_field (tree);
50 static void mangle_vtable (tree);
51 static void mangle_field_decl (tree);
52 static void mangle_method_decl (tree);
53 static void mangle_local_cni_method_decl (tree);
55 static void mangle_type (tree);
56 static void mangle_pointer_type (tree);
57 static void mangle_array_type (tree);
58 static int mangle_record_type (tree, int);
60 static int find_compression_pointer_match (tree);
61 static int find_compression_array_match (tree);
62 static int find_compression_record_match (tree, tree *);
63 static int find_compression_array_template_match (tree);
65 static void set_type_package_list (tree);
66 static int entry_match_pointer_p (tree, int);
67 static void emit_compression_string (int);
69 static void init_mangling (void);
70 static tree finish_mangling (void);
71 static void compression_table_add (tree);
73 static void mangle_member_name (tree);
75 static struct obstack mangle_obstack_1;
76 struct obstack *mangle_obstack;
78 #define MANGLE_RAW_STRING(S) \
79 obstack_grow (mangle_obstack, (S), sizeof (S)-1)
81 /* atms: array template mangled string. */
82 static GTY(()) tree atms;
84 /* This is the mangling interface: a decl, a class field (.class) and
85 the vtable. */
87 void
88 java_mangle_decl (tree decl)
90 /* A copy of the check from the beginning of lhd_set_decl_assembler_name.
91 Only FUNCTION_DECLs and VAR_DECLs for variables with static storage
92 duration need a real DECL_ASSEMBLER_NAME. */
93 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
94 || (TREE_CODE (decl) == VAR_DECL
95 && (TREE_STATIC (decl)
96 || DECL_EXTERNAL (decl)
97 || TREE_PUBLIC (decl))));
99 /* Mangling only applies to class members. */
100 if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
102 init_mangling ();
103 switch (TREE_CODE (decl))
105 case VAR_DECL:
106 if (DECL_LANG_SPECIFIC (decl))
108 if (DECL_CLASS_FIELD_P (decl))
110 mangle_class_field (decl);
111 break;
113 else if (DECL_VTABLE_P (decl))
115 mangle_vtable (DECL_CONTEXT (decl));
116 break;
119 mangle_field_decl (decl);
120 break;
122 case FUNCTION_DECL:
123 if (DECL_LANG_SPECIFIC (decl) && DECL_LOCAL_CNI_METHOD_P (decl))
124 mangle_local_cni_method_decl (decl);
125 else
126 mangle_method_decl (decl);
127 break;
129 default:
130 gcc_unreachable ();
132 SET_DECL_ASSEMBLER_NAME (decl, finish_mangling ());
134 else
135 lhd_set_decl_assembler_name (decl);
138 /* Beginning of the helper functions */
140 static void
141 mangle_class_field (tree decl)
143 tree type = DECL_CONTEXT (decl);
144 mangle_record_type (type, /* for_pointer = */ 0);
145 if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
146 MANGLE_RAW_STRING ("6class$");
147 else
148 MANGLE_RAW_STRING ("7class$$");
149 obstack_1grow (mangle_obstack, 'E');
152 static void
153 mangle_vtable (tree type)
155 MANGLE_RAW_STRING ("TV");
156 mangle_record_type (type, /* for_pointer = */ 0);
157 obstack_1grow (mangle_obstack, 'E');
160 /* This mangles a field decl */
162 static void
163 mangle_field_decl (tree decl)
165 /* Mangle the name of the this the field belongs to */
166 mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
168 /* Mangle the name of the field */
169 mangle_member_name (DECL_NAME (decl));
171 /* Terminate the mangled name */
172 obstack_1grow (mangle_obstack, 'E');
175 /* This mangles a method decl, first mangling its name and then all
176 its arguments. */
178 static void
179 mangle_method_decl (tree mdecl)
181 tree method_name = DECL_NAME (mdecl);
182 tree arglist;
184 /* Mangle the name of the type that contains mdecl */
185 mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
187 /* Mangle the function name. There are two cases:
188 - mdecl is a constructor, use `C1' for its name, (denotes a
189 complete object constructor.)
190 - mdecl is not a constructor, standard mangling is performed.
191 We terminate the mangled function name with a `E'. */
192 if (ID_INIT_P (method_name))
193 obstack_grow (mangle_obstack, "C1", 2);
194 else
195 mangle_member_name (method_name);
196 obstack_1grow (mangle_obstack, 'E');
198 /* We mangled type.methodName. Now onto the arguments. */
199 arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
200 if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
201 arglist = TREE_CHAIN (arglist);
203 /* Output literal 'J' and mangle the return type IF not a
204 constructor. */
205 if (!ID_INIT_P (method_name))
207 obstack_1grow (mangle_obstack, 'J');
208 mangle_type(TREE_TYPE(TREE_TYPE(mdecl)));
211 /* No arguments is easy. We shortcut it. */
212 if (arglist == end_params_node)
213 obstack_1grow (mangle_obstack, 'v');
214 else
216 tree arg;
217 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
218 mangle_type (TREE_VALUE (arg));
222 /* This mangles a CNI method for a local class. If the target supports
223 hidden aliases, then G++ will have generated one for us. It is the
224 responsibility of java_mark_class_local to check target support, since
225 we need to set DECL_VISIBILITY (or not) much earlier. */
227 static void
228 mangle_local_cni_method_decl (tree decl)
230 MANGLE_RAW_STRING ("GA");
231 mangle_method_decl (decl);
234 /* This mangles a member name, like a function name or a field
235 name. Handle cases were `name' is a C++ keyword. Return a nonzero
236 value if unicode encoding was required. */
238 static void
239 mangle_member_name (tree name)
241 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
242 IDENTIFIER_LENGTH (name));
245 /* Append the mangled name of TYPE onto OBSTACK. */
247 static void
248 mangle_type (tree type)
250 switch (TREE_CODE (type))
252 char code;
253 case BOOLEAN_TYPE: code = 'b'; goto primitive;
254 case VOID_TYPE: code = 'v'; goto primitive;
255 case INTEGER_TYPE:
256 if (type == char_type_node || type == promoted_char_type_node)
258 code = 'w';
259 goto primitive;
261 /* Get the original type instead of the arguments promoted type.
262 Avoid symbol name clashes. Should call a function to do that.
263 FIXME. */
264 if (type == promoted_short_type_node)
265 type = short_type_node;
266 if (type == promoted_byte_type_node)
267 type = byte_type_node;
268 switch (TYPE_PRECISION (type))
270 case 8: code = 'c'; goto primitive;
271 case 16: code = 's'; goto primitive;
272 case 32: code = 'i'; goto primitive;
273 case 64: code = 'x'; goto primitive;
274 default: goto bad_type;
276 primitive:
277 obstack_1grow (mangle_obstack, code);
278 break;
280 case REAL_TYPE:
281 switch (TYPE_PRECISION (type))
283 case 32: code = 'f'; goto primitive;
284 case 64: code = 'd'; goto primitive;
285 default: goto bad_type;
287 case POINTER_TYPE:
288 if (TYPE_ARRAY_P (TREE_TYPE (type)))
289 mangle_array_type (type);
290 else
291 mangle_pointer_type (type);
292 break;
293 bad_type:
294 default:
295 gcc_unreachable ();
299 /* The compression table is a vector that keeps track of things we've
300 already seen, so they can be reused. For example, java.lang.Object
301 would generate three entries: two package names and a type. If
302 java.lang.String is presented next, the java.lang will be matched
303 against the first two entries (and kept for compression as S0_), and
304 type String would be added to the table. See mangle_record_type.
305 COMPRESSION_NEXT is the index to the location of the next insertion
306 of an element. */
308 static GTY(()) tree compression_table;
309 static int compression_next;
311 /* Find a POINTER_TYPE in the compression table. Use a special
312 function to match pointer entries and start from the end */
314 static int
315 find_compression_pointer_match (tree type)
317 int i;
319 for (i = compression_next-1; i >= 0; i--)
320 if (entry_match_pointer_p (type, i))
321 return i;
322 return -1;
325 /* Already recorder arrays are handled like pointer as they're always
326 associated with it. */
328 static int
329 find_compression_array_match (tree type)
331 return find_compression_pointer_match (type);
334 /* Match the table of type against STRING. */
336 static int
337 find_compression_array_template_match (tree string)
339 int i;
340 for (i = 0; i < compression_next; i++)
341 if (TREE_VEC_ELT (compression_table, i) == string)
342 return i;
343 return -1;
346 /* We go through the compression table and try to find a complete or
347 partial match. The function returns the compression table entry
348 that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
349 to the rest of TYPE to be mangled. */
351 static int
352 find_compression_record_match (tree type, tree *next_current)
354 int i, match = -1;
355 tree current, saved_current = NULL_TREE;
357 current = TYPE_PACKAGE_LIST (type);
359 for (i = 0; i < compression_next; i++)
361 tree compression_entry = TREE_VEC_ELT (compression_table, i);
362 if (current && compression_entry == TREE_PURPOSE (current))
364 match = i;
365 saved_current = current;
366 current = TREE_CHAIN (current);
368 else
369 /* We don't want to match an element that appears in the middle
370 of a package name, so skip forward to the next complete type name.
371 IDENTIFIER_NODEs (except for a "6JArray") are partial package
372 names while RECORD_TYPEs represent complete type names. */
373 while (i < compression_next
374 && TREE_CODE (compression_entry) == IDENTIFIER_NODE
375 && compression_entry != atms)
376 compression_entry = TREE_VEC_ELT (compression_table, ++i);
379 if (!next_current)
380 return match;
382 /* If we have a match, set next_current to the item next to the last
383 matched value. */
384 if (match >= 0)
385 *next_current = TREE_CHAIN (saved_current);
386 /* We had no match: we'll have to start from the beginning. */
387 if (match < 0)
388 *next_current = TYPE_PACKAGE_LIST (type);
390 return match;
393 /* Mangle a record type. If a nonzero value is returned, it means
394 that a 'N' was emitted (so that a matching 'E' can be emitted if
395 necessary.) FOR_POINTER indicates that this element is for a pointer
396 symbol, meaning it was preceded by a 'P'. */
398 static int
399 mangle_record_type (tree type, int for_pointer)
401 tree current;
402 int match;
403 int nadded_p = 0;
404 int qualified;
406 /* Does this name have a package qualifier? */
407 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
409 #define ADD_N() \
410 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
412 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
414 if (!TYPE_PACKAGE_LIST (type))
415 set_type_package_list (type);
417 match = find_compression_record_match (type, &current);
418 if (match >= 0)
420 /* If we had a pointer, and there's more, we need to emit
421 'N' after 'P' (for_pointer tells us we already emitted it.) */
422 if (for_pointer && current)
423 ADD_N();
424 emit_compression_string (match);
426 while (current)
428 /* Add the new type to the table */
429 compression_table_add (TREE_PURPOSE (current));
430 /* Add 'N' if we never got a chance to, but only if we have a qualified
431 name. For non-pointer elements, the name is always qualified. */
432 if ((qualified || !for_pointer) && !nadded_p)
433 ADD_N();
434 /* Use the bare type name for the mangle. */
435 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
436 IDENTIFIER_LENGTH (TREE_VALUE (current)));
437 current = TREE_CHAIN (current);
439 return nadded_p;
440 #undef ADD_N
443 /* Mangle a pointer type. There are two cases: the pointer is already
444 in the compression table: the compression is emitted sans 'P'
445 indicator. Otherwise, a 'P' is emitted and, depending on the type,
446 a partial compression or/plus the rest of the mangling. */
448 static void
449 mangle_pointer_type (tree type)
451 int match;
452 tree pointer_type;
454 /* Search for the type already in the compression table */
455 if ((match = find_compression_pointer_match (type)) >= 0)
457 emit_compression_string (match);
458 return;
461 /* This didn't work. We start by mangling the pointed-to type */
462 pointer_type = type;
463 type = TREE_TYPE (type);
464 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
466 obstack_1grow (mangle_obstack, 'P');
467 if (mangle_record_type (type, /* for_pointer = */ 1))
468 obstack_1grow (mangle_obstack, 'E');
470 /* Don't forget to insert the pointer type in the table */
471 compression_table_add (pointer_type);
474 /* Mangle an array type. Search for an easy solution first, then go
475 through the process of finding out whether the bare array type or even
476 the template indicator were already used and compressed appropriately.
477 It handles pointers. */
479 static void
480 mangle_array_type (tree p_type)
482 tree type, elt_type;
483 int match;
485 type = TREE_TYPE (p_type);
486 gcc_assert (type);
488 elt_type = TYPE_ARRAY_ELEMENT (type);
490 /* We cache a bit of the Jarray <> mangle. */
491 if (!atms)
493 atms = get_identifier ("6JArray");
496 /* Maybe we have what we're looking for in the compression table. */
497 if ((match = find_compression_array_match (p_type)) >= 0)
499 emit_compression_string (match);
500 return;
503 /* We know for a fact that all arrays are pointers */
504 obstack_1grow (mangle_obstack, 'P');
505 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
506 if ((match = find_compression_record_match (type, NULL)) > 0)
508 emit_compression_string (match);
509 return;
512 /* Maybe we already have just JArray somewhere */
513 if ((match = find_compression_array_template_match (atms)) > 0)
514 emit_compression_string (match);
515 else
517 /* Start the template mangled name */
518 obstack_grow (mangle_obstack,
519 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
520 /* Insert in the compression table */
521 compression_table_add (atms);
524 /* Mangle Jarray <elt_type> */
525 obstack_1grow (mangle_obstack, 'I');
526 mangle_type (elt_type);
527 obstack_1grow (mangle_obstack, 'E');
529 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
530 compression_table_add (type);
531 compression_table_add (p_type);
534 /* Write a substitution string for entry I. Substitution string starts a
535 -1 (encoded S_.) The base is 36, and the code shamelessly taken from
536 cp/mangle.c. */
538 static void
539 emit_compression_string (int i)
541 i -= 1; /* Adjust */
542 obstack_1grow (mangle_obstack, 'S');
543 if (i >= 0)
545 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
546 unsigned HOST_WIDE_INT n;
547 unsigned HOST_WIDE_INT m=1;
548 /* How many digits for I in base 36? */
549 for (n = i; n >= 36; n /= 36, m *=36);
550 /* Write the digits out */
551 while (m > 0)
553 int digit = i / m;
554 obstack_1grow (mangle_obstack, digits [digit]);
555 i -= digit * m;
556 m /= 36;
559 obstack_1grow (mangle_obstack, '_');
562 /* If search the compression table at index I for a pointer type
563 equivalent to TYPE (meaning that after all the indirection, which
564 might all be unique, we find the same RECORD_TYPE.) */
566 static int
567 entry_match_pointer_p (tree type, int i)
569 tree t = TREE_VEC_ELT (compression_table, i);
571 while (TREE_CODE (type) == POINTER_TYPE
572 && TREE_CODE (t) == POINTER_TYPE)
574 t = TREE_TYPE (t);
575 type = TREE_TYPE (type);
577 return (TREE_CODE (type) == RECORD_TYPE
578 && TREE_CODE (t) == RECORD_TYPE
579 && t == type);
582 /* Go through all qualification of type and build a list of list node
583 elements containings as a purpose what should be used for a match and
584 inserted in the compression table; and as it value the raw name of the
585 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
587 static void
588 set_type_package_list (tree type)
590 int i;
591 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
592 const char *ptr;
593 int qualifications;
594 tree list = NULL_TREE, elt;
596 for (ptr = type_string, qualifications = 0; *ptr; ptr++)
597 if (*ptr == '.')
598 qualifications += 1;
600 for (ptr = type_string, i = 0; i < qualifications; ptr++)
602 if (ptr [0] == '.')
604 tree const identifier
605 = get_identifier_with_length (type_string, ptr - type_string);
607 elt = build_tree_list (identifier, identifier);
608 TREE_CHAIN (elt) = list;
609 list = elt;
610 type_string = ptr+1;
611 i += 1;
615 elt = build_tree_list (type, get_identifier (type_string));
616 TREE_CHAIN (elt) = list;
617 list = elt;
618 TYPE_PACKAGE_LIST (type) = nreverse (list);
621 /* Add TYPE as the last element of the compression table. Resize the
622 compression table if necessary. */
624 static void
625 compression_table_add (tree type)
627 if (compression_next == TREE_VEC_LENGTH (compression_table))
629 tree new_table = make_tree_vec (2*compression_next);
630 int i;
632 for (i = 0; i < compression_next; i++)
633 TREE_VEC_ELT (new_table, i) = TREE_VEC_ELT (compression_table, i);
635 compression_table = new_table;
637 TREE_VEC_ELT (compression_table, compression_next++) = type;
640 /* Mangle an embedded resource file name. "_ZGr" is the prefix. A
641 '_' is prepended to the name so that names starting with a digit
642 can be demangled. The length and then the resulting name itself
643 are appended while escaping '$', '.', and '/' to: "$$", "$_", and
644 "$S". */
646 tree
647 java_mangle_resource_name (const char *name)
649 int len = strlen (name);
650 char *buf = (char *) alloca (2 * len + 1);
651 char *pos;
652 const unsigned char *w1 = (const unsigned char *) name;
653 const unsigned char *w2;
654 const unsigned char *limit = w1 + len;
656 pos = buf;
658 init_mangling ();
659 MANGLE_RAW_STRING ("Gr");
661 *pos++ = '_';
662 while (w1 < limit)
664 int ch;
665 w2 = w1;
666 ch = UTF8_GET (w1, limit);
667 gcc_assert (ch > 0);
668 switch (ch)
670 case '$':
671 *pos++ = '$';
672 *pos++ = '$';
673 break;
674 case '.':
675 *pos++ = '$';
676 *pos++ = '_';
677 break;
678 case '/':
679 *pos++ = '$';
680 *pos++ = 'S';
681 break;
682 default:
683 memcpy (pos, w2, w1 - w2);
684 pos += w1 - w2;
685 break;
688 append_gpp_mangled_name (buf, pos - buf);
690 return finish_mangling ();
693 /* Mangling initialization routine. */
695 static void
696 init_mangling (void)
698 if (!mangle_obstack)
700 mangle_obstack = &mangle_obstack_1;
701 gcc_obstack_init (mangle_obstack);
704 gcc_assert (compression_table == NULL);
705 compression_table = make_tree_vec (10);
707 /* Mangled name are to be suffixed */
708 MANGLE_RAW_STRING ("_Z");
711 /* Mangling finalization routine. The mangled name is returned as a
712 IDENTIFIER_NODE. */
714 static tree
715 finish_mangling (void)
717 tree result;
719 gcc_assert (compression_table);
721 compression_table = NULL_TREE;
722 compression_next = 0;
723 obstack_1grow (mangle_obstack, '\0');
724 result = get_identifier ((char *) obstack_base (mangle_obstack));
725 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
727 return result;
730 #include "gt-java-mangle.h"