1 /* Functions related to mangling class names for the GNU compiler
2 for the Java(TM) language.
3 Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
22 Java and all Java-based marks are trademarks or registered trademarks
23 of Sun Microsystems, Inc. in the United States and other countries.
24 The Free Software Foundation is independent of Sun Microsystems, Inc. */
26 /* Written by Per Bothner <bothner@cygnus.com> */
32 #include "java-tree.h"
38 static void mangle_field_decl PARAMS ((tree));
39 static void mangle_method_decl PARAMS ((tree));
41 static void mangle_type PARAMS ((tree));
42 static void mangle_pointer_type PARAMS ((tree));
43 static void mangle_array_type PARAMS ((tree));
44 static int mangle_record_type PARAMS ((tree, int));
46 static int find_compression_pointer_match PARAMS ((tree));
47 static int find_compression_array_match PARAMS ((tree));
48 static int find_compression_record_match PARAMS ((tree, tree *));
49 static int find_compression_array_template_match PARAMS ((tree));
51 static void set_type_package_list PARAMS ((tree));
52 static int entry_match_pointer_p PARAMS ((tree, int));
53 static void emit_compression_string PARAMS ((int));
55 static void init_mangling PARAMS ((struct obstack *));
56 static tree finish_mangling PARAMS ((void));
57 static void compression_table_add PARAMS ((tree));
59 static void append_unicode_mangled_name PARAMS ((const char *, int));
60 static void append_gpp_mangled_name PARAMS ((const char *, int));
61 static int unicode_mangling_length PARAMS ((const char *, int));
62 static int mangle_member_name PARAMS ((tree));
64 /* We use an incoming obstack, always to be provided to the interface
66 struct obstack *mangle_obstack;
67 #define MANGLE_RAW_STRING(S) \
68 obstack_grow (mangle_obstack, (S), sizeof (S)-1)
70 /* This is the mangling interface: a decl, a class field (.class) and
74 java_mangle_decl (obstack, decl)
75 struct obstack *obstack;
78 init_mangling (obstack);
79 switch (TREE_CODE (decl))
82 mangle_field_decl (decl);
85 mangle_method_decl (decl);
88 internal_error ("Can't mangle %s", tree_code_name [TREE_CODE (decl)]);
90 return finish_mangling ();
94 java_mangle_class_field (obstack, type)
95 struct obstack *obstack;
98 init_mangling (obstack);
99 mangle_record_type (type, /* from_pointer = */ 0);
100 MANGLE_RAW_STRING ("6class$");
101 obstack_1grow (mangle_obstack, 'E');
102 return finish_mangling ();
106 java_mangle_vtable (obstack, type)
107 struct obstack *obstack;
110 init_mangling (obstack);
111 MANGLE_RAW_STRING ("TV");
112 mangle_record_type (type, /* from_pointer = */ 0);
113 obstack_1grow (mangle_obstack, 'E');
114 return finish_mangling ();
117 /* Beginning of the helper functions */
119 /* This mangles a field decl */
122 mangle_field_decl (decl)
125 tree name = DECL_NAME (decl);
126 int field_name_needs_escapes = 0;
128 /* Mangle the name of the this the field belongs to */
129 mangle_record_type (DECL_CONTEXT (decl), /* from_pointer = */ 0);
131 /* Mangle the name of the field */
132 field_name_needs_escapes = mangle_member_name (name);
134 /* Terminate the mangled name */
135 obstack_1grow (mangle_obstack, 'E');
136 if (field_name_needs_escapes)
137 obstack_1grow (mangle_obstack, 'U');
140 /* This mangles a method decl, first mangling its name and then all
144 mangle_method_decl (mdecl)
147 tree method_name = DECL_NAME (mdecl);
149 int method_name_needs_escapes = 0;
151 /* Mangle the name of the type that contains mdecl */
152 mangle_record_type (DECL_CONTEXT (mdecl), /* from_pointer = */ 0);
154 /* Mangle the function name. There three cases
155 - mdecl is java.lang.Object.Object(), use `C2' for its name
156 (denotes a base object constructor.)
157 - mdecl is a constructor, use `C1' for its name, (denotes a
158 complete object constructor.)
159 - mdecl is not a constructor, standard mangling is performed.
160 We terminate the mangled function name with a `E'. */
161 if (ID_INIT_P (method_name))
163 if (DECL_CONTEXT (mdecl) == object_type_node)
164 obstack_grow (mangle_obstack, "C2", 2);
166 obstack_grow (mangle_obstack, "C1", 2);
169 method_name_needs_escapes = mangle_member_name (method_name);
170 obstack_1grow (mangle_obstack, 'E');
172 /* We mangled type.methodName. Now onto the arguments. */
173 arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
174 if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
175 arglist = TREE_CHAIN (arglist);
177 /* No arguments is easy. We shortcut it. */
178 if (arglist == end_params_node)
179 obstack_1grow (mangle_obstack, 'v');
183 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
184 mangle_type (TREE_VALUE (arg));
187 /* Terminate the mangled name */
188 if (method_name_needs_escapes)
189 obstack_1grow (mangle_obstack, 'U');
192 /* This mangles a member name, like a function name or a field
193 name. Handle cases were `name' is a C++ keyword. Return a non zero
194 value if unicode encoding was required. */
197 mangle_member_name (name)
200 const char * name_string = IDENTIFIER_POINTER (name);
201 int len = IDENTIFIER_LENGTH (name);
204 if (unicode_mangling_length (name_string, len) > 0)
206 append_unicode_mangled_name (name_string, len);
210 append_gpp_mangled_name (name_string, len);
212 /* If NAME happens to be a C++ keyword, add `$' or `.' or `_'. */
213 if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
215 #ifndef NO_DOLLAR_IN_LABEL
216 obstack_1grow (mangle_obstack, '$');
217 #else /* NO_DOLLAR_IN_LABEL */
218 #ifndef NO_DOT_IN_LABEL
219 obstack_1grow (mangle_obstack, '.');
220 #else /* NO_DOT_IN_LABEL */
221 obstack_1grow (mangle_obstack, '_');
222 #endif /* NO_DOT_IN_LABEL */
223 #endif /* NO_DOLLAR_IN_LABEL */
229 /* Assuming (NAME, LEN) is a Utf8-encoding string, calculate
230 the length of the string as mangled (a la g++) including Unicode escapes.
231 If no escapes are needed, return 0. */
234 unicode_mangling_length (name, len)
238 const unsigned char *ptr;
239 const unsigned char *limit = (const unsigned char *)name + len;
240 int need_escapes = 0;
243 for (ptr = (const unsigned char *) name; ptr < limit; )
245 int ch = UTF8_GET(ptr, limit);
247 error ("internal error - invalid Utf8 name");
248 if (ch >= '0' && ch <= '9')
249 need_escapes += num_chars == 0;
252 else if (ch != '$' && (ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z'))
257 return num_chars + 4 * (need_escapes + underscores);
262 /* Assuming (NAME, LEN) is a Utf8-encoding string, emit the string
263 appropriately mangled (with Unicode escapes) to OBSTACK. */
266 append_unicode_mangled_name (name, len)
270 const unsigned char *ptr;
271 const unsigned char *limit = (const unsigned char *)name + len;
272 for (ptr = (const unsigned char *) name; ptr < limit; )
274 int ch = UTF8_GET(ptr, limit);
278 error ("internal error - bad Utf8 string");
281 if (ch >= '0' && ch <= '9')
282 emit_escape = (ptr == (const unsigned char *) name);
284 emit_escape = (ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z');
288 sprintf (buf, "_%04x", ch);
289 obstack_grow (mangle_obstack, buf, 5);
293 obstack_1grow (mangle_obstack, ch);
298 /* Assuming (NAME, LEN) is a Utf8-encoding string, emit the string
299 appropriately mangled (with Unicode escapes if needed) to OBSTACK. */
302 append_gpp_mangled_name (name, len)
306 int encoded_len = unicode_mangling_length (name, len);
307 int needs_escapes = encoded_len > 0;
311 sprintf (buf, "U%d", encoded_len);
312 obstack_grow (mangle_obstack, buf, strlen(buf));
313 append_unicode_mangled_name (name, len);
317 sprintf (buf, "%d", len);
318 obstack_grow (mangle_obstack, buf, strlen(buf));
319 obstack_grow (mangle_obstack, name, len);
323 /* Append the mangled name of TYPE onto OBSTACK. */
329 switch (TREE_CODE (type))
332 case BOOLEAN_TYPE: code = 'b'; goto primitive;
333 case CHAR_TYPE: code = 'w'; goto primitive;
334 case VOID_TYPE: code = 'v'; goto primitive;
336 /* Get the original type instead of the arguments promoted type.
337 Avoid symbol name clashes. Should call a function to do that.
339 if (type == promoted_short_type_node)
340 type = short_type_node;
341 if (type == promoted_byte_type_node)
342 type = byte_type_node;
343 switch (TYPE_PRECISION (type))
345 case 8: code = 'c'; goto primitive;
346 case 16: code = 's'; goto primitive;
347 case 32: code = 'i'; goto primitive;
348 case 64: code = 'x'; goto primitive;
349 default: goto bad_type;
352 obstack_1grow (mangle_obstack, code);
356 switch (TYPE_PRECISION (type))
358 case 32: code = 'f'; goto primitive;
359 case 64: code = 'd'; goto primitive;
360 default: goto bad_type;
363 if (TYPE_ARRAY_P (TREE_TYPE (type)))
364 mangle_array_type (type);
366 mangle_pointer_type (type);
374 /* The compression table is a vector that keeps track of things we've
375 already seen, so they can be reused. For example, java.lang.Object
376 Would generate three entries: two package names and a type. If
377 java.lang.String is presented next, the java.lang will be matched
378 against the first two entries (and kept for compression as S_0), and
379 type String would be added to the table. See mangle_record_type.
380 COMPRESSION_NEXT is the index to the location of the next insertion
383 static tree compression_table;
384 static int compression_next;
386 /* Find a POINTER_TYPE in the compression table. Use a special
387 function to match pointer entries and start from the end */
390 find_compression_pointer_match (type)
395 for (i = compression_next-1; i >= 0; i--)
396 if (entry_match_pointer_p (type, i))
401 /* Already recorder arrays are handled like pointer as they're always
402 associated with it. */
405 find_compression_array_match (type)
408 return find_compression_pointer_match (type);
411 /* Match the table of type against STRING. */
414 find_compression_array_template_match (string)
418 for (i = 0; i < compression_next; i++)
419 if (TREE_VEC_ELT (compression_table, i) == string)
424 /* We go through the compression table and try to find a complete or
425 partial match. The function returns the compression table entry
426 that (evenutally partially) matches TYPE. *NEXT_CURRENT can be set
427 to the rest of TYPE to be mangled. */
430 find_compression_record_match (type, next_current)
435 tree current, saved_current;
437 /* Search from the beginning for something that matches TYPE, even
439 for (current = TYPE_PACKAGE_LIST (type), i = 0, match = -1; current;
440 current = TREE_CHAIN (current))
443 for (j = i; j < compression_next; j++)
444 if (TREE_VEC_ELT (compression_table, j) == TREE_PURPOSE (current))
447 saved_current = current;
455 /* If we have a match, set next_current to the item next to the last
458 *next_current = TREE_CHAIN (saved_current);
459 /* We had no match: we'll have to start from the beginning. */
461 *next_current = TYPE_PACKAGE_LIST (type);
466 /* Mangle a record type. If a non zero value is returned, it means
467 that a 'N' was emitted (so that a matching 'E' can be emitted if
471 mangle_record_type (type, from_pointer)
480 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
482 if (TREE_CODE (type) != RECORD_TYPE)
485 if (!TYPE_PACKAGE_LIST (type))
486 set_type_package_list (type);
488 match = find_compression_record_match (type, ¤t);
491 /* If we had a pointer, and there's more, we need to emit
492 'N' after 'P' (from pointer tells us we already emitted it.) */
493 if (from_pointer && current)
495 emit_compression_string (match);
499 /* Add the new type to the table */
500 compression_table_add (TREE_PURPOSE (current));
501 /* Add 'N' if we never got a chance to. */
504 /* Use the bare type name for the mangle. */
505 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
506 IDENTIFIER_LENGTH (TREE_VALUE (current)));
507 current = TREE_CHAIN (current);
513 /* Mangle a pointer type. There are two cases: the pointer is already
514 in the compression table: the compression is emited sans 'P'
515 indicator. Otherwise, a 'P' is emitted and, depending on the type,
516 a partial compression or/plus the rest of the mangling. */
519 mangle_pointer_type (type)
525 /* Search for the type already in the compression table */
526 if ((match = find_compression_pointer_match (type)) >= 0)
528 emit_compression_string (match);
532 /* This didn't work. We start by mangling the pointed-to type */
534 type = TREE_TYPE (type);
535 if (TREE_CODE (type) != RECORD_TYPE)
538 obstack_1grow (mangle_obstack, 'P');
539 if (mangle_record_type (type, /* for_pointer = */ 1))
540 obstack_1grow (mangle_obstack, 'E');
542 /* Don't forget to insert the pointer type in the table */
543 compression_table_add (pointer_type);
546 /* Mangle an array type. Search for an easy solution first, then go
547 through the process of finding out whether the bare array type or even
548 the template indicator where already used an compress appropriately.
549 It handles pointers. */
552 mangle_array_type (p_type)
555 /* atms: array template mangled string. */
556 static tree atms = NULL_TREE;
560 type = TREE_TYPE (p_type);
564 elt_type = TYPE_ARRAY_ELEMENT (type);
566 /* We cache a bit of the Jarray <> mangle. */
569 atms = get_identifier ("6JArray");
570 ggc_add_tree_root (&atms, 1);
573 /* Maybe we have what we're looking in the compression table. */
574 if ((match = find_compression_array_match (p_type)) >= 0)
576 emit_compression_string (match);
580 /* We know for a fact that all arrays are pointers */
581 obstack_1grow (mangle_obstack, 'P');
582 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
583 if ((match = find_compression_record_match (type, NULL)) > 0)
585 emit_compression_string (match);
589 /* Maybe we already have just JArray somewhere */
590 if ((match = find_compression_array_template_match (atms)) > 0)
591 emit_compression_string (match);
594 /* Start the template mangled name */
595 obstack_grow (mangle_obstack,
596 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
597 /* Insert in the compression table */
598 compression_table_add (atms);
601 /* Mangle Jarray <elt_type> */
602 obstack_1grow (mangle_obstack, 'I');
603 mangle_type (elt_type);
604 obstack_1grow (mangle_obstack, 'E');
606 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
607 compression_table_add (type);
608 compression_table_add (p_type);
611 /* Write a substition string for entry I. Substitution string starts a
612 -1 (encoded S_.) The base is 36, and the code shamlessly taken from
616 emit_compression_string (int i)
619 obstack_1grow (mangle_obstack, 'S');
622 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
623 unsigned HOST_WIDE_INT n;
624 unsigned HOST_WIDE_INT m=1;
625 /* How many digits for I in base 36? */
626 for (n = i; n >= 36; n /= 36, m *=36);
627 /* Write the digits out */
631 obstack_1grow (mangle_obstack, digits [digit]);
636 obstack_1grow (mangle_obstack, '_');
639 /* If search the compression table at index I for a pointer type
640 equivalent to TYPE (meaning that after all the indirection, which
641 might all be unique, we find the same RECORD_TYPE.) */
644 entry_match_pointer_p (type, i)
648 tree t = TREE_VEC_ELT (compression_table, i);
650 while (TREE_CODE (type) == POINTER_TYPE
651 && TREE_CODE (t) == POINTER_TYPE)
654 type = TREE_TYPE (type);
656 return (TREE_CODE (type) == RECORD_TYPE
657 && TREE_CODE (t) == RECORD_TYPE
661 /* Go through all qualification of type and build a list of list node
662 elements containings as a purpose what should be used for a match and
663 inserted in the compression table; and as it value the raw name of the
664 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
667 set_type_package_list (type)
671 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
674 tree list = NULL_TREE, elt;
676 for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
680 for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
687 /* Can't use an obstack, we're already using it to
688 accumulate the mangling. */
691 identifier = get_identifier (type_string);
693 elt = build_tree_list (identifier, identifier);
694 TREE_CHAIN (elt) = list;
701 elt = build_tree_list (type, get_identifier (type_string));
702 TREE_CHAIN (elt) = list;
704 TYPE_PACKAGE_LIST (type) = nreverse (list);
707 /* Add TYPE as the last element of the compression table. Resize the
708 compression table if necessary. */
711 compression_table_add (type)
714 if (compression_next == TREE_VEC_LENGTH (compression_table))
716 tree new = make_tree_vec (2*compression_next);
719 for (i = 0; i < compression_next; i++)
720 TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
722 ggc_del_root (&compression_table);
723 compression_table = new;
724 ggc_add_tree_root (&compression_table, 1);
726 TREE_VEC_ELT (compression_table, compression_next++) = type;
729 /* Mangling initialization routine. */
732 init_mangling (obstack)
733 struct obstack *obstack;
735 mangle_obstack = obstack;
736 if (!compression_table)
737 compression_table = make_tree_vec (10);
739 /* Mangling already in progress. */
742 /* Mangled name are to be suffixed */
743 obstack_grow (mangle_obstack, "_Z", 2);
745 /* Register the compression table with the GC */
746 ggc_add_tree_root (&compression_table, 1);
749 /* Mangling finalization routine. The mangled name is returned as a
757 if (!compression_table)
758 /* Mangling already finished. */
761 ggc_del_root (&compression_table);
762 compression_table = NULL_TREE;
763 compression_next = 0;
764 obstack_1grow (mangle_obstack, '\0');
765 result = get_identifier (obstack_base (mangle_obstack));
766 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
768 printf ("// %s\n", IDENTIFIER_POINTER (result));