2005-06-07 Thomas Koenig <Thomas.Koenig@online.de>
[official-gcc.git] / gcc / java / mangle.c
blob22a391839a720a508323112d3a11f60cb4e6ca44
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.
6 This file is part of GCC.
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.
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.
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.
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. */
27 /* Written by Per Bothner <bothner@cygnus.com> */
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"
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);
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);
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);
57 static void set_type_package_list (tree);
58 static int entry_match_pointer_p (tree, int);
59 static void emit_compression_string (int);
61 static void init_mangling (void);
62 static tree finish_mangling (void);
63 static void compression_table_add (tree);
65 static void mangle_member_name (tree);
67 static struct obstack mangle_obstack_1;
68 struct obstack *mangle_obstack;
70 #define MANGLE_RAW_STRING(S) \
71 obstack_grow (mangle_obstack, (S), sizeof (S)-1)
73 /* atms: array template mangled string. */
74 static GTY(()) tree atms;
76 /* This is the mangling interface: a decl, a class field (.class) and
77 the vtable. */
79 void
80 java_mangle_decl (tree decl)
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))));
91 /* Mangling only applies to class members. */
92 if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
94 init_mangling ();
95 switch (TREE_CODE (decl))
97 case VAR_DECL:
98 if (DECL_LANG_SPECIFIC (decl))
100 if (DECL_CLASS_FIELD_P (decl))
102 mangle_class_field (DECL_CONTEXT (decl));
103 break;
105 else if (DECL_VTABLE_P (decl))
107 mangle_vtable (DECL_CONTEXT (decl));
108 break;
111 mangle_field_decl (decl);
112 break;
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;
121 default:
122 gcc_unreachable ();
124 SET_DECL_ASSEMBLER_NAME (decl, finish_mangling ());
126 else
127 lhd_set_decl_assembler_name (decl);
130 /* Beginning of the helper functions */
132 static void
133 mangle_class_field (tree type)
135 mangle_record_type (type, /* for_pointer = */ 0);
136 MANGLE_RAW_STRING ("6class$");
137 obstack_1grow (mangle_obstack, 'E');
140 static void
141 mangle_vtable (tree type)
143 MANGLE_RAW_STRING ("TV");
144 mangle_record_type (type, /* for_pointer = */ 0);
145 obstack_1grow (mangle_obstack, 'E');
148 /* This mangles a field decl */
150 static void
151 mangle_field_decl (tree decl)
153 /* Mangle the name of the this the field belongs to */
154 mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
156 /* Mangle the name of the field */
157 mangle_member_name (DECL_NAME (decl));
159 /* Terminate the mangled name */
160 obstack_1grow (mangle_obstack, 'E');
163 /* This mangles a method decl, first mangling its name and then all
164 its arguments. */
166 static void
167 mangle_method_decl (tree mdecl)
169 tree method_name = DECL_NAME (mdecl);
170 tree arglist;
172 /* Mangle the name of the type that contains mdecl */
173 mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
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');
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);
191 /* No arguments is easy. We shortcut it. */
192 if (arglist == end_params_node)
193 obstack_1grow (mangle_obstack, 'v');
194 else
196 tree arg;
197 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
198 mangle_type (TREE_VALUE (arg));
202 /* This mangles a CNI method for a local class. If the target supports
203 hidden aliases, then G++ will have generated one for us. It is the
204 responsibility of java_mark_class_local to check target support, since
205 we need to set DECL_VISIBILITY (or not) much earlier. */
207 static void
208 mangle_local_cni_method_decl (tree decl)
210 MANGLE_RAW_STRING ("GA");
211 mangle_method_decl (decl);
214 /* This mangles a member name, like a function name or a field
215 name. Handle cases were `name' is a C++ keyword. Return a nonzero
216 value if unicode encoding was required. */
218 static void
219 mangle_member_name (tree name)
221 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
222 IDENTIFIER_LENGTH (name));
224 /* If NAME happens to be a C++ keyword, add `$'. */
225 if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
226 obstack_1grow (mangle_obstack, '$');
229 /* Append the mangled name of TYPE onto OBSTACK. */
231 static void
232 mangle_type (tree type)
234 switch (TREE_CODE (type))
236 char code;
237 case BOOLEAN_TYPE: code = 'b'; goto primitive;
238 case CHAR_TYPE: code = 'w'; goto primitive;
239 case VOID_TYPE: code = 'v'; goto primitive;
240 case INTEGER_TYPE:
241 /* Get the original type instead of the arguments promoted type.
242 Avoid symbol name clashes. Should call a function to do that.
243 FIXME. */
244 if (type == promoted_short_type_node)
245 type = short_type_node;
246 if (type == promoted_byte_type_node)
247 type = byte_type_node;
248 switch (TYPE_PRECISION (type))
250 case 8: code = 'c'; goto primitive;
251 case 16: code = 's'; goto primitive;
252 case 32: code = 'i'; goto primitive;
253 case 64: code = 'x'; goto primitive;
254 default: goto bad_type;
256 primitive:
257 obstack_1grow (mangle_obstack, code);
258 break;
260 case REAL_TYPE:
261 switch (TYPE_PRECISION (type))
263 case 32: code = 'f'; goto primitive;
264 case 64: code = 'd'; goto primitive;
265 default: goto bad_type;
267 case POINTER_TYPE:
268 if (TYPE_ARRAY_P (TREE_TYPE (type)))
269 mangle_array_type (type);
270 else
271 mangle_pointer_type (type);
272 break;
273 bad_type:
274 default:
275 abort ();
279 /* The compression table is a vector that keeps track of things we've
280 already seen, so they can be reused. For example, java.lang.Object
281 would generate three entries: two package names and a type. If
282 java.lang.String is presented next, the java.lang will be matched
283 against the first two entries (and kept for compression as S0_), and
284 type String would be added to the table. See mangle_record_type.
285 COMPRESSION_NEXT is the index to the location of the next insertion
286 of an element. */
288 static GTY(()) tree compression_table;
289 static int compression_next;
291 /* Find a POINTER_TYPE in the compression table. Use a special
292 function to match pointer entries and start from the end */
294 static int
295 find_compression_pointer_match (tree type)
297 int i;
299 for (i = compression_next-1; i >= 0; i--)
300 if (entry_match_pointer_p (type, i))
301 return i;
302 return -1;
305 /* Already recorder arrays are handled like pointer as they're always
306 associated with it. */
308 static int
309 find_compression_array_match (tree type)
311 return find_compression_pointer_match (type);
314 /* Match the table of type against STRING. */
316 static int
317 find_compression_array_template_match (tree string)
319 int i;
320 for (i = 0; i < compression_next; i++)
321 if (TREE_VEC_ELT (compression_table, i) == string)
322 return i;
323 return -1;
326 /* We go through the compression table and try to find a complete or
327 partial match. The function returns the compression table entry
328 that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
329 to the rest of TYPE to be mangled. */
331 static int
332 find_compression_record_match (tree type, tree *next_current)
334 int i, match = -1;
335 tree current, saved_current = NULL_TREE;
337 current = TYPE_PACKAGE_LIST (type);
339 for (i = 0; i < compression_next; i++)
341 tree compression_entry = TREE_VEC_ELT (compression_table, i);
342 if (current && compression_entry == TREE_PURPOSE (current))
344 match = i;
345 saved_current = current;
346 current = TREE_CHAIN (current);
348 else
349 /* We don't want to match an element that appears in the middle
350 of a package name, so skip forward to the next complete type name.
351 IDENTIFIER_NODEs (except for a "6JArray") are partial package
352 names while RECORD_TYPEs represent complete type names. */
353 while (i < compression_next
354 && TREE_CODE (compression_entry) == IDENTIFIER_NODE
355 && compression_entry != atms)
356 compression_entry = TREE_VEC_ELT (compression_table, ++i);
359 if (!next_current)
360 return match;
362 /* If we have a match, set next_current to the item next to the last
363 matched value. */
364 if (match >= 0)
365 *next_current = TREE_CHAIN (saved_current);
366 /* We had no match: we'll have to start from the beginning. */
367 if (match < 0)
368 *next_current = TYPE_PACKAGE_LIST (type);
370 return match;
373 /* Mangle a record type. If a nonzero value is returned, it means
374 that a 'N' was emitted (so that a matching 'E' can be emitted if
375 necessary.) FOR_POINTER indicates that this element is for a pointer
376 symbol, meaning it was preceded by a 'P'. */
378 static int
379 mangle_record_type (tree type, int for_pointer)
381 tree current;
382 int match;
383 int nadded_p = 0;
384 int qualified;
386 /* Does this name have a package qualifier? */
387 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
389 #define ADD_N() \
390 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
392 if (TREE_CODE (type) != RECORD_TYPE)
393 abort ();
395 if (!TYPE_PACKAGE_LIST (type))
396 set_type_package_list (type);
398 match = find_compression_record_match (type, &current);
399 if (match >= 0)
401 /* If we had a pointer, and there's more, we need to emit
402 'N' after 'P' (for_pointer tells us we already emitted it.) */
403 if (for_pointer && current)
404 ADD_N();
405 emit_compression_string (match);
407 while (current)
409 /* Add the new type to the table */
410 compression_table_add (TREE_PURPOSE (current));
411 /* Add 'N' if we never got a chance to, but only if we have a qualified
412 name. For non-pointer elements, the name is always qualified. */
413 if ((qualified || !for_pointer) && !nadded_p)
414 ADD_N();
415 /* Use the bare type name for the mangle. */
416 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
417 IDENTIFIER_LENGTH (TREE_VALUE (current)));
418 current = TREE_CHAIN (current);
420 return nadded_p;
421 #undef ADD_N
424 /* Mangle a pointer type. There are two cases: the pointer is already
425 in the compression table: the compression is emitted sans 'P'
426 indicator. Otherwise, a 'P' is emitted and, depending on the type,
427 a partial compression or/plus the rest of the mangling. */
429 static void
430 mangle_pointer_type (tree type)
432 int match;
433 tree pointer_type;
435 /* Search for the type already in the compression table */
436 if ((match = find_compression_pointer_match (type)) >= 0)
438 emit_compression_string (match);
439 return;
442 /* This didn't work. We start by mangling the pointed-to type */
443 pointer_type = type;
444 type = TREE_TYPE (type);
445 if (TREE_CODE (type) != RECORD_TYPE)
446 abort ();
448 obstack_1grow (mangle_obstack, 'P');
449 if (mangle_record_type (type, /* for_pointer = */ 1))
450 obstack_1grow (mangle_obstack, 'E');
452 /* Don't forget to insert the pointer type in the table */
453 compression_table_add (pointer_type);
456 /* Mangle an array type. Search for an easy solution first, then go
457 through the process of finding out whether the bare array type or even
458 the template indicator were already used and compressed appropriately.
459 It handles pointers. */
461 static void
462 mangle_array_type (tree p_type)
464 tree type, elt_type;
465 int match;
467 type = TREE_TYPE (p_type);
468 if (!type)
469 abort ();
471 elt_type = TYPE_ARRAY_ELEMENT (type);
473 /* We cache a bit of the Jarray <> mangle. */
474 if (!atms)
476 atms = get_identifier ("6JArray");
479 /* Maybe we have what we're looking for in the compression table. */
480 if ((match = find_compression_array_match (p_type)) >= 0)
482 emit_compression_string (match);
483 return;
486 /* We know for a fact that all arrays are pointers */
487 obstack_1grow (mangle_obstack, 'P');
488 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
489 if ((match = find_compression_record_match (type, NULL)) > 0)
491 emit_compression_string (match);
492 return;
495 /* Maybe we already have just JArray somewhere */
496 if ((match = find_compression_array_template_match (atms)) > 0)
497 emit_compression_string (match);
498 else
500 /* Start the template mangled name */
501 obstack_grow (mangle_obstack,
502 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
503 /* Insert in the compression table */
504 compression_table_add (atms);
507 /* Mangle Jarray <elt_type> */
508 obstack_1grow (mangle_obstack, 'I');
509 mangle_type (elt_type);
510 obstack_1grow (mangle_obstack, 'E');
512 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
513 compression_table_add (type);
514 compression_table_add (p_type);
517 /* Write a substitution string for entry I. Substitution string starts a
518 -1 (encoded S_.) The base is 36, and the code shamelessly taken from
519 cp/mangle.c. */
521 static void
522 emit_compression_string (int i)
524 i -= 1; /* Adjust */
525 obstack_1grow (mangle_obstack, 'S');
526 if (i >= 0)
528 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
529 unsigned HOST_WIDE_INT n;
530 unsigned HOST_WIDE_INT m=1;
531 /* How many digits for I in base 36? */
532 for (n = i; n >= 36; n /= 36, m *=36);
533 /* Write the digits out */
534 while (m > 0)
536 int digit = i / m;
537 obstack_1grow (mangle_obstack, digits [digit]);
538 i -= digit * m;
539 m /= 36;
542 obstack_1grow (mangle_obstack, '_');
545 /* If search the compression table at index I for a pointer type
546 equivalent to TYPE (meaning that after all the indirection, which
547 might all be unique, we find the same RECORD_TYPE.) */
549 static int
550 entry_match_pointer_p (tree type, int i)
552 tree t = TREE_VEC_ELT (compression_table, i);
554 while (TREE_CODE (type) == POINTER_TYPE
555 && TREE_CODE (t) == POINTER_TYPE)
557 t = TREE_TYPE (t);
558 type = TREE_TYPE (type);
560 return (TREE_CODE (type) == RECORD_TYPE
561 && TREE_CODE (t) == RECORD_TYPE
562 && t == type);
565 /* Go through all qualification of type and build a list of list node
566 elements containings as a purpose what should be used for a match and
567 inserted in the compression table; and as it value the raw name of the
568 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
570 static void
571 set_type_package_list (tree type)
573 int i;
574 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
575 char *ptr;
576 int qualifications;
577 tree list = NULL_TREE, elt;
579 for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
580 if (*ptr == '.')
581 qualifications += 1;
583 for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
585 if (ptr [0] == '.')
587 char c;
588 tree identifier;
590 /* Can't use an obstack, we're already using it to
591 accumulate the mangling. */
592 c = ptr [0];
593 ptr [0] = '\0';
594 identifier = get_identifier (type_string);
595 ptr [0] = c;
596 elt = build_tree_list (identifier, identifier);
597 TREE_CHAIN (elt) = list;
598 list = elt;
599 type_string = ptr+1;
600 i += 1;
604 elt = build_tree_list (type, get_identifier (type_string));
605 TREE_CHAIN (elt) = list;
606 list = elt;
607 TYPE_PACKAGE_LIST (type) = nreverse (list);
610 /* Add TYPE as the last element of the compression table. Resize the
611 compression table if necessary. */
613 static void
614 compression_table_add (tree type)
616 if (compression_next == TREE_VEC_LENGTH (compression_table))
618 tree new = make_tree_vec (2*compression_next);
619 int i;
621 for (i = 0; i < compression_next; i++)
622 TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
624 compression_table = new;
626 TREE_VEC_ELT (compression_table, compression_next++) = type;
629 /* Mangling initialization routine. */
631 static void
632 init_mangling (void)
634 if (!mangle_obstack)
636 mangle_obstack = &mangle_obstack_1;
637 gcc_obstack_init (mangle_obstack);
640 gcc_assert (compression_table == NULL);
641 compression_table = make_tree_vec (10);
643 /* Mangled name are to be suffixed */
644 MANGLE_RAW_STRING ("_Z");
647 /* Mangling finalization routine. The mangled name is returned as a
648 IDENTIFIER_NODE. */
650 static tree
651 finish_mangling (void)
653 tree result;
655 gcc_assert (compression_table);
657 compression_table = NULL_TREE;
658 compression_next = 0;
659 obstack_1grow (mangle_obstack, '\0');
660 result = get_identifier (obstack_base (mangle_obstack));
661 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
663 return result;
666 #include "gt-java-mangle.h"