OSDN Git Service

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