2013-05-30 Ed Smith-Rowland <3dw4rd@verizon.net>
[official-gcc.git] / gcc / java / mangle.c
blob10557e94ebde507e541ce5c81196be04a51d49c7
1 /* Functions related to mangling class names for the GNU compiler
2 for the Java(TM) language.
3 Copyright (C) 1998-2013 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 "tree.h"
32 #include "java-tree.h"
33 #include "obstack.h"
34 #include "diagnostic-core.h"
35 #include "ggc.h"
36 #include "langhooks-def.h"
38 static void mangle_class_field (tree);
39 static void mangle_vtable (tree);
40 static void mangle_field_decl (tree);
41 static void mangle_method_decl (tree);
42 static void mangle_local_cni_method_decl (tree);
44 static void mangle_type (tree);
45 static void mangle_pointer_type (tree);
46 static void mangle_array_type (tree);
47 static int mangle_record_type (tree, int);
49 static int find_compression_pointer_match (tree);
50 static int find_compression_array_match (tree);
51 static int find_compression_record_match (tree, tree *);
52 static int find_compression_array_template_match (tree);
54 static void set_type_package_list (tree);
55 static int entry_match_pointer_p (tree, int);
56 static void emit_compression_string (int);
58 static void init_mangling (void);
59 static tree finish_mangling (void);
60 static void compression_table_add (tree);
62 static void mangle_member_name (tree);
64 static struct obstack mangle_obstack_1;
65 struct obstack *mangle_obstack;
67 #define MANGLE_RAW_STRING(S) \
68 obstack_grow (mangle_obstack, (S), sizeof (S)-1)
70 /* atms: array template mangled string. */
71 static GTY(()) tree atms;
73 /* This is the mangling interface: a decl, a class field (.class) and
74 the vtable. */
76 void
77 java_mangle_decl (tree decl)
79 /* A copy of the check from the beginning of lhd_set_decl_assembler_name.
80 Only FUNCTION_DECLs and VAR_DECLs for variables with static storage
81 duration need a real DECL_ASSEMBLER_NAME. */
82 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
83 || (TREE_CODE (decl) == VAR_DECL
84 && (TREE_STATIC (decl)
85 || DECL_EXTERNAL (decl)
86 || TREE_PUBLIC (decl))));
88 /* Mangling only applies to class members. */
89 if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
91 init_mangling ();
92 switch (TREE_CODE (decl))
94 case VAR_DECL:
95 if (DECL_LANG_SPECIFIC (decl))
97 if (DECL_CLASS_FIELD_P (decl))
99 mangle_class_field (decl);
100 break;
102 else if (DECL_VTABLE_P (decl))
104 mangle_vtable (DECL_CONTEXT (decl));
105 break;
108 mangle_field_decl (decl);
109 break;
111 case FUNCTION_DECL:
112 if (DECL_LANG_SPECIFIC (decl) && DECL_LOCAL_CNI_METHOD_P (decl))
113 mangle_local_cni_method_decl (decl);
114 else
115 mangle_method_decl (decl);
116 break;
118 default:
119 gcc_unreachable ();
121 SET_DECL_ASSEMBLER_NAME (decl, finish_mangling ());
123 else
124 lhd_set_decl_assembler_name (decl);
127 /* Beginning of the helper functions */
129 static void
130 mangle_class_field (tree decl)
132 tree type = DECL_CONTEXT (decl);
133 mangle_record_type (type, /* for_pointer = */ 0);
134 if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
135 MANGLE_RAW_STRING ("6class$");
136 else
137 MANGLE_RAW_STRING ("7class$$");
138 obstack_1grow (mangle_obstack, 'E');
141 static void
142 mangle_vtable (tree type)
144 MANGLE_RAW_STRING ("TV");
145 mangle_record_type (type, /* for_pointer = */ 0);
146 obstack_1grow (mangle_obstack, 'E');
149 /* This mangles a field decl */
151 static void
152 mangle_field_decl (tree decl)
154 /* Mangle the name of the this the field belongs to */
155 mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
157 /* Mangle the name of the field */
158 mangle_member_name (DECL_NAME (decl));
160 /* Terminate the mangled name */
161 obstack_1grow (mangle_obstack, 'E');
164 /* This mangles a method decl, first mangling its name and then all
165 its arguments. */
167 static void
168 mangle_method_decl (tree mdecl)
170 tree method_name = DECL_NAME (mdecl);
171 tree arglist;
173 /* Mangle the name of the type that contains mdecl */
174 mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
176 /* Mangle the function name. There are two cases:
177 - mdecl is a constructor, use `C1' for its name, (denotes a
178 complete object constructor.)
179 - mdecl is not a constructor, standard mangling is performed.
180 We terminate the mangled function name with a `E'. */
181 if (ID_INIT_P (method_name))
182 obstack_grow (mangle_obstack, "C1", 2);
183 else
184 mangle_member_name (method_name);
185 obstack_1grow (mangle_obstack, 'E');
187 /* We mangled type.methodName. Now onto the arguments. */
188 arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
189 if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
190 arglist = TREE_CHAIN (arglist);
192 /* Output literal 'J' and mangle the return type IF not a
193 constructor. */
194 if (!ID_INIT_P (method_name))
196 obstack_1grow (mangle_obstack, 'J');
197 mangle_type(TREE_TYPE(TREE_TYPE(mdecl)));
200 /* No arguments is easy. We shortcut it. */
201 if (arglist == end_params_node)
202 obstack_1grow (mangle_obstack, 'v');
203 else
205 tree arg;
206 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
207 mangle_type (TREE_VALUE (arg));
211 /* This mangles a CNI method for a local class. If the target supports
212 hidden aliases, then G++ will have generated one for us. It is the
213 responsibility of java_mark_class_local to check target support, since
214 we need to set DECL_VISIBILITY (or not) much earlier. */
216 static void
217 mangle_local_cni_method_decl (tree decl)
219 MANGLE_RAW_STRING ("GA");
220 mangle_method_decl (decl);
223 /* This mangles a member name, like a function name or a field
224 name. Handle cases were `name' is a C++ keyword. Return a nonzero
225 value if unicode encoding was required. */
227 static void
228 mangle_member_name (tree name)
230 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
231 IDENTIFIER_LENGTH (name));
234 /* Append the mangled name of TYPE onto OBSTACK. */
236 static void
237 mangle_type (tree type)
239 switch (TREE_CODE (type))
241 char code;
242 case BOOLEAN_TYPE: code = 'b'; goto primitive;
243 case VOID_TYPE: code = 'v'; goto primitive;
244 case INTEGER_TYPE:
245 if (type == char_type_node || type == promoted_char_type_node)
247 code = 'w';
248 goto primitive;
250 /* Get the original type instead of the arguments promoted type.
251 Avoid symbol name clashes. Should call a function to do that.
252 FIXME. */
253 if (type == promoted_short_type_node)
254 type = short_type_node;
255 if (type == promoted_byte_type_node)
256 type = byte_type_node;
257 switch (TYPE_PRECISION (type))
259 case 8: code = 'c'; goto primitive;
260 case 16: code = 's'; goto primitive;
261 case 32: code = 'i'; goto primitive;
262 case 64: code = 'x'; goto primitive;
263 default: goto bad_type;
265 primitive:
266 obstack_1grow (mangle_obstack, code);
267 break;
269 case REAL_TYPE:
270 switch (TYPE_PRECISION (type))
272 case 32: code = 'f'; goto primitive;
273 case 64: code = 'd'; goto primitive;
274 default: goto bad_type;
276 case POINTER_TYPE:
277 if (TYPE_ARRAY_P (TREE_TYPE (type)))
278 mangle_array_type (type);
279 else
280 mangle_pointer_type (type);
281 break;
282 bad_type:
283 default:
284 gcc_unreachable ();
288 /* The compression table is a vector that keeps track of things we've
289 already seen, so they can be reused. For example, java.lang.Object
290 would generate three entries: two package names and a type. If
291 java.lang.String is presented next, the java.lang will be matched
292 against the first two entries (and kept for compression as S0_), and
293 type String would be added to the table. See mangle_record_type.
294 COMPRESSION_NEXT is the index to the location of the next insertion
295 of an element. */
297 static GTY(()) tree compression_table;
298 static int compression_next;
300 /* Find a POINTER_TYPE in the compression table. Use a special
301 function to match pointer entries and start from the end */
303 static int
304 find_compression_pointer_match (tree type)
306 int i;
308 for (i = compression_next-1; i >= 0; i--)
309 if (entry_match_pointer_p (type, i))
310 return i;
311 return -1;
314 /* Already recorder arrays are handled like pointer as they're always
315 associated with it. */
317 static int
318 find_compression_array_match (tree type)
320 return find_compression_pointer_match (type);
323 /* Match the table of type against STRING. */
325 static int
326 find_compression_array_template_match (tree string)
328 int i;
329 for (i = 0; i < compression_next; i++)
330 if (TREE_VEC_ELT (compression_table, i) == string)
331 return i;
332 return -1;
335 /* We go through the compression table and try to find a complete or
336 partial match. The function returns the compression table entry
337 that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
338 to the rest of TYPE to be mangled. */
340 static int
341 find_compression_record_match (tree type, tree *next_current)
343 int i, match = -1;
344 tree current, saved_current = NULL_TREE;
346 current = TYPE_PACKAGE_LIST (type);
348 for (i = 0; i < compression_next; i++)
350 tree compression_entry = TREE_VEC_ELT (compression_table, i);
351 if (current && compression_entry == TREE_PURPOSE (current))
353 match = i;
354 saved_current = current;
355 current = TREE_CHAIN (current);
357 else
358 /* We don't want to match an element that appears in the middle
359 of a package name, so skip forward to the next complete type name.
360 IDENTIFIER_NODEs (except for a "6JArray") are partial package
361 names while RECORD_TYPEs represent complete type names. */
362 while (i < compression_next
363 && TREE_CODE (compression_entry) == IDENTIFIER_NODE
364 && compression_entry != atms)
365 compression_entry = TREE_VEC_ELT (compression_table, ++i);
368 if (!next_current)
369 return match;
371 /* If we have a match, set next_current to the item next to the last
372 matched value. */
373 if (match >= 0)
374 *next_current = TREE_CHAIN (saved_current);
375 /* We had no match: we'll have to start from the beginning. */
376 if (match < 0)
377 *next_current = TYPE_PACKAGE_LIST (type);
379 return match;
382 /* Mangle a record type. If a nonzero value is returned, it means
383 that a 'N' was emitted (so that a matching 'E' can be emitted if
384 necessary.) FOR_POINTER indicates that this element is for a pointer
385 symbol, meaning it was preceded by a 'P'. */
387 static int
388 mangle_record_type (tree type, int for_pointer)
390 tree current;
391 int match;
392 int nadded_p = 0;
393 int qualified;
395 /* Does this name have a package qualifier? */
396 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
398 #define ADD_N() \
399 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
401 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
403 if (!TYPE_PACKAGE_LIST (type))
404 set_type_package_list (type);
406 match = find_compression_record_match (type, &current);
407 if (match >= 0)
409 /* If we had a pointer, and there's more, we need to emit
410 'N' after 'P' (for_pointer tells us we already emitted it.) */
411 if (for_pointer && current)
412 ADD_N();
413 emit_compression_string (match);
415 while (current)
417 /* Add the new type to the table */
418 compression_table_add (TREE_PURPOSE (current));
419 /* Add 'N' if we never got a chance to, but only if we have a qualified
420 name. For non-pointer elements, the name is always qualified. */
421 if ((qualified || !for_pointer) && !nadded_p)
422 ADD_N();
423 /* Use the bare type name for the mangle. */
424 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
425 IDENTIFIER_LENGTH (TREE_VALUE (current)));
426 current = TREE_CHAIN (current);
428 return nadded_p;
429 #undef ADD_N
432 /* Mangle a pointer type. There are two cases: the pointer is already
433 in the compression table: the compression is emitted sans 'P'
434 indicator. Otherwise, a 'P' is emitted and, depending on the type,
435 a partial compression or/plus the rest of the mangling. */
437 static void
438 mangle_pointer_type (tree type)
440 int match;
441 tree pointer_type;
443 /* Search for the type already in the compression table */
444 if ((match = find_compression_pointer_match (type)) >= 0)
446 emit_compression_string (match);
447 return;
450 /* This didn't work. We start by mangling the pointed-to type */
451 pointer_type = type;
452 type = TREE_TYPE (type);
453 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
455 obstack_1grow (mangle_obstack, 'P');
456 if (mangle_record_type (type, /* for_pointer = */ 1))
457 obstack_1grow (mangle_obstack, 'E');
459 /* Don't forget to insert the pointer type in the table */
460 compression_table_add (pointer_type);
463 /* Mangle an array type. Search for an easy solution first, then go
464 through the process of finding out whether the bare array type or even
465 the template indicator were already used and compressed appropriately.
466 It handles pointers. */
468 static void
469 mangle_array_type (tree p_type)
471 tree type, elt_type;
472 int match;
474 type = TREE_TYPE (p_type);
475 gcc_assert (type);
477 elt_type = TYPE_ARRAY_ELEMENT (type);
479 /* We cache a bit of the Jarray <> mangle. */
480 if (!atms)
482 atms = get_identifier ("6JArray");
485 /* Maybe we have what we're looking for in the compression table. */
486 if ((match = find_compression_array_match (p_type)) >= 0)
488 emit_compression_string (match);
489 return;
492 /* We know for a fact that all arrays are pointers */
493 obstack_1grow (mangle_obstack, 'P');
494 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
495 if ((match = find_compression_record_match (type, NULL)) > 0)
497 emit_compression_string (match);
498 return;
501 /* Maybe we already have just JArray somewhere */
502 if ((match = find_compression_array_template_match (atms)) > 0)
503 emit_compression_string (match);
504 else
506 /* Start the template mangled name */
507 obstack_grow (mangle_obstack,
508 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
509 /* Insert in the compression table */
510 compression_table_add (atms);
513 /* Mangle Jarray <elt_type> */
514 obstack_1grow (mangle_obstack, 'I');
515 mangle_type (elt_type);
516 obstack_1grow (mangle_obstack, 'E');
518 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
519 compression_table_add (type);
520 compression_table_add (p_type);
523 /* Write a substitution string for entry I. Substitution string starts a
524 -1 (encoded S_.) The base is 36, and the code shamelessly taken from
525 cp/mangle.c. */
527 static void
528 emit_compression_string (int i)
530 i -= 1; /* Adjust */
531 obstack_1grow (mangle_obstack, 'S');
532 if (i >= 0)
534 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
535 unsigned HOST_WIDE_INT n;
536 unsigned HOST_WIDE_INT m=1;
537 /* How many digits for I in base 36? */
538 for (n = i; n >= 36; n /= 36, m *=36);
539 /* Write the digits out */
540 while (m > 0)
542 int digit = i / m;
543 obstack_1grow (mangle_obstack, digits [digit]);
544 i -= digit * m;
545 m /= 36;
548 obstack_1grow (mangle_obstack, '_');
551 /* If search the compression table at index I for a pointer type
552 equivalent to TYPE (meaning that after all the indirection, which
553 might all be unique, we find the same RECORD_TYPE.) */
555 static int
556 entry_match_pointer_p (tree type, int i)
558 tree t = TREE_VEC_ELT (compression_table, i);
560 while (TREE_CODE (type) == POINTER_TYPE
561 && TREE_CODE (t) == POINTER_TYPE)
563 t = TREE_TYPE (t);
564 type = TREE_TYPE (type);
566 return (TREE_CODE (type) == RECORD_TYPE
567 && TREE_CODE (t) == RECORD_TYPE
568 && t == type);
571 /* Go through all qualification of type and build a list of list node
572 elements containings as a purpose what should be used for a match and
573 inserted in the compression table; and as it value the raw name of the
574 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
576 static void
577 set_type_package_list (tree type)
579 int i;
580 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
581 const char *ptr;
582 int qualifications;
583 tree list = NULL_TREE, elt;
585 for (ptr = type_string, qualifications = 0; *ptr; ptr++)
586 if (*ptr == '.')
587 qualifications += 1;
589 for (ptr = type_string, i = 0; i < qualifications; ptr++)
591 if (ptr [0] == '.')
593 tree const identifier
594 = get_identifier_with_length (type_string, ptr - type_string);
596 elt = build_tree_list (identifier, identifier);
597 TREE_CHAIN (elt) = list;
598 list = elt;
599 type_string = ptr+1;
600 i += 1;
604 elt = build_tree_list (type, get_identifier (type_string));
605 TREE_CHAIN (elt) = list;
606 list = elt;
607 TYPE_PACKAGE_LIST (type) = nreverse (list);
610 /* Add TYPE as the last element of the compression table. Resize the
611 compression table if necessary. */
613 static void
614 compression_table_add (tree type)
616 if (compression_next == TREE_VEC_LENGTH (compression_table))
618 tree new_table = make_tree_vec (2*compression_next);
619 int i;
621 for (i = 0; i < compression_next; i++)
622 TREE_VEC_ELT (new_table, i) = TREE_VEC_ELT (compression_table, i);
624 compression_table = new_table;
626 TREE_VEC_ELT (compression_table, compression_next++) = type;
629 /* Mangle an embedded resource file name. "_ZGr" is the prefix. A
630 '_' is prepended to the name so that names starting with a digit
631 can be demangled. The length and then the resulting name itself
632 are appended while escaping '$', '.', and '/' to: "$$", "$_", and
633 "$S". */
635 tree
636 java_mangle_resource_name (const char *name)
638 int len = strlen (name);
639 char *buf = (char *) alloca (2 * len + 1);
640 char *pos;
641 const unsigned char *w1 = (const unsigned char *) name;
642 const unsigned char *w2;
643 const unsigned char *limit = w1 + len;
645 pos = buf;
647 init_mangling ();
648 MANGLE_RAW_STRING ("Gr");
650 *pos++ = '_';
651 while (w1 < limit)
653 int ch;
654 w2 = w1;
655 ch = UTF8_GET (w1, limit);
656 gcc_assert (ch > 0);
657 switch (ch)
659 case '$':
660 *pos++ = '$';
661 *pos++ = '$';
662 break;
663 case '.':
664 *pos++ = '$';
665 *pos++ = '_';
666 break;
667 case '/':
668 *pos++ = '$';
669 *pos++ = 'S';
670 break;
671 default:
672 memcpy (pos, w2, w1 - w2);
673 pos += w1 - w2;
674 break;
677 append_gpp_mangled_name (buf, pos - buf);
679 return finish_mangling ();
682 /* Mangling initialization routine. */
684 static void
685 init_mangling (void)
687 if (!mangle_obstack)
689 mangle_obstack = &mangle_obstack_1;
690 gcc_obstack_init (mangle_obstack);
693 gcc_assert (compression_table == NULL);
694 compression_table = make_tree_vec (10);
696 /* Mangled name are to be suffixed */
697 MANGLE_RAW_STRING ("_Z");
700 /* Mangling finalization routine. The mangled name is returned as a
701 IDENTIFIER_NODE. */
703 static tree
704 finish_mangling (void)
706 tree result;
708 gcc_assert (compression_table);
710 compression_table = NULL_TREE;
711 compression_next = 0;
712 obstack_1grow (mangle_obstack, '\0');
713 result = get_identifier (obstack_base (mangle_obstack));
714 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
716 return result;
719 #include "gt-java-mangle.h"