OSDN Git Service

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