FSF GCC merge 02/23/03
[official-gcc.git] / gcc / java / mangle.c
blobca5997cba7488bfb871d9edf2d6c2f68a0a49328
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 /* This is the mangling interface: a decl, a class field (.class) and
71 the vtable. */
73 tree
74 java_mangle_decl (struct obstack *obstack, tree decl)
76 init_mangling (obstack);
77 switch (TREE_CODE (decl))
79 case VAR_DECL:
80 mangle_field_decl (decl);
81 break;
82 case FUNCTION_DECL:
83 mangle_method_decl (decl);
84 break;
85 default:
86 internal_error ("can't mangle %s", tree_code_name [TREE_CODE (decl)]);
88 return finish_mangling ();
91 tree
92 java_mangle_class_field (struct obstack *obstack, tree type)
94 init_mangling (obstack);
95 mangle_record_type (type, /* for_pointer = */ 0);
96 MANGLE_RAW_STRING ("6class$");
97 obstack_1grow (mangle_obstack, 'E');
98 return finish_mangling ();
101 tree
102 java_mangle_vtable (struct obstack *obstack, tree type)
104 init_mangling (obstack);
105 MANGLE_RAW_STRING ("TV");
106 mangle_record_type (type, /* for_pointer = */ 0);
107 obstack_1grow (mangle_obstack, 'E');
108 return finish_mangling ();
111 /* Beginning of the helper functions */
113 /* This mangles a field decl */
115 static void
116 mangle_field_decl (tree decl)
118 /* Mangle the name of the this the field belongs to */
119 mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
121 /* Mangle the name of the field */
122 mangle_member_name (DECL_NAME (decl));
124 /* Terminate the mangled name */
125 obstack_1grow (mangle_obstack, 'E');
128 /* This mangles a method decl, first mangling its name and then all
129 its arguments. */
131 static void
132 mangle_method_decl (tree mdecl)
134 tree method_name = DECL_NAME (mdecl);
135 tree arglist;
137 /* Mangle the name of the type that contains mdecl */
138 mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
140 /* Mangle the function name. There are two cases:
141 - mdecl is a constructor, use `C1' for its name, (denotes a
142 complete object constructor.)
143 - mdecl is not a constructor, standard mangling is performed.
144 We terminate the mangled function name with a `E'. */
145 if (ID_INIT_P (method_name))
146 obstack_grow (mangle_obstack, "C1", 2);
147 else
148 mangle_member_name (method_name);
149 obstack_1grow (mangle_obstack, 'E');
151 /* We mangled type.methodName. Now onto the arguments. */
152 arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
153 if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
154 arglist = TREE_CHAIN (arglist);
156 /* No arguments is easy. We shortcut it. */
157 if (arglist == end_params_node)
158 obstack_1grow (mangle_obstack, 'v');
159 else
161 tree arg;
162 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
163 mangle_type (TREE_VALUE (arg));
167 /* This mangles a member name, like a function name or a field
168 name. Handle cases were `name' is a C++ keyword. Return a nonzero
169 value if unicode encoding was required. */
171 static void
172 mangle_member_name (tree name)
174 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
175 IDENTIFIER_LENGTH (name));
177 /* If NAME happens to be a C++ keyword, add `$'. */
178 if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
179 obstack_1grow (mangle_obstack, '$');
182 /* Append the mangled name of TYPE onto OBSTACK. */
184 static void
185 mangle_type (tree type)
187 switch (TREE_CODE (type))
189 char code;
190 case BOOLEAN_TYPE: code = 'b'; goto primitive;
191 case CHAR_TYPE: code = 'w'; goto primitive;
192 case VOID_TYPE: code = 'v'; goto primitive;
193 case INTEGER_TYPE:
194 /* Get the original type instead of the arguments promoted type.
195 Avoid symbol name clashes. Should call a function to do that.
196 FIXME. */
197 if (type == promoted_short_type_node)
198 type = short_type_node;
199 if (type == promoted_byte_type_node)
200 type = byte_type_node;
201 switch (TYPE_PRECISION (type))
203 case 8: code = 'c'; goto primitive;
204 case 16: code = 's'; goto primitive;
205 case 32: code = 'i'; goto primitive;
206 case 64: code = 'x'; goto primitive;
207 default: goto bad_type;
209 primitive:
210 obstack_1grow (mangle_obstack, code);
211 break;
213 case REAL_TYPE:
214 switch (TYPE_PRECISION (type))
216 case 32: code = 'f'; goto primitive;
217 case 64: code = 'd'; goto primitive;
218 default: goto bad_type;
220 case POINTER_TYPE:
221 if (TYPE_ARRAY_P (TREE_TYPE (type)))
222 mangle_array_type (type);
223 else
224 mangle_pointer_type (type);
225 break;
226 bad_type:
227 default:
228 abort ();
232 /* The compression table is a vector that keeps track of things we've
233 already seen, so they can be reused. For example, java.lang.Object
234 would generate three entries: two package names and a type. If
235 java.lang.String is presented next, the java.lang will be matched
236 against the first two entries (and kept for compression as S_0), and
237 type String would be added to the table. See mangle_record_type.
238 COMPRESSION_NEXT is the index to the location of the next insertion
239 of an element. */
241 static GTY(()) tree compression_table;
242 static int compression_next;
244 /* Find a POINTER_TYPE in the compression table. Use a special
245 function to match pointer entries and start from the end */
247 static int
248 find_compression_pointer_match (tree type)
250 int i;
252 for (i = compression_next-1; i >= 0; i--)
253 if (entry_match_pointer_p (type, i))
254 return i;
255 return -1;
258 /* Already recorder arrays are handled like pointer as they're always
259 associated with it. */
261 static int
262 find_compression_array_match (tree type)
264 return find_compression_pointer_match (type);
267 /* Match the table of type against STRING. */
269 static int
270 find_compression_array_template_match (tree string)
272 int i;
273 for (i = 0; i < compression_next; i++)
274 if (TREE_VEC_ELT (compression_table, i) == string)
275 return i;
276 return -1;
279 /* We go through the compression table and try to find a complete or
280 partial match. The function returns the compression table entry
281 that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
282 to the rest of TYPE to be mangled. */
284 static int
285 find_compression_record_match (tree type, tree *next_current)
287 int i, match;
288 tree current, saved_current = NULL_TREE;
290 /* Search from the beginning for something that matches TYPE, even
291 partially. */
292 for (current = TYPE_PACKAGE_LIST (type), i = 0, match = -1; current;
293 current = TREE_CHAIN (current))
295 int j;
296 for (j = i; j < compression_next; j++)
297 if (TREE_VEC_ELT (compression_table, j) == TREE_PURPOSE (current))
299 match = i = j;
300 saved_current = current;
301 i++;
302 break;
304 else
306 /* We don't want to match an element that appears in the middle
307 of a package name, so skip forward to the next complete type name.
308 IDENTIFIER_NODEs are partial package names while RECORD_TYPEs
309 represent complete type names. */
310 while (j < compression_next
311 && TREE_CODE (TREE_VEC_ELT (compression_table, j)) ==
312 IDENTIFIER_NODE)
313 j++;
317 if (!next_current)
318 return match;
320 /* If we have a match, set next_current to the item next to the last
321 matched value. */
322 if (match >= 0)
323 *next_current = TREE_CHAIN (saved_current);
324 /* We had no match: we'll have to start from the beginning. */
325 if (match < 0)
326 *next_current = TYPE_PACKAGE_LIST (type);
328 return match;
331 /* Mangle a record type. If a nonzero value is returned, it means
332 that a 'N' was emitted (so that a matching 'E' can be emitted if
333 necessary.) FOR_POINTER indicates that this element is for a pointer
334 symbol, meaning it was preceded by a 'P'. */
336 static int
337 mangle_record_type (tree type, int for_pointer)
339 tree current;
340 int match;
341 int nadded_p = 0;
342 int qualified;
344 /* Does this name have a package qualifier? */
345 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
347 #define ADD_N() \
348 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
350 if (TREE_CODE (type) != RECORD_TYPE)
351 abort ();
353 if (!TYPE_PACKAGE_LIST (type))
354 set_type_package_list (type);
356 match = find_compression_record_match (type, &current);
357 if (match >= 0)
359 /* If we had a pointer, and there's more, we need to emit
360 'N' after 'P' (for_pointer tells us we already emitted it.) */
361 if (for_pointer && current)
362 ADD_N();
363 emit_compression_string (match);
365 while (current)
367 /* Add the new type to the table */
368 compression_table_add (TREE_PURPOSE (current));
369 /* Add 'N' if we never got a chance to, but only if we have a qualified
370 name. For non-pointer elements, the name is always qualified. */
371 if ((qualified || !for_pointer) && !nadded_p)
372 ADD_N();
373 /* Use the bare type name for the mangle. */
374 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
375 IDENTIFIER_LENGTH (TREE_VALUE (current)));
376 current = TREE_CHAIN (current);
378 return nadded_p;
379 #undef ADD_N
382 /* Mangle a pointer type. There are two cases: the pointer is already
383 in the compression table: the compression is emitted sans 'P'
384 indicator. Otherwise, a 'P' is emitted and, depending on the type,
385 a partial compression or/plus the rest of the mangling. */
387 static void
388 mangle_pointer_type (tree type)
390 int match;
391 tree pointer_type;
393 /* Search for the type already in the compression table */
394 if ((match = find_compression_pointer_match (type)) >= 0)
396 emit_compression_string (match);
397 return;
400 /* This didn't work. We start by mangling the pointed-to type */
401 pointer_type = type;
402 type = TREE_TYPE (type);
403 if (TREE_CODE (type) != RECORD_TYPE)
404 abort ();
406 obstack_1grow (mangle_obstack, 'P');
407 if (mangle_record_type (type, /* for_pointer = */ 1))
408 obstack_1grow (mangle_obstack, 'E');
410 /* Don't forget to insert the pointer type in the table */
411 compression_table_add (pointer_type);
414 /* Mangle an array type. Search for an easy solution first, then go
415 through the process of finding out whether the bare array type or even
416 the template indicator where already used an compress appropriately.
417 It handles pointers. */
419 /* atms: array template mangled string. */
420 static GTY(()) tree atms;
421 static void
422 mangle_array_type (tree p_type)
424 tree type, elt_type;
425 int match;
427 type = TREE_TYPE (p_type);
428 if (!type)
429 abort ();
431 elt_type = TYPE_ARRAY_ELEMENT (type);
433 /* We cache a bit of the Jarray <> mangle. */
434 if (!atms)
436 atms = get_identifier ("6JArray");
439 /* Maybe we have what we're looking in the compression table. */
440 if ((match = find_compression_array_match (p_type)) >= 0)
442 emit_compression_string (match);
443 return;
446 /* We know for a fact that all arrays are pointers */
447 obstack_1grow (mangle_obstack, 'P');
448 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
449 if ((match = find_compression_record_match (type, NULL)) > 0)
451 emit_compression_string (match);
452 return;
455 /* Maybe we already have just JArray somewhere */
456 if ((match = find_compression_array_template_match (atms)) > 0)
457 emit_compression_string (match);
458 else
460 /* Start the template mangled name */
461 obstack_grow (mangle_obstack,
462 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
463 /* Insert in the compression table */
464 compression_table_add (atms);
467 /* Mangle Jarray <elt_type> */
468 obstack_1grow (mangle_obstack, 'I');
469 mangle_type (elt_type);
470 obstack_1grow (mangle_obstack, 'E');
472 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
473 compression_table_add (type);
474 compression_table_add (p_type);
477 /* Write a substitution string for entry I. Substitution string starts a
478 -1 (encoded S_.) The base is 36, and the code shamlessly taken from
479 cp/mangle.c. */
481 static void
482 emit_compression_string (int i)
484 i -= 1; /* Adjust */
485 obstack_1grow (mangle_obstack, 'S');
486 if (i >= 0)
488 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
489 unsigned HOST_WIDE_INT n;
490 unsigned HOST_WIDE_INT m=1;
491 /* How many digits for I in base 36? */
492 for (n = i; n >= 36; n /= 36, m *=36);
493 /* Write the digits out */
494 while (m > 0)
496 int digit = i / m;
497 obstack_1grow (mangle_obstack, digits [digit]);
498 i -= digit * m;
499 m /= 36;
502 obstack_1grow (mangle_obstack, '_');
505 /* If search the compression table at index I for a pointer type
506 equivalent to TYPE (meaning that after all the indirection, which
507 might all be unique, we find the same RECORD_TYPE.) */
509 static int
510 entry_match_pointer_p (tree type, int i)
512 tree t = TREE_VEC_ELT (compression_table, i);
514 while (TREE_CODE (type) == POINTER_TYPE
515 && TREE_CODE (t) == POINTER_TYPE)
517 t = TREE_TYPE (t);
518 type = TREE_TYPE (type);
520 return (TREE_CODE (type) == RECORD_TYPE
521 && TREE_CODE (t) == RECORD_TYPE
522 && t == type);
525 /* Go through all qualification of type and build a list of list node
526 elements containings as a purpose what should be used for a match and
527 inserted in the compression table; and as it value the raw name of the
528 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
530 static void
531 set_type_package_list (tree type)
533 int i;
534 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
535 char *ptr;
536 int qualifications;
537 tree list = NULL_TREE, elt;
539 for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
540 if (*ptr == '.')
541 qualifications += 1;
543 for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
545 if (ptr [0] == '.')
547 char c;
548 tree identifier;
550 /* Can't use an obstack, we're already using it to
551 accumulate the mangling. */
552 c = ptr [0];
553 ptr [0] = '\0';
554 identifier = get_identifier (type_string);
555 ptr [0] = c;
556 elt = build_tree_list (identifier, identifier);
557 TREE_CHAIN (elt) = list;
558 list = elt;
559 type_string = ptr+1;
560 i += 1;
564 elt = build_tree_list (type, get_identifier (type_string));
565 TREE_CHAIN (elt) = list;
566 list = elt;
567 TYPE_PACKAGE_LIST (type) = nreverse (list);
570 /* Add TYPE as the last element of the compression table. Resize the
571 compression table if necessary. */
573 static void
574 compression_table_add (tree type)
576 if (compression_next == TREE_VEC_LENGTH (compression_table))
578 tree new = make_tree_vec (2*compression_next);
579 int i;
581 for (i = 0; i < compression_next; i++)
582 TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
584 compression_table = new;
586 TREE_VEC_ELT (compression_table, compression_next++) = type;
589 /* Mangling initialization routine. */
591 static void
592 init_mangling (struct obstack *obstack)
594 mangle_obstack = obstack;
595 if (!compression_table)
596 compression_table = make_tree_vec (10);
597 else
598 /* Mangling already in progress. */
599 abort ();
601 /* Mangled name are to be suffixed */
602 obstack_grow (mangle_obstack, "_Z", 2);
605 /* Mangling finalization routine. The mangled name is returned as a
606 IDENTIFIER_NODE. */
608 static tree
609 finish_mangling (void)
611 tree result;
613 if (!compression_table)
614 /* Mangling already finished. */
615 abort ();
617 compression_table = NULL_TREE;
618 compression_next = 0;
619 obstack_1grow (mangle_obstack, '\0');
620 result = get_identifier (obstack_base (mangle_obstack));
621 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
622 #if 0
623 printf ("// %s\n", IDENTIFIER_POINTER (result));
624 #endif
625 return result;
628 #include "gt-java-mangle.h"