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