Daily bump.
[gcc.git] / gcc / java / mangle.c
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.
5
6 This file is part of GCC.
7
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.
12
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.
17
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.
22
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. */
26
27 /* Written by Per Bothner <bothner@cygnus.com> */
28
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"
40
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);
46
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);
51
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);
56
57 static void set_type_package_list (tree);
58 static int entry_match_pointer_p (tree, int);
59 static void emit_compression_string (int);
60
61 static void init_mangling (void);
62 static tree finish_mangling (void);
63 static void compression_table_add (tree);
64
65 static void mangle_member_name (tree);
66
67 static struct obstack mangle_obstack_1;
68 struct obstack *mangle_obstack;
69
70 #define MANGLE_RAW_STRING(S) \
71 obstack_grow (mangle_obstack, (S), sizeof (S)-1)
72
73 /* atms: array template mangled string. */
74 static GTY(()) tree atms;
75
76 /* This is the mangling interface: a decl, a class field (.class) and
77 the vtable. */
78
79 void
80 java_mangle_decl (tree decl)
81 {
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))));
90
91 /* Mangling only applies to class members. */
92 if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
93 {
94 init_mangling ();
95 switch (TREE_CODE (decl))
96 {
97 case VAR_DECL:
98 if (DECL_LANG_SPECIFIC (decl))
99 {
100 if (DECL_CLASS_FIELD_P (decl))
101 {
102 mangle_class_field (DECL_CONTEXT (decl));
103 break;
104 }
105 else if (DECL_VTABLE_P (decl))
106 {
107 mangle_vtable (DECL_CONTEXT (decl));
108 break;
109 }
110 }
111 mangle_field_decl (decl);
112 break;
113
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;
120
121 default:
122 gcc_unreachable ();
123 }
124 SET_DECL_ASSEMBLER_NAME (decl, finish_mangling ());
125 }
126 else
127 lhd_set_decl_assembler_name (decl);
128 }
129
130 /* Beginning of the helper functions */
131
132 static void
133 mangle_class_field (tree type)
134 {
135 mangle_record_type (type, /* for_pointer = */ 0);
136 MANGLE_RAW_STRING ("6class$");
137 obstack_1grow (mangle_obstack, 'E');
138 }
139
140 static void
141 mangle_vtable (tree type)
142 {
143 MANGLE_RAW_STRING ("TV");
144 mangle_record_type (type, /* for_pointer = */ 0);
145 obstack_1grow (mangle_obstack, 'E');
146 }
147
148 /* This mangles a field decl */
149
150 static void
151 mangle_field_decl (tree decl)
152 {
153 /* Mangle the name of the this the field belongs to */
154 mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
155
156 /* Mangle the name of the field */
157 mangle_member_name (DECL_NAME (decl));
158
159 /* Terminate the mangled name */
160 obstack_1grow (mangle_obstack, 'E');
161 }
162
163 /* This mangles a method decl, first mangling its name and then all
164 its arguments. */
165
166 static void
167 mangle_method_decl (tree mdecl)
168 {
169 tree method_name = DECL_NAME (mdecl);
170 tree arglist;
171
172 /* Mangle the name of the type that contains mdecl */
173 mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
174
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');
185
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);
190
191 /* Output literal 'J' and mangle the return type IF not a
192 constructor. */
193 if (!ID_INIT_P (method_name))
194 {
195 obstack_1grow (mangle_obstack, 'J');
196 mangle_type(TREE_TYPE(TREE_TYPE(mdecl)));
197 }
198
199 /* No arguments is easy. We shortcut it. */
200 if (arglist == end_params_node)
201 obstack_1grow (mangle_obstack, 'v');
202 else
203 {
204 tree arg;
205 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
206 mangle_type (TREE_VALUE (arg));
207 }
208 }
209
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. */
214
215 static void
216 mangle_local_cni_method_decl (tree decl)
217 {
218 MANGLE_RAW_STRING ("GA");
219 mangle_method_decl (decl);
220 }
221
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. */
225
226 static void
227 mangle_member_name (tree name)
228 {
229 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
230 IDENTIFIER_LENGTH (name));
231
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, '$');
235 }
236
237 /* Append the mangled name of TYPE onto OBSTACK. */
238
239 static void
240 mangle_type (tree type)
241 {
242 switch (TREE_CODE (type))
243 {
244 char code;
245 case BOOLEAN_TYPE: code = 'b'; goto primitive;
246 case VOID_TYPE: code = 'v'; goto primitive;
247 case INTEGER_TYPE:
248 if (type == char_type_node || type == promoted_char_type_node)
249 {
250 code = 'w';
251 goto primitive;
252 }
253 /* Get the original type instead of the arguments promoted type.
254 Avoid symbol name clashes. Should call a function to do that.
255 FIXME. */
256 if (type == promoted_short_type_node)
257 type = short_type_node;
258 if (type == promoted_byte_type_node)
259 type = byte_type_node;
260 switch (TYPE_PRECISION (type))
261 {
262 case 8: code = 'c'; goto primitive;
263 case 16: code = 's'; goto primitive;
264 case 32: code = 'i'; goto primitive;
265 case 64: code = 'x'; goto primitive;
266 default: goto bad_type;
267 }
268 primitive:
269 obstack_1grow (mangle_obstack, code);
270 break;
271
272 case REAL_TYPE:
273 switch (TYPE_PRECISION (type))
274 {
275 case 32: code = 'f'; goto primitive;
276 case 64: code = 'd'; goto primitive;
277 default: goto bad_type;
278 }
279 case POINTER_TYPE:
280 if (TYPE_ARRAY_P (TREE_TYPE (type)))
281 mangle_array_type (type);
282 else
283 mangle_pointer_type (type);
284 break;
285 bad_type:
286 default:
287 gcc_unreachable ();
288 }
289 }
290
291 /* The compression table is a vector that keeps track of things we've
292 already seen, so they can be reused. For example, java.lang.Object
293 would generate three entries: two package names and a type. If
294 java.lang.String is presented next, the java.lang will be matched
295 against the first two entries (and kept for compression as S0_), and
296 type String would be added to the table. See mangle_record_type.
297 COMPRESSION_NEXT is the index to the location of the next insertion
298 of an element. */
299
300 static GTY(()) tree compression_table;
301 static int compression_next;
302
303 /* Find a POINTER_TYPE in the compression table. Use a special
304 function to match pointer entries and start from the end */
305
306 static int
307 find_compression_pointer_match (tree type)
308 {
309 int i;
310
311 for (i = compression_next-1; i >= 0; i--)
312 if (entry_match_pointer_p (type, i))
313 return i;
314 return -1;
315 }
316
317 /* Already recorder arrays are handled like pointer as they're always
318 associated with it. */
319
320 static int
321 find_compression_array_match (tree type)
322 {
323 return find_compression_pointer_match (type);
324 }
325
326 /* Match the table of type against STRING. */
327
328 static int
329 find_compression_array_template_match (tree string)
330 {
331 int i;
332 for (i = 0; i < compression_next; i++)
333 if (TREE_VEC_ELT (compression_table, i) == string)
334 return i;
335 return -1;
336 }
337
338 /* We go through the compression table and try to find a complete or
339 partial match. The function returns the compression table entry
340 that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
341 to the rest of TYPE to be mangled. */
342
343 static int
344 find_compression_record_match (tree type, tree *next_current)
345 {
346 int i, match = -1;
347 tree current, saved_current = NULL_TREE;
348
349 current = TYPE_PACKAGE_LIST (type);
350
351 for (i = 0; i < compression_next; i++)
352 {
353 tree compression_entry = TREE_VEC_ELT (compression_table, i);
354 if (current && compression_entry == TREE_PURPOSE (current))
355 {
356 match = i;
357 saved_current = current;
358 current = TREE_CHAIN (current);
359 }
360 else
361 /* We don't want to match an element that appears in the middle
362 of a package name, so skip forward to the next complete type name.
363 IDENTIFIER_NODEs (except for a "6JArray") are partial package
364 names while RECORD_TYPEs represent complete type names. */
365 while (i < compression_next
366 && TREE_CODE (compression_entry) == IDENTIFIER_NODE
367 && compression_entry != atms)
368 compression_entry = TREE_VEC_ELT (compression_table, ++i);
369 }
370
371 if (!next_current)
372 return match;
373
374 /* If we have a match, set next_current to the item next to the last
375 matched value. */
376 if (match >= 0)
377 *next_current = TREE_CHAIN (saved_current);
378 /* We had no match: we'll have to start from the beginning. */
379 if (match < 0)
380 *next_current = TYPE_PACKAGE_LIST (type);
381
382 return match;
383 }
384
385 /* Mangle a record type. If a nonzero value is returned, it means
386 that a 'N' was emitted (so that a matching 'E' can be emitted if
387 necessary.) FOR_POINTER indicates that this element is for a pointer
388 symbol, meaning it was preceded by a 'P'. */
389
390 static int
391 mangle_record_type (tree type, int for_pointer)
392 {
393 tree current;
394 int match;
395 int nadded_p = 0;
396 int qualified;
397
398 /* Does this name have a package qualifier? */
399 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
400
401 #define ADD_N() \
402 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
403
404 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
405
406 if (!TYPE_PACKAGE_LIST (type))
407 set_type_package_list (type);
408
409 match = find_compression_record_match (type, &current);
410 if (match >= 0)
411 {
412 /* If we had a pointer, and there's more, we need to emit
413 'N' after 'P' (for_pointer tells us we already emitted it.) */
414 if (for_pointer && current)
415 ADD_N();
416 emit_compression_string (match);
417 }
418 while (current)
419 {
420 /* Add the new type to the table */
421 compression_table_add (TREE_PURPOSE (current));
422 /* Add 'N' if we never got a chance to, but only if we have a qualified
423 name. For non-pointer elements, the name is always qualified. */
424 if ((qualified || !for_pointer) && !nadded_p)
425 ADD_N();
426 /* Use the bare type name for the mangle. */
427 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
428 IDENTIFIER_LENGTH (TREE_VALUE (current)));
429 current = TREE_CHAIN (current);
430 }
431 return nadded_p;
432 #undef ADD_N
433 }
434
435 /* Mangle a pointer type. There are two cases: the pointer is already
436 in the compression table: the compression is emitted sans 'P'
437 indicator. Otherwise, a 'P' is emitted and, depending on the type,
438 a partial compression or/plus the rest of the mangling. */
439
440 static void
441 mangle_pointer_type (tree type)
442 {
443 int match;
444 tree pointer_type;
445
446 /* Search for the type already in the compression table */
447 if ((match = find_compression_pointer_match (type)) >= 0)
448 {
449 emit_compression_string (match);
450 return;
451 }
452
453 /* This didn't work. We start by mangling the pointed-to type */
454 pointer_type = type;
455 type = TREE_TYPE (type);
456 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
457
458 obstack_1grow (mangle_obstack, 'P');
459 if (mangle_record_type (type, /* for_pointer = */ 1))
460 obstack_1grow (mangle_obstack, 'E');
461
462 /* Don't forget to insert the pointer type in the table */
463 compression_table_add (pointer_type);
464 }
465
466 /* Mangle an array type. Search for an easy solution first, then go
467 through the process of finding out whether the bare array type or even
468 the template indicator were already used and compressed appropriately.
469 It handles pointers. */
470
471 static void
472 mangle_array_type (tree p_type)
473 {
474 tree type, elt_type;
475 int match;
476
477 type = TREE_TYPE (p_type);
478 gcc_assert (type);
479
480 elt_type = TYPE_ARRAY_ELEMENT (type);
481
482 /* We cache a bit of the Jarray <> mangle. */
483 if (!atms)
484 {
485 atms = get_identifier ("6JArray");
486 }
487
488 /* Maybe we have what we're looking for in the compression table. */
489 if ((match = find_compression_array_match (p_type)) >= 0)
490 {
491 emit_compression_string (match);
492 return;
493 }
494
495 /* We know for a fact that all arrays are pointers */
496 obstack_1grow (mangle_obstack, 'P');
497 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
498 if ((match = find_compression_record_match (type, NULL)) > 0)
499 {
500 emit_compression_string (match);
501 return;
502 }
503
504 /* Maybe we already have just JArray somewhere */
505 if ((match = find_compression_array_template_match (atms)) > 0)
506 emit_compression_string (match);
507 else
508 {
509 /* Start the template mangled name */
510 obstack_grow (mangle_obstack,
511 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
512 /* Insert in the compression table */
513 compression_table_add (atms);
514 }
515
516 /* Mangle Jarray <elt_type> */
517 obstack_1grow (mangle_obstack, 'I');
518 mangle_type (elt_type);
519 obstack_1grow (mangle_obstack, 'E');
520
521 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
522 compression_table_add (type);
523 compression_table_add (p_type);
524 }
525
526 /* Write a substitution string for entry I. Substitution string starts a
527 -1 (encoded S_.) The base is 36, and the code shamelessly taken from
528 cp/mangle.c. */
529
530 static void
531 emit_compression_string (int i)
532 {
533 i -= 1; /* Adjust */
534 obstack_1grow (mangle_obstack, 'S');
535 if (i >= 0)
536 {
537 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
538 unsigned HOST_WIDE_INT n;
539 unsigned HOST_WIDE_INT m=1;
540 /* How many digits for I in base 36? */
541 for (n = i; n >= 36; n /= 36, m *=36);
542 /* Write the digits out */
543 while (m > 0)
544 {
545 int digit = i / m;
546 obstack_1grow (mangle_obstack, digits [digit]);
547 i -= digit * m;
548 m /= 36;
549 }
550 }
551 obstack_1grow (mangle_obstack, '_');
552 }
553
554 /* If search the compression table at index I for a pointer type
555 equivalent to TYPE (meaning that after all the indirection, which
556 might all be unique, we find the same RECORD_TYPE.) */
557
558 static int
559 entry_match_pointer_p (tree type, int i)
560 {
561 tree t = TREE_VEC_ELT (compression_table, i);
562
563 while (TREE_CODE (type) == POINTER_TYPE
564 && TREE_CODE (t) == POINTER_TYPE)
565 {
566 t = TREE_TYPE (t);
567 type = TREE_TYPE (type);
568 }
569 return (TREE_CODE (type) == RECORD_TYPE
570 && TREE_CODE (t) == RECORD_TYPE
571 && t == type);
572 }
573
574 /* Go through all qualification of type and build a list of list node
575 elements containings as a purpose what should be used for a match and
576 inserted in the compression table; and as it value the raw name of the
577 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
578
579 static void
580 set_type_package_list (tree type)
581 {
582 int i;
583 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
584 char *ptr;
585 int qualifications;
586 tree list = NULL_TREE, elt;
587
588 for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
589 if (*ptr == '.')
590 qualifications += 1;
591
592 for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
593 {
594 if (ptr [0] == '.')
595 {
596 char c;
597 tree identifier;
598
599 /* Can't use an obstack, we're already using it to
600 accumulate the mangling. */
601 c = ptr [0];
602 ptr [0] = '\0';
603 identifier = get_identifier (type_string);
604 ptr [0] = c;
605 elt = build_tree_list (identifier, identifier);
606 TREE_CHAIN (elt) = list;
607 list = elt;
608 type_string = ptr+1;
609 i += 1;
610 }
611 }
612
613 elt = build_tree_list (type, get_identifier (type_string));
614 TREE_CHAIN (elt) = list;
615 list = elt;
616 TYPE_PACKAGE_LIST (type) = nreverse (list);
617 }
618
619 /* Add TYPE as the last element of the compression table. Resize the
620 compression table if necessary. */
621
622 static void
623 compression_table_add (tree type)
624 {
625 if (compression_next == TREE_VEC_LENGTH (compression_table))
626 {
627 tree new = make_tree_vec (2*compression_next);
628 int i;
629
630 for (i = 0; i < compression_next; i++)
631 TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
632
633 compression_table = new;
634 }
635 TREE_VEC_ELT (compression_table, compression_next++) = type;
636 }
637
638 /* Mangling initialization routine. */
639
640 static void
641 init_mangling (void)
642 {
643 if (!mangle_obstack)
644 {
645 mangle_obstack = &mangle_obstack_1;
646 gcc_obstack_init (mangle_obstack);
647 }
648
649 gcc_assert (compression_table == NULL);
650 compression_table = make_tree_vec (10);
651
652 /* Mangled name are to be suffixed */
653 MANGLE_RAW_STRING ("_Z");
654 }
655
656 /* Mangling finalization routine. The mangled name is returned as a
657 IDENTIFIER_NODE. */
658
659 static tree
660 finish_mangling (void)
661 {
662 tree result;
663
664 gcc_assert (compression_table);
665
666 compression_table = NULL_TREE;
667 compression_next = 0;
668 obstack_1grow (mangle_obstack, '\0');
669 result = get_identifier (obstack_base (mangle_obstack));
670 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
671
672 return result;
673 }
674
675 #include "gt-java-mangle.h"