]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/java/mangle.c
Merge basic-improvements-branch to trunk
[thirdparty/gcc.git] / gcc / java / mangle.c
CommitLineData
e04a16fb
AG
1/* Functions related to mangling class names for the GNU compiler
2 for the Java(TM) language.
dc08e603 3 Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
e04a16fb
AG
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA.
21
22Java and all Java-based marks are trademarks or registered trademarks
23of Sun Microsystems, Inc. in the United States and other countries.
24The Free Software Foundation is independent of Sun Microsystems, Inc. */
25
26/* Written by Per Bothner <bothner@cygnus.com> */
27
e04a16fb 28#include "config.h"
1f43f4b4 29#include "system.h"
4977bab6
ZW
30#include "coretypes.h"
31#include "tm.h"
e04a16fb 32#include "jcf.h"
4bcde32e
KG
33#include "tree.h"
34#include "java-tree.h"
e04a16fb 35#include "obstack.h"
d4476be2 36#include "toplev.h"
dc08e603
APB
37#include "obstack.h"
38#include "ggc.h"
39
40static void mangle_field_decl PARAMS ((tree));
41static void mangle_method_decl PARAMS ((tree));
42
43static void mangle_type PARAMS ((tree));
44static void mangle_pointer_type PARAMS ((tree));
45static void mangle_array_type PARAMS ((tree));
46static int mangle_record_type PARAMS ((tree, int));
47
48static int find_compression_pointer_match PARAMS ((tree));
49static int find_compression_array_match PARAMS ((tree));
50static int find_compression_record_match PARAMS ((tree, tree *));
51static int find_compression_array_template_match PARAMS ((tree));
52
53static void set_type_package_list PARAMS ((tree));
54static int entry_match_pointer_p PARAMS ((tree, int));
55static void emit_compression_string PARAMS ((int));
56
57static void init_mangling PARAMS ((struct obstack *));
58static tree finish_mangling PARAMS ((void));
59static void compression_table_add PARAMS ((tree));
60
1b43b6be 61static void mangle_member_name PARAMS ((tree));
dc08e603
APB
62
63/* We use an incoming obstack, always to be provided to the interface
64 functions. */
65struct 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
72tree
73java_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:
c725bd79 87 internal_error ("can't mangle %s", tree_code_name [TREE_CODE (decl)]);
dc08e603
APB
88 }
89 return finish_mangling ();
90}
91
92tree
93java_mangle_class_field (obstack, type)
94 struct obstack *obstack;
95 tree type;
96{
97 init_mangling (obstack);
551bf03c 98 mangle_record_type (type, /* for_pointer = */ 0);
dc08e603
APB
99 MANGLE_RAW_STRING ("6class$");
100 obstack_1grow (mangle_obstack, 'E');
101 return finish_mangling ();
102}
103
104tree
105java_mangle_vtable (obstack, type)
106 struct obstack *obstack;
107 tree type;
108{
109 init_mangling (obstack);
110 MANGLE_RAW_STRING ("TV");
551bf03c 111 mangle_record_type (type, /* for_pointer = */ 0);
dc08e603
APB
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
120static void
121mangle_field_decl (decl)
122 tree decl;
123{
dc08e603 124 /* Mangle the name of the this the field belongs to */
551bf03c 125 mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
dc08e603
APB
126
127 /* Mangle the name of the field */
1b43b6be 128 mangle_member_name (DECL_NAME (decl));
dc08e603
APB
129
130 /* Terminate the mangled name */
131 obstack_1grow (mangle_obstack, 'E');
dc08e603
APB
132}
133
134/* This mangles a method decl, first mangling its name and then all
135 its arguments. */
136
137static void
138mangle_method_decl (mdecl)
139 tree mdecl;
140{
141 tree method_name = DECL_NAME (mdecl);
142 tree arglist;
dc08e603
APB
143
144 /* Mangle the name of the type that contains mdecl */
551bf03c 145 mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
dc08e603 146
2c5187c5 147 /* Mangle the function name. There are two cases:
dc08e603
APB
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))
2c5187c5 153 obstack_grow (mangle_obstack, "C1", 2);
dc08e603 154 else
1b43b6be 155 mangle_member_name (method_name);
dc08e603
APB
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 }
dc08e603
APB
172}
173
174/* This mangles a member name, like a function name or a field
ee142fe7 175 name. Handle cases were `name' is a C++ keyword. Return a nonzero
dc08e603
APB
176 value if unicode encoding was required. */
177
1b43b6be 178static void
dc08e603
APB
179mangle_member_name (name)
180 tree name;
181{
1b43b6be
APB
182 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
183 IDENTIFIER_LENGTH (name));
dc08e603 184
de4984af 185 /* If NAME happens to be a C++ keyword, add `$'. */
dc08e603 186 if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
de4984af 187 obstack_1grow (mangle_obstack, '$');
e04a16fb
AG
188}
189
dc08e603 190/* Append the mangled name of TYPE onto OBSTACK. */
e04a16fb 191
dc08e603
APB
192static void
193mangle_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:
400500c4 237 abort ();
dc08e603
APB
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
98f705b9 243 would generate three entries: two package names and a type. If
dc08e603
APB
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
e2500fed 250static GTY(()) tree compression_table;
dc08e603
APB
251static 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
256static int
257find_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
271static int
272find_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
280static int
281find_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
296static int
297find_compression_record_match (type, next_current)
298 tree type;
299 tree *next_current;
e04a16fb 300{
dc08e603 301 int i, match;
962584ea 302 tree current, saved_current = NULL_TREE;
e04a16fb 303
dc08e603
APB
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))
e04a16fb 308 {
dc08e603
APB
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;
2b472f91 315 i++;
dc08e603
APB
316 break;
317 }
2b472f91
BM
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 }
dc08e603
APB
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
ee142fe7 345/* Mangle a record type. If a nonzero value is returned, it means
dc08e603 346 that a 'N' was emitted (so that a matching 'E' can be emitted if
551bf03c
BM
347 necessary.) FOR_POINTER indicates that this element is for a pointer
348 symbol, meaning it was preceded by a 'P'. */
dc08e603
APB
349
350static int
551bf03c 351mangle_record_type (type, for_pointer)
dc08e603 352 tree type;
551bf03c 353 int for_pointer;
dc08e603
APB
354{
355 tree current;
356 int match;
357 int nadded_p = 0;
551bf03c
BM
358 int qualified;
359
360 /* Does this name have a package qualifier? */
361 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
dc08e603
APB
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)
400500c4 367 abort ();
dc08e603
APB
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
551bf03c
BM
376 'N' after 'P' (for_pointer tells us we already emitted it.) */
377 if (for_pointer && current)
dc08e603
APB
378 ADD_N();
379 emit_compression_string (match);
e04a16fb 380 }
dc08e603 381 while (current)
e04a16fb 382 {
dc08e603
APB
383 /* Add the new type to the table */
384 compression_table_add (TREE_PURPOSE (current));
551bf03c
BM
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)
dc08e603
APB
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
403static void
404mangle_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;
e04a16fb 415 }
dc08e603
APB
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)
400500c4 421 abort ();
dc08e603
APB
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
e2500fed
GK
436/* atms: array template mangled string. */
437static GTY(()) tree atms;
dc08e603
APB
438static void
439mangle_array_type (p_type)
440 tree p_type;
441{
dc08e603
APB
442 tree type, elt_type;
443 int match;
444
445 type = TREE_TYPE (p_type);
446 if (!type)
400500c4
RK
447 abort ();
448
dc08e603
APB
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");
dc08e603
APB
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
e04a16fb 477 {
dc08e603
APB
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
499static void
500emit_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)
e04a16fb 513 {
dc08e603
APB
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
527static int
528entry_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
550static void
551set_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;
e04a16fb
AG
582 }
583 }
dc08e603
APB
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
594static void
595compression_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
dc08e603 606 compression_table = new;
dc08e603
APB
607 }
608 TREE_VEC_ELT (compression_table, compression_next++) = type;
609}
610
611/* Mangling initialization routine. */
612
613static void
614init_mangling (obstack)
615 struct obstack *obstack;
616{
617 mangle_obstack = obstack;
618 if (!compression_table)
619 compression_table = make_tree_vec (10);
620 else
400500c4
RK
621 /* Mangling already in progress. */
622 abort ();
dc08e603
APB
623
624 /* Mangled name are to be suffixed */
625 obstack_grow (mangle_obstack, "_Z", 2);
dc08e603
APB
626}
627
628/* Mangling finalization routine. The mangled name is returned as a
629 IDENTIFIER_NODE. */
630
631static tree
632finish_mangling ()
633{
634 tree result;
635
636 if (!compression_table)
400500c4
RK
637 /* Mangling already finished. */
638 abort ();
dc08e603 639
dc08e603
APB
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;
e04a16fb 649}
e2500fed
GK
650
651#include "gt-java-mangle.h"