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, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, 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 "obstack.h"
39 #include "ggc.h"
40
41 static void mangle_field_decl (tree);
42 static void mangle_method_decl (tree);
43
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);
48
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);
53
54 static void set_type_package_list (tree);
55 static int entry_match_pointer_p (tree, int);
56 static void emit_compression_string (int);
57
58 static void init_mangling (struct obstack *);
59 static tree finish_mangling (void);
60 static void compression_table_add (tree);
61
62 static void mangle_member_name (tree);
63
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)
69
70 /* atms: array template mangled string. */
71 static GTY(()) tree atms;
72
73 /* This is the mangling interface: a decl, a class field (.class) and
74 the vtable. */
75
76 tree
java_mangle_decl(struct obstack * obstack,tree decl)77 java_mangle_decl (struct obstack *obstack, tree decl)
78 {
79 init_mangling (obstack);
80 switch (TREE_CODE (decl))
81 {
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)]);
90 }
91 return finish_mangling ();
92 }
93
94 tree
java_mangle_class_field(struct obstack * obstack,tree type)95 java_mangle_class_field (struct obstack *obstack, tree type)
96 {
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 ();
102 }
103
104 tree
java_mangle_vtable(struct obstack * obstack,tree type)105 java_mangle_vtable (struct obstack *obstack, tree type)
106 {
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 ();
112 }
113
114 /* Beginning of the helper functions */
115
116 /* This mangles a field decl */
117
118 static void
mangle_field_decl(tree decl)119 mangle_field_decl (tree decl)
120 {
121 /* Mangle the name of the this the field belongs to */
122 mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
123
124 /* Mangle the name of the field */
125 mangle_member_name (DECL_NAME (decl));
126
127 /* Terminate the mangled name */
128 obstack_1grow (mangle_obstack, 'E');
129 }
130
131 /* This mangles a method decl, first mangling its name and then all
132 its arguments. */
133
134 static void
mangle_method_decl(tree mdecl)135 mangle_method_decl (tree mdecl)
136 {
137 tree method_name = DECL_NAME (mdecl);
138 tree arglist;
139
140 /* Mangle the name of the type that contains mdecl */
141 mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
142
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');
153
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);
158
159 /* No arguments is easy. We shortcut it. */
160 if (arglist == end_params_node)
161 obstack_1grow (mangle_obstack, 'v');
162 else
163 {
164 tree arg;
165 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
166 mangle_type (TREE_VALUE (arg));
167 }
168 }
169
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. */
173
174 static void
mangle_member_name(tree name)175 mangle_member_name (tree name)
176 {
177 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
178 IDENTIFIER_LENGTH (name));
179
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, '$');
183 }
184
185 /* Append the mangled name of TYPE onto OBSTACK. */
186
187 static void
mangle_type(tree type)188 mangle_type (tree type)
189 {
190 switch (TREE_CODE (type))
191 {
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))
205 {
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;
211 }
212 primitive:
213 obstack_1grow (mangle_obstack, code);
214 break;
215
216 case REAL_TYPE:
217 switch (TYPE_PRECISION (type))
218 {
219 case 32: code = 'f'; goto primitive;
220 case 64: code = 'd'; goto primitive;
221 default: goto bad_type;
222 }
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 ();
232 }
233 }
234
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. */
243
244 static GTY(()) tree compression_table;
245 static int compression_next;
246
247 /* Find a POINTER_TYPE in the compression table. Use a special
248 function to match pointer entries and start from the end */
249
250 static int
find_compression_pointer_match(tree type)251 find_compression_pointer_match (tree type)
252 {
253 int i;
254
255 for (i = compression_next-1; i >= 0; i--)
256 if (entry_match_pointer_p (type, i))
257 return i;
258 return -1;
259 }
260
261 /* Already recorder arrays are handled like pointer as they're always
262 associated with it. */
263
264 static int
find_compression_array_match(tree type)265 find_compression_array_match (tree type)
266 {
267 return find_compression_pointer_match (type);
268 }
269
270 /* Match the table of type against STRING. */
271
272 static int
find_compression_array_template_match(tree string)273 find_compression_array_template_match (tree string)
274 {
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;
280 }
281
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. */
286
287 static int
find_compression_record_match(tree type,tree * next_current)288 find_compression_record_match (tree type, tree *next_current)
289 {
290 int i, match = -1;
291 tree current, saved_current = NULL_TREE;
292
293 current = TYPE_PACKAGE_LIST (type);
294
295 for (i = 0; i < compression_next; i++)
296 {
297 tree compression_entry = TREE_VEC_ELT (compression_table, i);
298 if (current && compression_entry == TREE_PURPOSE (current))
299 {
300 match = i;
301 saved_current = current;
302 current = TREE_CHAIN (current);
303 }
304 else
305 /* We don't want to match an element that appears in the middle
306 of a package name, so skip forward to the next complete type name.
307 IDENTIFIER_NODEs (except for a "6JArray") are partial package
308 names while RECORD_TYPEs represent complete type names. */
309 while (i < compression_next
310 && TREE_CODE (compression_entry) == IDENTIFIER_NODE
311 && compression_entry != atms)
312 compression_entry = TREE_VEC_ELT (compression_table, ++i);
313 }
314
315 if (!next_current)
316 return match;
317
318 /* If we have a match, set next_current to the item next to the last
319 matched value. */
320 if (match >= 0)
321 *next_current = TREE_CHAIN (saved_current);
322 /* We had no match: we'll have to start from the beginning. */
323 if (match < 0)
324 *next_current = TYPE_PACKAGE_LIST (type);
325
326 return match;
327 }
328
329 /* Mangle a record type. If a nonzero value is returned, it means
330 that a 'N' was emitted (so that a matching 'E' can be emitted if
331 necessary.) FOR_POINTER indicates that this element is for a pointer
332 symbol, meaning it was preceded by a 'P'. */
333
334 static int
mangle_record_type(tree type,int for_pointer)335 mangle_record_type (tree type, int for_pointer)
336 {
337 tree current;
338 int match;
339 int nadded_p = 0;
340 int qualified;
341
342 /* Does this name have a package qualifier? */
343 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
344
345 #define ADD_N() \
346 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
347
348 if (TREE_CODE (type) != RECORD_TYPE)
349 abort ();
350
351 if (!TYPE_PACKAGE_LIST (type))
352 set_type_package_list (type);
353
354 match = find_compression_record_match (type, ¤t);
355 if (match >= 0)
356 {
357 /* If we had a pointer, and there's more, we need to emit
358 'N' after 'P' (for_pointer tells us we already emitted it.) */
359 if (for_pointer && current)
360 ADD_N();
361 emit_compression_string (match);
362 }
363 while (current)
364 {
365 /* Add the new type to the table */
366 compression_table_add (TREE_PURPOSE (current));
367 /* Add 'N' if we never got a chance to, but only if we have a qualified
368 name. For non-pointer elements, the name is always qualified. */
369 if ((qualified || !for_pointer) && !nadded_p)
370 ADD_N();
371 /* Use the bare type name for the mangle. */
372 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
373 IDENTIFIER_LENGTH (TREE_VALUE (current)));
374 current = TREE_CHAIN (current);
375 }
376 return nadded_p;
377 #undef ADD_N
378 }
379
380 /* Mangle a pointer type. There are two cases: the pointer is already
381 in the compression table: the compression is emitted sans 'P'
382 indicator. Otherwise, a 'P' is emitted and, depending on the type,
383 a partial compression or/plus the rest of the mangling. */
384
385 static void
mangle_pointer_type(tree type)386 mangle_pointer_type (tree type)
387 {
388 int match;
389 tree pointer_type;
390
391 /* Search for the type already in the compression table */
392 if ((match = find_compression_pointer_match (type)) >= 0)
393 {
394 emit_compression_string (match);
395 return;
396 }
397
398 /* This didn't work. We start by mangling the pointed-to type */
399 pointer_type = type;
400 type = TREE_TYPE (type);
401 if (TREE_CODE (type) != RECORD_TYPE)
402 abort ();
403
404 obstack_1grow (mangle_obstack, 'P');
405 if (mangle_record_type (type, /* for_pointer = */ 1))
406 obstack_1grow (mangle_obstack, 'E');
407
408 /* Don't forget to insert the pointer type in the table */
409 compression_table_add (pointer_type);
410 }
411
412 /* Mangle an array type. Search for an easy solution first, then go
413 through the process of finding out whether the bare array type or even
414 the template indicator were already used and compressed appropriately.
415 It handles pointers. */
416
417 static void
mangle_array_type(tree p_type)418 mangle_array_type (tree p_type)
419 {
420 tree type, elt_type;
421 int match;
422
423 type = TREE_TYPE (p_type);
424 if (!type)
425 abort ();
426
427 elt_type = TYPE_ARRAY_ELEMENT (type);
428
429 /* We cache a bit of the Jarray <> mangle. */
430 if (!atms)
431 {
432 atms = get_identifier ("6JArray");
433 }
434
435 /* Maybe we have what we're looking for in the compression table. */
436 if ((match = find_compression_array_match (p_type)) >= 0)
437 {
438 emit_compression_string (match);
439 return;
440 }
441
442 /* We know for a fact that all arrays are pointers */
443 obstack_1grow (mangle_obstack, 'P');
444 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
445 if ((match = find_compression_record_match (type, NULL)) > 0)
446 {
447 emit_compression_string (match);
448 return;
449 }
450
451 /* Maybe we already have just JArray somewhere */
452 if ((match = find_compression_array_template_match (atms)) > 0)
453 emit_compression_string (match);
454 else
455 {
456 /* Start the template mangled name */
457 obstack_grow (mangle_obstack,
458 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
459 /* Insert in the compression table */
460 compression_table_add (atms);
461 }
462
463 /* Mangle Jarray <elt_type> */
464 obstack_1grow (mangle_obstack, 'I');
465 mangle_type (elt_type);
466 obstack_1grow (mangle_obstack, 'E');
467
468 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
469 compression_table_add (type);
470 compression_table_add (p_type);
471 }
472
473 /* Write a substitution string for entry I. Substitution string starts a
474 -1 (encoded S_.) The base is 36, and the code shamelessly taken from
475 cp/mangle.c. */
476
477 static void
emit_compression_string(int i)478 emit_compression_string (int i)
479 {
480 i -= 1; /* Adjust */
481 obstack_1grow (mangle_obstack, 'S');
482 if (i >= 0)
483 {
484 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
485 unsigned HOST_WIDE_INT n;
486 unsigned HOST_WIDE_INT m=1;
487 /* How many digits for I in base 36? */
488 for (n = i; n >= 36; n /= 36, m *=36);
489 /* Write the digits out */
490 while (m > 0)
491 {
492 int digit = i / m;
493 obstack_1grow (mangle_obstack, digits [digit]);
494 i -= digit * m;
495 m /= 36;
496 }
497 }
498 obstack_1grow (mangle_obstack, '_');
499 }
500
501 /* If search the compression table at index I for a pointer type
502 equivalent to TYPE (meaning that after all the indirection, which
503 might all be unique, we find the same RECORD_TYPE.) */
504
505 static int
entry_match_pointer_p(tree type,int i)506 entry_match_pointer_p (tree type, int i)
507 {
508 tree t = TREE_VEC_ELT (compression_table, i);
509
510 while (TREE_CODE (type) == POINTER_TYPE
511 && TREE_CODE (t) == POINTER_TYPE)
512 {
513 t = TREE_TYPE (t);
514 type = TREE_TYPE (type);
515 }
516 return (TREE_CODE (type) == RECORD_TYPE
517 && TREE_CODE (t) == RECORD_TYPE
518 && t == type);
519 }
520
521 /* Go through all qualification of type and build a list of list node
522 elements containings as a purpose what should be used for a match and
523 inserted in the compression table; and as it value the raw name of the
524 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
525
526 static void
set_type_package_list(tree type)527 set_type_package_list (tree type)
528 {
529 int i;
530 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
531 char *ptr;
532 int qualifications;
533 tree list = NULL_TREE, elt;
534
535 for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
536 if (*ptr == '.')
537 qualifications += 1;
538
539 for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
540 {
541 if (ptr [0] == '.')
542 {
543 char c;
544 tree identifier;
545
546 /* Can't use an obstack, we're already using it to
547 accumulate the mangling. */
548 c = ptr [0];
549 ptr [0] = '\0';
550 identifier = get_identifier (type_string);
551 ptr [0] = c;
552 elt = build_tree_list (identifier, identifier);
553 TREE_CHAIN (elt) = list;
554 list = elt;
555 type_string = ptr+1;
556 i += 1;
557 }
558 }
559
560 elt = build_tree_list (type, get_identifier (type_string));
561 TREE_CHAIN (elt) = list;
562 list = elt;
563 TYPE_PACKAGE_LIST (type) = nreverse (list);
564 }
565
566 /* Add TYPE as the last element of the compression table. Resize the
567 compression table if necessary. */
568
569 static void
compression_table_add(tree type)570 compression_table_add (tree type)
571 {
572 if (compression_next == TREE_VEC_LENGTH (compression_table))
573 {
574 tree new = make_tree_vec (2*compression_next);
575 int i;
576
577 for (i = 0; i < compression_next; i++)
578 TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
579
580 compression_table = new;
581 }
582 TREE_VEC_ELT (compression_table, compression_next++) = type;
583 }
584
585 /* Mangling initialization routine. */
586
587 static void
init_mangling(struct obstack * obstack)588 init_mangling (struct obstack *obstack)
589 {
590 mangle_obstack = obstack;
591 if (!compression_table)
592 compression_table = make_tree_vec (10);
593 else
594 /* Mangling already in progress. */
595 abort ();
596
597 /* Mangled name are to be suffixed */
598 obstack_grow (mangle_obstack, "_Z", 2);
599 }
600
601 /* Mangling finalization routine. The mangled name is returned as a
602 IDENTIFIER_NODE. */
603
604 static tree
finish_mangling(void)605 finish_mangling (void)
606 {
607 tree result;
608
609 if (!compression_table)
610 /* Mangling already finished. */
611 abort ();
612
613 compression_table = NULL_TREE;
614 compression_next = 0;
615 obstack_1grow (mangle_obstack, '\0');
616 result = get_identifier (obstack_base (mangle_obstack));
617 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
618 #if 0
619 printf ("// %s\n", IDENTIFIER_POINTER (result));
620 #endif
621 return result;
622 }
623
624 #include "gt-java-mangle.h"
625