OSDN Git Service

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