OSDN Git Service

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