* print-rtl.c (xspaces): Remove.
[official-gcc.git] / gcc / java / mangle.c
blob027eb5d5babc5bbc45a814c5849e600ce517a730
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)
10 any later version.
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> */
28 #include "config.h"
29 #include "system.h"
30 #include "jcf.h"
31 #include "tree.h"
32 #include "java-tree.h"
33 #include "obstack.h"
34 #include "toplev.h"
35 #include "obstack.h"
36 #include "ggc.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 mangle_member_name PARAMS ((tree));
61 /* We use an incoming obstack, always to be provided to the interface
62 functions. */
63 struct obstack *mangle_obstack;
64 #define MANGLE_RAW_STRING(S) \
65 obstack_grow (mangle_obstack, (S), sizeof (S)-1)
67 /* This is the mangling interface: a decl, a class field (.class) and
68 the vtable. */
70 tree
71 java_mangle_decl (obstack, decl)
72 struct obstack *obstack;
73 tree decl;
75 init_mangling (obstack);
76 switch (TREE_CODE (decl))
78 case VAR_DECL:
79 mangle_field_decl (decl);
80 break;
81 case FUNCTION_DECL:
82 mangle_method_decl (decl);
83 break;
84 default:
85 internal_error ("Can't mangle %s", tree_code_name [TREE_CODE (decl)]);
87 return finish_mangling ();
90 tree
91 java_mangle_class_field (obstack, type)
92 struct obstack *obstack;
93 tree type;
95 init_mangling (obstack);
96 mangle_record_type (type, /* for_pointer = */ 0);
97 MANGLE_RAW_STRING ("6class$");
98 obstack_1grow (mangle_obstack, 'E');
99 return finish_mangling ();
102 tree
103 java_mangle_vtable (obstack, type)
104 struct obstack *obstack;
105 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 (decl)
120 tree decl;
122 /* Mangle the name of the this the field belongs to */
123 mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
125 /* Mangle the name of the field */
126 mangle_member_name (DECL_NAME (decl));
128 /* Terminate the mangled name */
129 obstack_1grow (mangle_obstack, 'E');
132 /* This mangles a method decl, first mangling its name and then all
133 its arguments. */
135 static void
136 mangle_method_decl (mdecl)
137 tree mdecl;
139 tree method_name = DECL_NAME (mdecl);
140 tree arglist;
142 /* Mangle the name of the type that contains mdecl */
143 mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
145 /* Mangle the function name. There three cases
146 - mdecl is java.lang.Object.Object(), use `C2' for its name
147 (denotes a base object constructor.)
148 - mdecl is a constructor, use `C1' for its name, (denotes a
149 complete object constructor.)
150 - mdecl is not a constructor, standard mangling is performed.
151 We terminate the mangled function name with a `E'. */
152 if (ID_INIT_P (method_name))
154 if (DECL_CONTEXT (mdecl) == object_type_node)
155 obstack_grow (mangle_obstack, "C2", 2);
156 else
157 obstack_grow (mangle_obstack, "C1", 2);
159 else
160 mangle_member_name (method_name);
161 obstack_1grow (mangle_obstack, 'E');
163 /* We mangled type.methodName. Now onto the arguments. */
164 arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
165 if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
166 arglist = TREE_CHAIN (arglist);
168 /* No arguments is easy. We shortcut it. */
169 if (arglist == end_params_node)
170 obstack_1grow (mangle_obstack, 'v');
171 else
173 tree arg;
174 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
175 mangle_type (TREE_VALUE (arg));
179 /* This mangles a member name, like a function name or a field
180 name. Handle cases were `name' is a C++ keyword. Return a non zero
181 value if unicode encoding was required. */
183 static void
184 mangle_member_name (name)
185 tree name;
187 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
188 IDENTIFIER_LENGTH (name));
190 /* If NAME happens to be a C++ keyword, add `$' or `.' or `_'. */
191 if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
193 #ifndef NO_DOLLAR_IN_LABEL
194 obstack_1grow (mangle_obstack, '$');
195 #else /* NO_DOLLAR_IN_LABEL */
196 #ifndef NO_DOT_IN_LABEL
197 obstack_1grow (mangle_obstack, '.');
198 #else /* NO_DOT_IN_LABEL */
199 obstack_1grow (mangle_obstack, '_');
200 #endif /* NO_DOT_IN_LABEL */
201 #endif /* NO_DOLLAR_IN_LABEL */
205 /* Append the mangled name of TYPE onto OBSTACK. */
207 static void
208 mangle_type (type)
209 tree type;
211 switch (TREE_CODE (type))
213 char code;
214 case BOOLEAN_TYPE: code = 'b'; goto primitive;
215 case CHAR_TYPE: code = 'w'; goto primitive;
216 case VOID_TYPE: code = 'v'; goto primitive;
217 case INTEGER_TYPE:
218 /* Get the original type instead of the arguments promoted type.
219 Avoid symbol name clashes. Should call a function to do that.
220 FIXME. */
221 if (type == promoted_short_type_node)
222 type = short_type_node;
223 if (type == promoted_byte_type_node)
224 type = byte_type_node;
225 switch (TYPE_PRECISION (type))
227 case 8: code = 'c'; goto primitive;
228 case 16: code = 's'; goto primitive;
229 case 32: code = 'i'; goto primitive;
230 case 64: code = 'x'; goto primitive;
231 default: goto bad_type;
233 primitive:
234 obstack_1grow (mangle_obstack, code);
235 break;
237 case REAL_TYPE:
238 switch (TYPE_PRECISION (type))
240 case 32: code = 'f'; goto primitive;
241 case 64: code = 'd'; goto primitive;
242 default: goto bad_type;
244 case POINTER_TYPE:
245 if (TYPE_ARRAY_P (TREE_TYPE (type)))
246 mangle_array_type (type);
247 else
248 mangle_pointer_type (type);
249 break;
250 bad_type:
251 default:
252 abort ();
256 /* The compression table is a vector that keeps track of things we've
257 already seen, so they can be reused. For example, java.lang.Object
258 Would generate three entries: two package names and a type. If
259 java.lang.String is presented next, the java.lang will be matched
260 against the first two entries (and kept for compression as S_0), and
261 type String would be added to the table. See mangle_record_type.
262 COMPRESSION_NEXT is the index to the location of the next insertion
263 of an element. */
265 static tree compression_table;
266 static int compression_next;
268 /* Find a POINTER_TYPE in the compression table. Use a special
269 function to match pointer entries and start from the end */
271 static int
272 find_compression_pointer_match (type)
273 tree type;
275 int i;
277 for (i = compression_next-1; i >= 0; i--)
278 if (entry_match_pointer_p (type, i))
279 return i;
280 return -1;
283 /* Already recorder arrays are handled like pointer as they're always
284 associated with it. */
286 static int
287 find_compression_array_match (type)
288 tree type;
290 return find_compression_pointer_match (type);
293 /* Match the table of type against STRING. */
295 static int
296 find_compression_array_template_match (string)
297 tree string;
299 int i;
300 for (i = 0; i < compression_next; i++)
301 if (TREE_VEC_ELT (compression_table, i) == string)
302 return i;
303 return -1;
306 /* We go through the compression table and try to find a complete or
307 partial match. The function returns the compression table entry
308 that (evenutally partially) matches TYPE. *NEXT_CURRENT can be set
309 to the rest of TYPE to be mangled. */
311 static int
312 find_compression_record_match (type, next_current)
313 tree type;
314 tree *next_current;
316 int i, match;
317 tree current, saved_current = NULL_TREE;
319 /* Search from the beginning for something that matches TYPE, even
320 partially. */
321 for (current = TYPE_PACKAGE_LIST (type), i = 0, match = -1; current;
322 current = TREE_CHAIN (current))
324 int j;
325 for (j = i; j < compression_next; j++)
326 if (TREE_VEC_ELT (compression_table, j) == TREE_PURPOSE (current))
328 match = i = j;
329 saved_current = current;
330 break;
334 if (!next_current)
335 return match;
337 /* If we have a match, set next_current to the item next to the last
338 matched value. */
339 if (match >= 0)
340 *next_current = TREE_CHAIN (saved_current);
341 /* We had no match: we'll have to start from the beginning. */
342 if (match < 0)
343 *next_current = TYPE_PACKAGE_LIST (type);
345 return match;
348 /* Mangle a record type. If a non zero value is returned, it means
349 that a 'N' was emitted (so that a matching 'E' can be emitted if
350 necessary.) FOR_POINTER indicates that this element is for a pointer
351 symbol, meaning it was preceded by a 'P'. */
353 static int
354 mangle_record_type (type, for_pointer)
355 tree type;
356 int for_pointer;
358 tree current;
359 int match;
360 int nadded_p = 0;
361 int qualified;
363 /* Does this name have a package qualifier? */
364 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
366 #define ADD_N() \
367 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
369 if (TREE_CODE (type) != RECORD_TYPE)
370 abort ();
372 if (!TYPE_PACKAGE_LIST (type))
373 set_type_package_list (type);
375 match = find_compression_record_match (type, &current);
376 if (match >= 0)
378 /* If we had a pointer, and there's more, we need to emit
379 'N' after 'P' (for_pointer tells us we already emitted it.) */
380 if (for_pointer && current)
381 ADD_N();
382 emit_compression_string (match);
384 while (current)
386 /* Add the new type to the table */
387 compression_table_add (TREE_PURPOSE (current));
388 /* Add 'N' if we never got a chance to, but only if we have a qualified
389 name. For non-pointer elements, the name is always qualified. */
390 if ((qualified || !for_pointer) && !nadded_p)
391 ADD_N();
392 /* Use the bare type name for the mangle. */
393 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
394 IDENTIFIER_LENGTH (TREE_VALUE (current)));
395 current = TREE_CHAIN (current);
397 return nadded_p;
398 #undef ADD_N
401 /* Mangle a pointer type. There are two cases: the pointer is already
402 in the compression table: the compression is emited sans 'P'
403 indicator. Otherwise, a 'P' is emitted and, depending on the type,
404 a partial compression or/plus the rest of the mangling. */
406 static void
407 mangle_pointer_type (type)
408 tree type;
410 int match;
411 tree pointer_type;
413 /* Search for the type already in the compression table */
414 if ((match = find_compression_pointer_match (type)) >= 0)
416 emit_compression_string (match);
417 return;
420 /* This didn't work. We start by mangling the pointed-to type */
421 pointer_type = type;
422 type = TREE_TYPE (type);
423 if (TREE_CODE (type) != RECORD_TYPE)
424 abort ();
426 obstack_1grow (mangle_obstack, 'P');
427 if (mangle_record_type (type, /* for_pointer = */ 1))
428 obstack_1grow (mangle_obstack, 'E');
430 /* Don't forget to insert the pointer type in the table */
431 compression_table_add (pointer_type);
434 /* Mangle an array type. Search for an easy solution first, then go
435 through the process of finding out whether the bare array type or even
436 the template indicator where already used an compress appropriately.
437 It handles pointers. */
439 static void
440 mangle_array_type (p_type)
441 tree p_type;
443 /* atms: array template mangled string. */
444 static tree atms = NULL_TREE;
445 tree type, elt_type;
446 int match;
448 type = TREE_TYPE (p_type);
449 if (!type)
450 abort ();
452 elt_type = TYPE_ARRAY_ELEMENT (type);
454 /* We cache a bit of the Jarray <> mangle. */
455 if (!atms)
457 atms = get_identifier ("6JArray");
458 ggc_add_tree_root (&atms, 1);
461 /* Maybe we have what we're looking in the compression table. */
462 if ((match = find_compression_array_match (p_type)) >= 0)
464 emit_compression_string (match);
465 return;
468 /* We know for a fact that all arrays are pointers */
469 obstack_1grow (mangle_obstack, 'P');
470 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
471 if ((match = find_compression_record_match (type, NULL)) > 0)
473 emit_compression_string (match);
474 return;
477 /* Maybe we already have just JArray somewhere */
478 if ((match = find_compression_array_template_match (atms)) > 0)
479 emit_compression_string (match);
480 else
482 /* Start the template mangled name */
483 obstack_grow (mangle_obstack,
484 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
485 /* Insert in the compression table */
486 compression_table_add (atms);
489 /* Mangle Jarray <elt_type> */
490 obstack_1grow (mangle_obstack, 'I');
491 mangle_type (elt_type);
492 obstack_1grow (mangle_obstack, 'E');
494 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
495 compression_table_add (type);
496 compression_table_add (p_type);
499 /* Write a substition string for entry I. Substitution string starts a
500 -1 (encoded S_.) The base is 36, and the code shamlessly taken from
501 cp/mangle.c. */
503 static void
504 emit_compression_string (int i)
506 i -= 1; /* Adjust */
507 obstack_1grow (mangle_obstack, 'S');
508 if (i >= 0)
510 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
511 unsigned HOST_WIDE_INT n;
512 unsigned HOST_WIDE_INT m=1;
513 /* How many digits for I in base 36? */
514 for (n = i; n >= 36; n /= 36, m *=36);
515 /* Write the digits out */
516 while (m > 0)
518 int digit = i / m;
519 obstack_1grow (mangle_obstack, digits [digit]);
520 i -= digit * m;
521 m /= 36;
524 obstack_1grow (mangle_obstack, '_');
527 /* If search the compression table at index I for a pointer type
528 equivalent to TYPE (meaning that after all the indirection, which
529 might all be unique, we find the same RECORD_TYPE.) */
531 static int
532 entry_match_pointer_p (type, i)
533 tree type;
534 int i;
536 tree t = TREE_VEC_ELT (compression_table, i);
538 while (TREE_CODE (type) == POINTER_TYPE
539 && TREE_CODE (t) == POINTER_TYPE)
541 t = TREE_TYPE (t);
542 type = TREE_TYPE (type);
544 return (TREE_CODE (type) == RECORD_TYPE
545 && TREE_CODE (t) == RECORD_TYPE
546 && t == type);
549 /* Go through all qualification of type and build a list of list node
550 elements containings as a purpose what should be used for a match and
551 inserted in the compression table; and as it value the raw name of the
552 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
554 static void
555 set_type_package_list (type)
556 tree type;
558 int i;
559 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
560 char *ptr;
561 int qualifications;
562 tree list = NULL_TREE, elt;
564 for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
565 if (*ptr == '.')
566 qualifications += 1;
568 for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
570 if (ptr [0] == '.')
572 char c;
573 tree identifier;
575 /* Can't use an obstack, we're already using it to
576 accumulate the mangling. */
577 c = ptr [0];
578 ptr [0] = '\0';
579 identifier = get_identifier (type_string);
580 ptr [0] = c;
581 elt = build_tree_list (identifier, identifier);
582 TREE_CHAIN (elt) = list;
583 list = elt;
584 type_string = ptr+1;
585 i += 1;
589 elt = build_tree_list (type, get_identifier (type_string));
590 TREE_CHAIN (elt) = list;
591 list = elt;
592 TYPE_PACKAGE_LIST (type) = nreverse (list);
595 /* Add TYPE as the last element of the compression table. Resize the
596 compression table if necessary. */
598 static void
599 compression_table_add (type)
600 tree type;
602 if (compression_next == TREE_VEC_LENGTH (compression_table))
604 tree new = make_tree_vec (2*compression_next);
605 int i;
607 for (i = 0; i < compression_next; i++)
608 TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
610 ggc_del_root (&compression_table);
611 compression_table = new;
612 ggc_add_tree_root (&compression_table, 1);
614 TREE_VEC_ELT (compression_table, compression_next++) = type;
617 /* Mangling initialization routine. */
619 static void
620 init_mangling (obstack)
621 struct obstack *obstack;
623 mangle_obstack = obstack;
624 if (!compression_table)
625 compression_table = make_tree_vec (10);
626 else
627 /* Mangling already in progress. */
628 abort ();
630 /* Mangled name are to be suffixed */
631 obstack_grow (mangle_obstack, "_Z", 2);
633 /* Register the compression table with the GC */
634 ggc_add_tree_root (&compression_table, 1);
637 /* Mangling finalization routine. The mangled name is returned as a
638 IDENTIFIER_NODE. */
640 static tree
641 finish_mangling ()
643 tree result;
645 if (!compression_table)
646 /* Mangling already finished. */
647 abort ();
649 ggc_del_root (&compression_table);
650 compression_table = NULL_TREE;
651 compression_next = 0;
652 obstack_1grow (mangle_obstack, '\0');
653 result = get_identifier (obstack_base (mangle_obstack));
654 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
655 #if 0
656 printf ("// %s\n", IDENTIFIER_POINTER (result));
657 #endif
658 return result;