OSDN Git Service

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