OSDN Git Service

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