OSDN Git Service

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