toplev.c (floor_log2, exact_log2): Don't define if __cplusplus.
[official-gcc.git] / gcc / java / mangle.c
blob372c9466c63c44ecc95f37ab57db3fe161b126e2
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 /* 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 /* Output literal 'J' and mangle the return type IF not a
192 constructor. */
193 if (!ID_INIT_P (method_name))
195 obstack_1grow (mangle_obstack, 'J');
196 mangle_type(TREE_TYPE(TREE_TYPE(mdecl)));
199 /* No arguments is easy. We shortcut it. */
200 if (arglist == end_params_node)
201 obstack_1grow (mangle_obstack, 'v');
202 else
204 tree arg;
205 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
206 mangle_type (TREE_VALUE (arg));
210 /* This mangles a CNI method for a local class. If the target supports
211 hidden aliases, then G++ will have generated one for us. It is the
212 responsibility of java_mark_class_local to check target support, since
213 we need to set DECL_VISIBILITY (or not) much earlier. */
215 static void
216 mangle_local_cni_method_decl (tree decl)
218 MANGLE_RAW_STRING ("GA");
219 mangle_method_decl (decl);
222 /* This mangles a member name, like a function name or a field
223 name. Handle cases were `name' is a C++ keyword. Return a nonzero
224 value if unicode encoding was required. */
226 static void
227 mangle_member_name (tree name)
229 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
230 IDENTIFIER_LENGTH (name));
232 /* If NAME happens to be a C++ keyword, add `$'. */
233 if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
234 obstack_1grow (mangle_obstack, '$');
237 /* Append the mangled name of TYPE onto OBSTACK. */
239 static void
240 mangle_type (tree type)
242 switch (TREE_CODE (type))
244 char code;
245 case BOOLEAN_TYPE: code = 'b'; goto primitive;
246 case CHAR_TYPE: code = 'w'; goto primitive;
247 case VOID_TYPE: code = 'v'; goto primitive;
248 case INTEGER_TYPE:
249 /* Get the original type instead of the arguments promoted type.
250 Avoid symbol name clashes. Should call a function to do that.
251 FIXME. */
252 if (type == promoted_short_type_node)
253 type = short_type_node;
254 if (type == promoted_byte_type_node)
255 type = byte_type_node;
256 switch (TYPE_PRECISION (type))
258 case 8: code = 'c'; goto primitive;
259 case 16: code = 's'; goto primitive;
260 case 32: code = 'i'; goto primitive;
261 case 64: code = 'x'; goto primitive;
262 default: goto bad_type;
264 primitive:
265 obstack_1grow (mangle_obstack, code);
266 break;
268 case REAL_TYPE:
269 switch (TYPE_PRECISION (type))
271 case 32: code = 'f'; goto primitive;
272 case 64: code = 'd'; goto primitive;
273 default: goto bad_type;
275 case POINTER_TYPE:
276 if (TYPE_ARRAY_P (TREE_TYPE (type)))
277 mangle_array_type (type);
278 else
279 mangle_pointer_type (type);
280 break;
281 bad_type:
282 default:
283 abort ();
287 /* The compression table is a vector that keeps track of things we've
288 already seen, so they can be reused. For example, java.lang.Object
289 would generate three entries: two package names and a type. If
290 java.lang.String is presented next, the java.lang will be matched
291 against the first two entries (and kept for compression as S0_), and
292 type String would be added to the table. See mangle_record_type.
293 COMPRESSION_NEXT is the index to the location of the next insertion
294 of an element. */
296 static GTY(()) tree compression_table;
297 static int compression_next;
299 /* Find a POINTER_TYPE in the compression table. Use a special
300 function to match pointer entries and start from the end */
302 static int
303 find_compression_pointer_match (tree type)
305 int i;
307 for (i = compression_next-1; i >= 0; i--)
308 if (entry_match_pointer_p (type, i))
309 return i;
310 return -1;
313 /* Already recorder arrays are handled like pointer as they're always
314 associated with it. */
316 static int
317 find_compression_array_match (tree type)
319 return find_compression_pointer_match (type);
322 /* Match the table of type against STRING. */
324 static int
325 find_compression_array_template_match (tree string)
327 int i;
328 for (i = 0; i < compression_next; i++)
329 if (TREE_VEC_ELT (compression_table, i) == string)
330 return i;
331 return -1;
334 /* We go through the compression table and try to find a complete or
335 partial match. The function returns the compression table entry
336 that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
337 to the rest of TYPE to be mangled. */
339 static int
340 find_compression_record_match (tree type, tree *next_current)
342 int i, match = -1;
343 tree current, saved_current = NULL_TREE;
345 current = TYPE_PACKAGE_LIST (type);
347 for (i = 0; i < compression_next; i++)
349 tree compression_entry = TREE_VEC_ELT (compression_table, i);
350 if (current && compression_entry == TREE_PURPOSE (current))
352 match = i;
353 saved_current = current;
354 current = TREE_CHAIN (current);
356 else
357 /* We don't want to match an element that appears in the middle
358 of a package name, so skip forward to the next complete type name.
359 IDENTIFIER_NODEs (except for a "6JArray") are partial package
360 names while RECORD_TYPEs represent complete type names. */
361 while (i < compression_next
362 && TREE_CODE (compression_entry) == IDENTIFIER_NODE
363 && compression_entry != atms)
364 compression_entry = TREE_VEC_ELT (compression_table, ++i);
367 if (!next_current)
368 return match;
370 /* If we have a match, set next_current to the item next to the last
371 matched value. */
372 if (match >= 0)
373 *next_current = TREE_CHAIN (saved_current);
374 /* We had no match: we'll have to start from the beginning. */
375 if (match < 0)
376 *next_current = TYPE_PACKAGE_LIST (type);
378 return match;
381 /* Mangle a record type. If a nonzero value is returned, it means
382 that a 'N' was emitted (so that a matching 'E' can be emitted if
383 necessary.) FOR_POINTER indicates that this element is for a pointer
384 symbol, meaning it was preceded by a 'P'. */
386 static int
387 mangle_record_type (tree type, int for_pointer)
389 tree current;
390 int match;
391 int nadded_p = 0;
392 int qualified;
394 /* Does this name have a package qualifier? */
395 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
397 #define ADD_N() \
398 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
400 if (TREE_CODE (type) != RECORD_TYPE)
401 abort ();
403 if (!TYPE_PACKAGE_LIST (type))
404 set_type_package_list (type);
406 match = find_compression_record_match (type, &current);
407 if (match >= 0)
409 /* If we had a pointer, and there's more, we need to emit
410 'N' after 'P' (for_pointer tells us we already emitted it.) */
411 if (for_pointer && current)
412 ADD_N();
413 emit_compression_string (match);
415 while (current)
417 /* Add the new type to the table */
418 compression_table_add (TREE_PURPOSE (current));
419 /* Add 'N' if we never got a chance to, but only if we have a qualified
420 name. For non-pointer elements, the name is always qualified. */
421 if ((qualified || !for_pointer) && !nadded_p)
422 ADD_N();
423 /* Use the bare type name for the mangle. */
424 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
425 IDENTIFIER_LENGTH (TREE_VALUE (current)));
426 current = TREE_CHAIN (current);
428 return nadded_p;
429 #undef ADD_N
432 /* Mangle a pointer type. There are two cases: the pointer is already
433 in the compression table: the compression is emitted sans 'P'
434 indicator. Otherwise, a 'P' is emitted and, depending on the type,
435 a partial compression or/plus the rest of the mangling. */
437 static void
438 mangle_pointer_type (tree type)
440 int match;
441 tree pointer_type;
443 /* Search for the type already in the compression table */
444 if ((match = find_compression_pointer_match (type)) >= 0)
446 emit_compression_string (match);
447 return;
450 /* This didn't work. We start by mangling the pointed-to type */
451 pointer_type = type;
452 type = TREE_TYPE (type);
453 if (TREE_CODE (type) != RECORD_TYPE)
454 abort ();
456 obstack_1grow (mangle_obstack, 'P');
457 if (mangle_record_type (type, /* for_pointer = */ 1))
458 obstack_1grow (mangle_obstack, 'E');
460 /* Don't forget to insert the pointer type in the table */
461 compression_table_add (pointer_type);
464 /* Mangle an array type. Search for an easy solution first, then go
465 through the process of finding out whether the bare array type or even
466 the template indicator were already used and compressed appropriately.
467 It handles pointers. */
469 static void
470 mangle_array_type (tree p_type)
472 tree type, elt_type;
473 int match;
475 type = TREE_TYPE (p_type);
476 if (!type)
477 abort ();
479 elt_type = TYPE_ARRAY_ELEMENT (type);
481 /* We cache a bit of the Jarray <> mangle. */
482 if (!atms)
484 atms = get_identifier ("6JArray");
487 /* Maybe we have what we're looking for in the compression table. */
488 if ((match = find_compression_array_match (p_type)) >= 0)
490 emit_compression_string (match);
491 return;
494 /* We know for a fact that all arrays are pointers */
495 obstack_1grow (mangle_obstack, 'P');
496 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
497 if ((match = find_compression_record_match (type, NULL)) > 0)
499 emit_compression_string (match);
500 return;
503 /* Maybe we already have just JArray somewhere */
504 if ((match = find_compression_array_template_match (atms)) > 0)
505 emit_compression_string (match);
506 else
508 /* Start the template mangled name */
509 obstack_grow (mangle_obstack,
510 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
511 /* Insert in the compression table */
512 compression_table_add (atms);
515 /* Mangle Jarray <elt_type> */
516 obstack_1grow (mangle_obstack, 'I');
517 mangle_type (elt_type);
518 obstack_1grow (mangle_obstack, 'E');
520 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
521 compression_table_add (type);
522 compression_table_add (p_type);
525 /* Write a substitution string for entry I. Substitution string starts a
526 -1 (encoded S_.) The base is 36, and the code shamelessly taken from
527 cp/mangle.c. */
529 static void
530 emit_compression_string (int i)
532 i -= 1; /* Adjust */
533 obstack_1grow (mangle_obstack, 'S');
534 if (i >= 0)
536 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
537 unsigned HOST_WIDE_INT n;
538 unsigned HOST_WIDE_INT m=1;
539 /* How many digits for I in base 36? */
540 for (n = i; n >= 36; n /= 36, m *=36);
541 /* Write the digits out */
542 while (m > 0)
544 int digit = i / m;
545 obstack_1grow (mangle_obstack, digits [digit]);
546 i -= digit * m;
547 m /= 36;
550 obstack_1grow (mangle_obstack, '_');
553 /* If search the compression table at index I for a pointer type
554 equivalent to TYPE (meaning that after all the indirection, which
555 might all be unique, we find the same RECORD_TYPE.) */
557 static int
558 entry_match_pointer_p (tree type, int i)
560 tree t = TREE_VEC_ELT (compression_table, i);
562 while (TREE_CODE (type) == POINTER_TYPE
563 && TREE_CODE (t) == POINTER_TYPE)
565 t = TREE_TYPE (t);
566 type = TREE_TYPE (type);
568 return (TREE_CODE (type) == RECORD_TYPE
569 && TREE_CODE (t) == RECORD_TYPE
570 && t == type);
573 /* Go through all qualification of type and build a list of list node
574 elements containings as a purpose what should be used for a match and
575 inserted in the compression table; and as it value the raw name of the
576 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
578 static void
579 set_type_package_list (tree type)
581 int i;
582 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
583 char *ptr;
584 int qualifications;
585 tree list = NULL_TREE, elt;
587 for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
588 if (*ptr == '.')
589 qualifications += 1;
591 for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
593 if (ptr [0] == '.')
595 char c;
596 tree identifier;
598 /* Can't use an obstack, we're already using it to
599 accumulate the mangling. */
600 c = ptr [0];
601 ptr [0] = '\0';
602 identifier = get_identifier (type_string);
603 ptr [0] = c;
604 elt = build_tree_list (identifier, identifier);
605 TREE_CHAIN (elt) = list;
606 list = elt;
607 type_string = ptr+1;
608 i += 1;
612 elt = build_tree_list (type, get_identifier (type_string));
613 TREE_CHAIN (elt) = list;
614 list = elt;
615 TYPE_PACKAGE_LIST (type) = nreverse (list);
618 /* Add TYPE as the last element of the compression table. Resize the
619 compression table if necessary. */
621 static void
622 compression_table_add (tree type)
624 if (compression_next == TREE_VEC_LENGTH (compression_table))
626 tree new = make_tree_vec (2*compression_next);
627 int i;
629 for (i = 0; i < compression_next; i++)
630 TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
632 compression_table = new;
634 TREE_VEC_ELT (compression_table, compression_next++) = type;
637 /* Mangling initialization routine. */
639 static void
640 init_mangling (void)
642 if (!mangle_obstack)
644 mangle_obstack = &mangle_obstack_1;
645 gcc_obstack_init (mangle_obstack);
648 gcc_assert (compression_table == NULL);
649 compression_table = make_tree_vec (10);
651 /* Mangled name are to be suffixed */
652 MANGLE_RAW_STRING ("_Z");
655 /* Mangling finalization routine. The mangled name is returned as a
656 IDENTIFIER_NODE. */
658 static tree
659 finish_mangling (void)
661 tree result;
663 gcc_assert (compression_table);
665 compression_table = NULL_TREE;
666 compression_next = 0;
667 obstack_1grow (mangle_obstack, '\0');
668 result = get_identifier (obstack_base (mangle_obstack));
669 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
671 return result;
674 #include "gt-java-mangle.h"