2006-06-06 Paolo Carlini <pcarlini@suse.de>
[official-gcc.git] / gcc / java / mangle.c
blob0fe5220b5b2b5173459fc78f78babeadb87ffcf7
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, 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, 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 if (TREE_CODE (decl) == RECORD_TYPE)
83 mangle_type (decl);
85 /* A copy of the check from the beginning of lhd_set_decl_assembler_name.
86 Only FUNCTION_DECLs and VAR_DECLs for variables with static storage
87 duration need a real DECL_ASSEMBLER_NAME. */
88 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
89 || (TREE_CODE (decl) == VAR_DECL
90 && (TREE_STATIC (decl)
91 || DECL_EXTERNAL (decl)
92 || TREE_PUBLIC (decl))));
94 /* Mangling only applies to class members. */
95 if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
97 init_mangling ();
98 switch (TREE_CODE (decl))
100 case VAR_DECL:
101 if (DECL_LANG_SPECIFIC (decl))
103 if (DECL_CLASS_FIELD_P (decl))
105 mangle_class_field (decl);
106 break;
108 else if (DECL_VTABLE_P (decl))
110 mangle_vtable (DECL_CONTEXT (decl));
111 break;
114 mangle_field_decl (decl);
115 break;
117 case FUNCTION_DECL:
118 if (DECL_LANG_SPECIFIC (decl) && DECL_LOCAL_CNI_METHOD_P (decl))
119 mangle_local_cni_method_decl (decl);
120 else
121 mangle_method_decl (decl);
122 break;
124 default:
125 gcc_unreachable ();
127 SET_DECL_ASSEMBLER_NAME (decl, finish_mangling ());
129 else
130 lhd_set_decl_assembler_name (decl);
133 /* Beginning of the helper functions */
135 static void
136 mangle_class_field (tree decl)
138 tree type = DECL_CONTEXT (decl);
139 mangle_record_type (type, /* for_pointer = */ 0);
140 if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
141 MANGLE_RAW_STRING ("6class$");
142 else
143 MANGLE_RAW_STRING ("7class$$");
144 obstack_1grow (mangle_obstack, 'E');
147 static void
148 mangle_vtable (tree type)
150 MANGLE_RAW_STRING ("TV");
151 mangle_record_type (type, /* for_pointer = */ 0);
152 obstack_1grow (mangle_obstack, 'E');
155 /* This mangles a field decl */
157 static void
158 mangle_field_decl (tree decl)
160 /* Mangle the name of the this the field belongs to */
161 mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
163 /* Mangle the name of the field */
164 mangle_member_name (DECL_NAME (decl));
166 /* Terminate the mangled name */
167 obstack_1grow (mangle_obstack, 'E');
170 /* This mangles a method decl, first mangling its name and then all
171 its arguments. */
173 static void
174 mangle_method_decl (tree mdecl)
176 tree method_name = DECL_NAME (mdecl);
177 tree arglist;
179 /* Mangle the name of the type that contains mdecl */
180 mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
182 /* Mangle the function name. There are two cases:
183 - mdecl is a constructor, use `C1' for its name, (denotes a
184 complete object constructor.)
185 - mdecl is not a constructor, standard mangling is performed.
186 We terminate the mangled function name with a `E'. */
187 if (ID_INIT_P (method_name))
188 obstack_grow (mangle_obstack, "C1", 2);
189 else
190 mangle_member_name (method_name);
191 obstack_1grow (mangle_obstack, 'E');
193 /* We mangled type.methodName. Now onto the arguments. */
194 arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
195 if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
196 arglist = TREE_CHAIN (arglist);
198 /* Output literal 'J' and mangle the return type IF not a
199 constructor. */
200 if (!ID_INIT_P (method_name))
202 obstack_1grow (mangle_obstack, 'J');
203 mangle_type(TREE_TYPE(TREE_TYPE(mdecl)));
206 /* No arguments is easy. We shortcut it. */
207 if (arglist == end_params_node)
208 obstack_1grow (mangle_obstack, 'v');
209 else
211 tree arg;
212 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
213 mangle_type (TREE_VALUE (arg));
217 /* This mangles a CNI method for a local class. If the target supports
218 hidden aliases, then G++ will have generated one for us. It is the
219 responsibility of java_mark_class_local to check target support, since
220 we need to set DECL_VISIBILITY (or not) much earlier. */
222 static void
223 mangle_local_cni_method_decl (tree decl)
225 MANGLE_RAW_STRING ("GA");
226 mangle_method_decl (decl);
229 /* This mangles a member name, like a function name or a field
230 name. Handle cases were `name' is a C++ keyword. Return a nonzero
231 value if unicode encoding was required. */
233 static void
234 mangle_member_name (tree name)
236 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
237 IDENTIFIER_LENGTH (name));
239 /* If NAME happens to be a C++ keyword, add `$'. */
240 if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
241 obstack_1grow (mangle_obstack, '$');
244 /* Append the mangled name of TYPE onto OBSTACK. */
246 static void
247 mangle_type (tree type)
249 switch (TREE_CODE (type))
251 char code;
252 case BOOLEAN_TYPE: code = 'b'; goto primitive;
253 case VOID_TYPE: code = 'v'; goto primitive;
254 case INTEGER_TYPE:
255 if (type == char_type_node || type == promoted_char_type_node)
257 code = 'w';
258 goto primitive;
260 /* Get the original type instead of the arguments promoted type.
261 Avoid symbol name clashes. Should call a function to do that.
262 FIXME. */
263 if (type == promoted_short_type_node)
264 type = short_type_node;
265 if (type == promoted_byte_type_node)
266 type = byte_type_node;
267 switch (TYPE_PRECISION (type))
269 case 8: code = 'c'; goto primitive;
270 case 16: code = 's'; goto primitive;
271 case 32: code = 'i'; goto primitive;
272 case 64: code = 'x'; goto primitive;
273 default: goto bad_type;
275 primitive:
276 obstack_1grow (mangle_obstack, code);
277 break;
279 case REAL_TYPE:
280 switch (TYPE_PRECISION (type))
282 case 32: code = 'f'; goto primitive;
283 case 64: code = 'd'; goto primitive;
284 default: goto bad_type;
286 case POINTER_TYPE:
287 if (TYPE_ARRAY_P (TREE_TYPE (type)))
288 mangle_array_type (type);
289 else
290 mangle_pointer_type (type);
291 break;
292 bad_type:
293 default:
294 gcc_unreachable ();
298 /* The compression table is a vector that keeps track of things we've
299 already seen, so they can be reused. For example, java.lang.Object
300 would generate three entries: two package names and a type. If
301 java.lang.String is presented next, the java.lang will be matched
302 against the first two entries (and kept for compression as S0_), and
303 type String would be added to the table. See mangle_record_type.
304 COMPRESSION_NEXT is the index to the location of the next insertion
305 of an element. */
307 static GTY(()) tree compression_table;
308 static int compression_next;
310 /* Find a POINTER_TYPE in the compression table. Use a special
311 function to match pointer entries and start from the end */
313 static int
314 find_compression_pointer_match (tree type)
316 int i;
318 for (i = compression_next-1; i >= 0; i--)
319 if (entry_match_pointer_p (type, i))
320 return i;
321 return -1;
324 /* Already recorder arrays are handled like pointer as they're always
325 associated with it. */
327 static int
328 find_compression_array_match (tree type)
330 return find_compression_pointer_match (type);
333 /* Match the table of type against STRING. */
335 static int
336 find_compression_array_template_match (tree string)
338 int i;
339 for (i = 0; i < compression_next; i++)
340 if (TREE_VEC_ELT (compression_table, i) == string)
341 return i;
342 return -1;
345 /* We go through the compression table and try to find a complete or
346 partial match. The function returns the compression table entry
347 that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
348 to the rest of TYPE to be mangled. */
350 static int
351 find_compression_record_match (tree type, tree *next_current)
353 int i, match = -1;
354 tree current, saved_current = NULL_TREE;
356 current = TYPE_PACKAGE_LIST (type);
358 for (i = 0; i < compression_next; i++)
360 tree compression_entry = TREE_VEC_ELT (compression_table, i);
361 if (current && compression_entry == TREE_PURPOSE (current))
363 match = i;
364 saved_current = current;
365 current = TREE_CHAIN (current);
367 else
368 /* We don't want to match an element that appears in the middle
369 of a package name, so skip forward to the next complete type name.
370 IDENTIFIER_NODEs (except for a "6JArray") are partial package
371 names while RECORD_TYPEs represent complete type names. */
372 while (i < compression_next
373 && TREE_CODE (compression_entry) == IDENTIFIER_NODE
374 && compression_entry != atms)
375 compression_entry = TREE_VEC_ELT (compression_table, ++i);
378 if (!next_current)
379 return match;
381 /* If we have a match, set next_current to the item next to the last
382 matched value. */
383 if (match >= 0)
384 *next_current = TREE_CHAIN (saved_current);
385 /* We had no match: we'll have to start from the beginning. */
386 if (match < 0)
387 *next_current = TYPE_PACKAGE_LIST (type);
389 return match;
392 /* Mangle a record type. If a nonzero value is returned, it means
393 that a 'N' was emitted (so that a matching 'E' can be emitted if
394 necessary.) FOR_POINTER indicates that this element is for a pointer
395 symbol, meaning it was preceded by a 'P'. */
397 static int
398 mangle_record_type (tree type, int for_pointer)
400 tree current;
401 int match;
402 int nadded_p = 0;
403 int qualified;
405 /* Does this name have a package qualifier? */
406 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
408 #define ADD_N() \
409 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
411 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
413 if (!TYPE_PACKAGE_LIST (type))
414 set_type_package_list (type);
416 match = find_compression_record_match (type, &current);
417 if (match >= 0)
419 /* If we had a pointer, and there's more, we need to emit
420 'N' after 'P' (for_pointer tells us we already emitted it.) */
421 if (for_pointer && current)
422 ADD_N();
423 emit_compression_string (match);
425 while (current)
427 /* Add the new type to the table */
428 compression_table_add (TREE_PURPOSE (current));
429 /* Add 'N' if we never got a chance to, but only if we have a qualified
430 name. For non-pointer elements, the name is always qualified. */
431 if ((qualified || !for_pointer) && !nadded_p)
432 ADD_N();
433 /* Use the bare type name for the mangle. */
434 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
435 IDENTIFIER_LENGTH (TREE_VALUE (current)));
436 current = TREE_CHAIN (current);
438 return nadded_p;
439 #undef ADD_N
442 /* Mangle a pointer type. There are two cases: the pointer is already
443 in the compression table: the compression is emitted sans 'P'
444 indicator. Otherwise, a 'P' is emitted and, depending on the type,
445 a partial compression or/plus the rest of the mangling. */
447 static void
448 mangle_pointer_type (tree type)
450 int match;
451 tree pointer_type;
453 /* Search for the type already in the compression table */
454 if ((match = find_compression_pointer_match (type)) >= 0)
456 emit_compression_string (match);
457 return;
460 /* This didn't work. We start by mangling the pointed-to type */
461 pointer_type = type;
462 type = TREE_TYPE (type);
463 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
465 obstack_1grow (mangle_obstack, 'P');
466 if (mangle_record_type (type, /* for_pointer = */ 1))
467 obstack_1grow (mangle_obstack, 'E');
469 /* Don't forget to insert the pointer type in the table */
470 compression_table_add (pointer_type);
473 /* Mangle an array type. Search for an easy solution first, then go
474 through the process of finding out whether the bare array type or even
475 the template indicator were already used and compressed appropriately.
476 It handles pointers. */
478 static void
479 mangle_array_type (tree p_type)
481 tree type, elt_type;
482 int match;
484 type = TREE_TYPE (p_type);
485 gcc_assert (type);
487 elt_type = TYPE_ARRAY_ELEMENT (type);
489 /* We cache a bit of the Jarray <> mangle. */
490 if (!atms)
492 atms = get_identifier ("6JArray");
495 /* Maybe we have what we're looking for in the compression table. */
496 if ((match = find_compression_array_match (p_type)) >= 0)
498 emit_compression_string (match);
499 return;
502 /* We know for a fact that all arrays are pointers */
503 obstack_1grow (mangle_obstack, 'P');
504 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
505 if ((match = find_compression_record_match (type, NULL)) > 0)
507 emit_compression_string (match);
508 return;
511 /* Maybe we already have just JArray somewhere */
512 if ((match = find_compression_array_template_match (atms)) > 0)
513 emit_compression_string (match);
514 else
516 /* Start the template mangled name */
517 obstack_grow (mangle_obstack,
518 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
519 /* Insert in the compression table */
520 compression_table_add (atms);
523 /* Mangle Jarray <elt_type> */
524 obstack_1grow (mangle_obstack, 'I');
525 mangle_type (elt_type);
526 obstack_1grow (mangle_obstack, 'E');
528 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
529 compression_table_add (type);
530 compression_table_add (p_type);
533 /* Write a substitution string for entry I. Substitution string starts a
534 -1 (encoded S_.) The base is 36, and the code shamelessly taken from
535 cp/mangle.c. */
537 static void
538 emit_compression_string (int i)
540 i -= 1; /* Adjust */
541 obstack_1grow (mangle_obstack, 'S');
542 if (i >= 0)
544 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
545 unsigned HOST_WIDE_INT n;
546 unsigned HOST_WIDE_INT m=1;
547 /* How many digits for I in base 36? */
548 for (n = i; n >= 36; n /= 36, m *=36);
549 /* Write the digits out */
550 while (m > 0)
552 int digit = i / m;
553 obstack_1grow (mangle_obstack, digits [digit]);
554 i -= digit * m;
555 m /= 36;
558 obstack_1grow (mangle_obstack, '_');
561 /* If search the compression table at index I for a pointer type
562 equivalent to TYPE (meaning that after all the indirection, which
563 might all be unique, we find the same RECORD_TYPE.) */
565 static int
566 entry_match_pointer_p (tree type, int i)
568 tree t = TREE_VEC_ELT (compression_table, i);
570 while (TREE_CODE (type) == POINTER_TYPE
571 && TREE_CODE (t) == POINTER_TYPE)
573 t = TREE_TYPE (t);
574 type = TREE_TYPE (type);
576 return (TREE_CODE (type) == RECORD_TYPE
577 && TREE_CODE (t) == RECORD_TYPE
578 && t == type);
581 /* Go through all qualification of type and build a list of list node
582 elements containings as a purpose what should be used for a match and
583 inserted in the compression table; and as it value the raw name of the
584 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
586 static void
587 set_type_package_list (tree type)
589 int i;
590 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
591 char *ptr;
592 int qualifications;
593 tree list = NULL_TREE, elt;
595 for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
596 if (*ptr == '.')
597 qualifications += 1;
599 for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
601 if (ptr [0] == '.')
603 char c;
604 tree identifier;
606 /* Can't use an obstack, we're already using it to
607 accumulate the mangling. */
608 c = ptr [0];
609 ptr [0] = '\0';
610 identifier = get_identifier (type_string);
611 ptr [0] = c;
612 elt = build_tree_list (identifier, identifier);
613 TREE_CHAIN (elt) = list;
614 list = elt;
615 type_string = ptr+1;
616 i += 1;
620 elt = build_tree_list (type, get_identifier (type_string));
621 TREE_CHAIN (elt) = list;
622 list = elt;
623 TYPE_PACKAGE_LIST (type) = nreverse (list);
626 /* Add TYPE as the last element of the compression table. Resize the
627 compression table if necessary. */
629 static void
630 compression_table_add (tree type)
632 if (compression_next == TREE_VEC_LENGTH (compression_table))
634 tree new = make_tree_vec (2*compression_next);
635 int i;
637 for (i = 0; i < compression_next; i++)
638 TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
640 compression_table = new;
642 TREE_VEC_ELT (compression_table, compression_next++) = type;
645 /* Mangling initialization routine. */
647 static void
648 init_mangling (void)
650 if (!mangle_obstack)
652 mangle_obstack = &mangle_obstack_1;
653 gcc_obstack_init (mangle_obstack);
656 gcc_assert (compression_table == NULL);
657 compression_table = make_tree_vec (10);
659 /* Mangled name are to be suffixed */
660 MANGLE_RAW_STRING ("_Z");
663 /* Mangling finalization routine. The mangled name is returned as a
664 IDENTIFIER_NODE. */
666 static tree
667 finish_mangling (void)
669 tree result;
671 gcc_assert (compression_table);
673 compression_table = NULL_TREE;
674 compression_next = 0;
675 obstack_1grow (mangle_obstack, '\0');
676 result = get_identifier (obstack_base (mangle_obstack));
677 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
679 return result;
682 #include "gt-java-mangle.h"