OSDN Git Service

2006-02-09 Andrew Haley <aph@redhat.com>
[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 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   char *ptr;
585   int qualifications;
586   tree list = NULL_TREE, elt;
587
588   for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
589     if (*ptr == '.')
590       qualifications += 1;
591
592   for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
593     {
594       if (ptr [0] == '.')
595         {
596           char c;
597           tree identifier;
598
599           /* Can't use an obstack, we're already using it to
600              accumulate the mangling. */
601           c = ptr [0];
602           ptr [0] = '\0';
603           identifier = get_identifier (type_string);
604           ptr [0] = c;
605           elt = build_tree_list (identifier, identifier);
606           TREE_CHAIN (elt) = list;
607           list = elt;
608           type_string = ptr+1;
609           i += 1;
610         }
611     }
612
613   elt = build_tree_list (type, get_identifier (type_string));
614   TREE_CHAIN (elt) = list;
615   list = elt;
616   TYPE_PACKAGE_LIST (type) = nreverse (list);
617 }
618
619 /* Add TYPE as the last element of the compression table. Resize the
620    compression table if necessary.  */
621
622 static void
623 compression_table_add (tree type)
624 {
625   if (compression_next == TREE_VEC_LENGTH (compression_table))
626     {
627       tree new = make_tree_vec (2*compression_next);
628       int i;
629
630       for (i = 0; i < compression_next; i++)
631         TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
632
633       compression_table = new;
634     }
635   TREE_VEC_ELT (compression_table, compression_next++) = type;
636 }
637
638 /* Mangling initialization routine.  */
639
640 static void
641 init_mangling (void)
642 {
643   if (!mangle_obstack)
644     {
645       mangle_obstack = &mangle_obstack_1;
646       gcc_obstack_init (mangle_obstack);
647     }
648
649   gcc_assert (compression_table == NULL);
650   compression_table = make_tree_vec (10);
651
652   /* Mangled name are to be suffixed */
653   MANGLE_RAW_STRING ("_Z");
654 }
655
656 /* Mangling finalization routine. The mangled name is returned as a
657    IDENTIFIER_NODE.  */
658
659 static tree
660 finish_mangling (void)
661 {
662   tree result;
663
664   gcc_assert (compression_table);
665
666   compression_table = NULL_TREE;
667   compression_next = 0;
668   obstack_1grow (mangle_obstack, '\0');
669   result = get_identifier (obstack_base (mangle_obstack));
670   obstack_free (mangle_obstack, obstack_base (mangle_obstack));
671
672   return result;
673 }
674
675 #include "gt-java-mangle.h"