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