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