OSDN Git Service

Fixes java/PR9861
[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
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, 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, 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 "ggc.h"
39 #include "langhooks-def.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_CONTEXT (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 type)
134 {
135   mangle_record_type (type, /* for_pointer = */ 0);
136   MANGLE_RAW_STRING ("6class$");
137   obstack_1grow (mangle_obstack, 'E');
138 }
139
140 static void
141 mangle_vtable (tree type)
142 {
143   MANGLE_RAW_STRING ("TV");
144   mangle_record_type (type, /* for_pointer = */ 0);
145   obstack_1grow (mangle_obstack, 'E');
146 }
147
148 /* This mangles a field decl */
149
150 static void
151 mangle_field_decl (tree decl)
152 {
153   /* Mangle the name of the this the field belongs to */
154   mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
155   
156   /* Mangle the name of the field */
157   mangle_member_name (DECL_NAME (decl));
158
159   /* Terminate the mangled name */
160   obstack_1grow (mangle_obstack, 'E');
161 }
162
163 /* This mangles a method decl, first mangling its name and then all
164    its arguments. */
165
166 static void
167 mangle_method_decl (tree mdecl)
168 {
169   tree method_name = DECL_NAME (mdecl);
170   tree arglist;
171
172   /* Mangle the name of the type that contains mdecl */
173   mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
174
175   /* Mangle the function name.  There are two cases:
176        - mdecl is a constructor, use `C1' for its name, (denotes a
177          complete object constructor.)
178        - mdecl is not a constructor, standard mangling is performed.
179      We terminate the mangled function name with a `E'. */
180   if (ID_INIT_P (method_name))
181     obstack_grow (mangle_obstack, "C1", 2);
182   else
183     mangle_member_name (method_name);
184   obstack_1grow (mangle_obstack, 'E');
185
186   /* We mangled type.methodName. Now onto the arguments. */
187   arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
188   if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
189     arglist = TREE_CHAIN (arglist);
190   
191   /* Output literal 'J' and mangle the return type IF not a 
192      constructor.  */
193   if (!ID_INIT_P (method_name))
194     {
195       obstack_1grow (mangle_obstack, 'J');
196       mangle_type(TREE_TYPE(TREE_TYPE(mdecl)));
197     }
198   
199   /* No arguments is easy. We shortcut it. */
200   if (arglist == end_params_node)
201     obstack_1grow (mangle_obstack, 'v');
202   else
203     {
204       tree arg;
205       for (arg = arglist; arg != end_params_node;  arg = TREE_CHAIN (arg))
206         mangle_type (TREE_VALUE (arg));
207     }
208 }
209
210 /* This mangles a CNI method for a local class.  If the target supports
211    hidden aliases, then G++ will have generated one for us.  It is the
212    responsibility of java_mark_class_local to check target support, since
213    we need to set DECL_VISIBILITY (or not) much earlier.  */
214
215 static void
216 mangle_local_cni_method_decl (tree decl)
217 {
218   MANGLE_RAW_STRING ("GA");
219   mangle_method_decl (decl);
220 }
221
222 /* This mangles a member name, like a function name or a field
223    name. Handle cases were `name' is a C++ keyword.  Return a nonzero
224    value if unicode encoding was required.  */
225
226 static void
227 mangle_member_name (tree name)
228 {
229   append_gpp_mangled_name (IDENTIFIER_POINTER (name),
230                            IDENTIFIER_LENGTH (name));
231
232   /* If NAME happens to be a C++ keyword, add `$'. */
233   if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
234     obstack_1grow (mangle_obstack, '$');
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 CHAR_TYPE:    code = 'w';  goto primitive;
247     case VOID_TYPE:    code = 'v';  goto primitive;
248     case INTEGER_TYPE:
249       /* Get the original type instead of the arguments promoted type.
250          Avoid symbol name clashes. Should call a function to do that.
251          FIXME.  */
252       if (type == promoted_short_type_node)
253         type = short_type_node;
254       if (type == promoted_byte_type_node)
255         type = byte_type_node;
256       switch (TYPE_PRECISION (type))
257         {
258         case  8:       code = 'c';  goto primitive;
259         case 16:       code = 's';  goto primitive;
260         case 32:       code = 'i';  goto primitive;
261         case 64:       code = 'x';  goto primitive;
262         default:  goto bad_type;
263         }
264     primitive:
265       obstack_1grow (mangle_obstack, code);
266       break;
267
268     case REAL_TYPE:
269       switch (TYPE_PRECISION (type))
270         {
271         case 32:       code = 'f';  goto primitive;
272         case 64:       code = 'd';  goto primitive;
273         default:  goto bad_type;
274         }
275     case POINTER_TYPE:
276       if (TYPE_ARRAY_P (TREE_TYPE (type)))
277         mangle_array_type (type);
278       else
279         mangle_pointer_type (type);
280       break;
281     bad_type:
282     default:
283       abort ();
284     }
285 }
286
287 /* The compression table is a vector that keeps track of things we've
288    already seen, so they can be reused. For example, java.lang.Object
289    would generate three entries: two package names and a type. If
290    java.lang.String is presented next, the java.lang will be matched
291    against the first two entries (and kept for compression as S0_), and
292    type String would be added to the table. See mangle_record_type.
293    COMPRESSION_NEXT is the index to the location of the next insertion
294    of an element.  */
295
296 static GTY(()) tree compression_table;
297 static int  compression_next;
298
299 /* Find a POINTER_TYPE in the compression table. Use a special
300    function to match pointer entries and start from the end */
301
302 static int
303 find_compression_pointer_match (tree type)
304 {
305   int i;
306
307   for (i = compression_next-1; i >= 0; i--)
308     if (entry_match_pointer_p (type, i))
309       return i;
310   return -1;
311 }
312
313 /* Already recorder arrays are handled like pointer as they're always
314    associated with it.  */
315
316 static int
317 find_compression_array_match (tree type)
318 {
319   return find_compression_pointer_match (type);
320 }
321
322 /* Match the table of type against STRING.  */
323
324 static int
325 find_compression_array_template_match (tree string)
326 {
327   int i;
328   for (i = 0; i < compression_next; i++)
329     if (TREE_VEC_ELT (compression_table, i) == string) 
330       return i;
331   return -1;
332 }
333
334 /* We go through the compression table and try to find a complete or
335    partial match. The function returns the compression table entry
336    that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
337    to the rest of TYPE to be mangled. */
338
339 static int
340 find_compression_record_match (tree type, tree *next_current)
341 {
342   int i, match = -1;
343   tree current, saved_current = NULL_TREE;
344
345   current = TYPE_PACKAGE_LIST (type);
346       
347   for (i = 0; i < compression_next; i++)
348     {
349       tree compression_entry = TREE_VEC_ELT (compression_table, i);
350       if (current && compression_entry == TREE_PURPOSE (current))
351         {
352           match = i;
353           saved_current = current;
354           current = TREE_CHAIN (current);
355         }
356       else
357         /* We don't want to match an element that appears in the middle
358            of a package name, so skip forward to the next complete type name.
359            IDENTIFIER_NODEs (except for a "6JArray") are partial package
360            names while RECORD_TYPEs represent complete type names. */
361         while (i < compression_next 
362                && TREE_CODE (compression_entry) == IDENTIFIER_NODE
363                && compression_entry != atms)
364           compression_entry = TREE_VEC_ELT (compression_table, ++i);
365     }
366
367   if (!next_current)
368     return match;
369
370   /* If we have a match, set next_current to the item next to the last
371      matched value. */
372   if (match >= 0)
373     *next_current = TREE_CHAIN (saved_current);
374   /* We had no match: we'll have to start from the beginning. */
375   if (match < 0)
376     *next_current = TYPE_PACKAGE_LIST (type);
377
378   return match;
379 }
380
381 /* Mangle a record type. If a nonzero value is returned, it means
382    that a 'N' was emitted (so that a matching 'E' can be emitted if
383    necessary.)  FOR_POINTER indicates that this element is for a pointer
384    symbol, meaning it was preceded by a 'P'. */
385
386 static int
387 mangle_record_type (tree type, int for_pointer)
388 {
389   tree current;
390   int match;
391   int nadded_p = 0;
392   int qualified;
393   
394   /* Does this name have a package qualifier? */
395   qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
396
397 #define ADD_N() \
398   do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
399
400   if (TREE_CODE (type) != RECORD_TYPE)
401     abort ();
402
403   if (!TYPE_PACKAGE_LIST (type))
404     set_type_package_list (type);
405
406   match = find_compression_record_match (type, &current);
407   if (match >= 0)
408     {
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);
414     }
415   while (current)
416     {
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);
427     }
428   return nadded_p;
429 #undef ADD_N
430 }
431
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. */
436
437 static void
438 mangle_pointer_type (tree type)
439 {
440   int match;
441   tree pointer_type;
442
443   /* Search for the type already in the compression table */
444   if ((match = find_compression_pointer_match (type)) >= 0) 
445     {
446       emit_compression_string (match);
447       return;
448     }
449   
450   /* This didn't work. We start by mangling the pointed-to type */
451   pointer_type = type;
452   type = TREE_TYPE (type);
453   if (TREE_CODE (type) != RECORD_TYPE)
454     abort ();
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
470 mangle_array_type (tree p_type)
471 {
472   tree type, elt_type;
473   int match;
474
475   type = TREE_TYPE (p_type);
476   if (!type)
477     abort ();
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   char *ptr;
584   int qualifications;
585   tree list = NULL_TREE, elt;
586
587   for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
588     if (*ptr == '.')
589       qualifications += 1;
590
591   for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
592     {
593       if (ptr [0] == '.')
594         {
595           char c;
596           tree identifier;
597
598           /* Can't use an obstack, we're already using it to
599              accumulate the mangling. */
600           c = ptr [0];
601           ptr [0] = '\0';
602           identifier = get_identifier (type_string);
603           ptr [0] = c;
604           elt = build_tree_list (identifier, identifier);
605           TREE_CHAIN (elt) = list;
606           list = elt;
607           type_string = ptr+1;
608           i += 1;
609         }
610     }
611
612   elt = build_tree_list (type, get_identifier (type_string));
613   TREE_CHAIN (elt) = list;
614   list = elt;
615   TYPE_PACKAGE_LIST (type) = nreverse (list);
616 }
617
618 /* Add TYPE as the last element of the compression table. Resize the
619    compression table if necessary.  */
620
621 static void
622 compression_table_add (tree type)
623 {
624   if (compression_next == TREE_VEC_LENGTH (compression_table))
625     {
626       tree new = make_tree_vec (2*compression_next);
627       int i;
628
629       for (i = 0; i < compression_next; i++)
630         TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
631
632       compression_table = new;
633     }
634   TREE_VEC_ELT (compression_table, compression_next++) = type;
635 }
636
637 /* Mangling initialization routine.  */
638
639 static void
640 init_mangling (void)
641 {
642   if (!mangle_obstack)
643     {
644       mangle_obstack = &mangle_obstack_1;
645       gcc_obstack_init (mangle_obstack);
646     }
647
648   gcc_assert (compression_table == NULL);
649   compression_table = make_tree_vec (10);
650
651   /* Mangled name are to be suffixed */
652   MANGLE_RAW_STRING ("_Z");
653 }
654
655 /* Mangling finalization routine. The mangled name is returned as a
656    IDENTIFIER_NODE.  */
657
658 static tree
659 finish_mangling (void)
660 {
661   tree result;
662
663   gcc_assert (compression_table);
664
665   compression_table = NULL_TREE;
666   compression_next = 0;
667   obstack_1grow (mangle_obstack, '\0');
668   result = get_identifier (obstack_base (mangle_obstack));
669   obstack_free (mangle_obstack, obstack_base (mangle_obstack));
670
671   return result;
672 }
673
674 #include "gt-java-mangle.h"