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