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)
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> */
32 #include "java-tree.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
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
71 java_mangle_decl (obstack
, decl
)
72 struct obstack
*obstack
;
75 init_mangling (obstack
);
76 switch (TREE_CODE (decl
))
79 mangle_field_decl (decl
);
82 mangle_method_decl (decl
);
85 internal_error ("can't mangle %s", tree_code_name
[TREE_CODE (decl
)]);
87 return finish_mangling ();
91 java_mangle_class_field (obstack
, type
)
92 struct obstack
*obstack
;
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 ();
103 java_mangle_vtable (obstack
, type
)
104 struct obstack
*obstack
;
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 */
119 mangle_field_decl (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
136 mangle_method_decl (mdecl
)
139 tree method_name
= DECL_NAME (mdecl
);
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 are two cases:
146 - mdecl is a constructor, use `C1' for its name, (denotes a
147 complete object constructor.)
148 - mdecl is not a constructor, standard mangling is performed.
149 We terminate the mangled function name with a `E'. */
150 if (ID_INIT_P (method_name
))
151 obstack_grow (mangle_obstack
, "C1", 2);
153 mangle_member_name (method_name
);
154 obstack_1grow (mangle_obstack
, 'E');
156 /* We mangled type.methodName. Now onto the arguments. */
157 arglist
= TYPE_ARG_TYPES (TREE_TYPE (mdecl
));
158 if (TREE_CODE (TREE_TYPE (mdecl
)) == METHOD_TYPE
)
159 arglist
= TREE_CHAIN (arglist
);
161 /* No arguments is easy. We shortcut it. */
162 if (arglist
== end_params_node
)
163 obstack_1grow (mangle_obstack
, 'v');
167 for (arg
= arglist
; arg
!= end_params_node
; arg
= TREE_CHAIN (arg
))
168 mangle_type (TREE_VALUE (arg
));
172 /* This mangles a member name, like a function name or a field
173 name. Handle cases were `name' is a C++ keyword. Return a non zero
174 value if unicode encoding was required. */
177 mangle_member_name (name
)
180 append_gpp_mangled_name (IDENTIFIER_POINTER (name
),
181 IDENTIFIER_LENGTH (name
));
183 /* If NAME happens to be a C++ keyword, add `$'. */
184 if (cxx_keyword_p (IDENTIFIER_POINTER (name
), IDENTIFIER_LENGTH (name
)))
185 obstack_1grow (mangle_obstack
, '$');
188 /* Append the mangled name of TYPE onto OBSTACK. */
194 switch (TREE_CODE (type
))
197 case BOOLEAN_TYPE
: code
= 'b'; goto primitive
;
198 case CHAR_TYPE
: code
= 'w'; goto primitive
;
199 case VOID_TYPE
: code
= 'v'; goto primitive
;
201 /* Get the original type instead of the arguments promoted type.
202 Avoid symbol name clashes. Should call a function to do that.
204 if (type
== promoted_short_type_node
)
205 type
= short_type_node
;
206 if (type
== promoted_byte_type_node
)
207 type
= byte_type_node
;
208 switch (TYPE_PRECISION (type
))
210 case 8: code
= 'c'; goto primitive
;
211 case 16: code
= 's'; goto primitive
;
212 case 32: code
= 'i'; goto primitive
;
213 case 64: code
= 'x'; goto primitive
;
214 default: goto bad_type
;
217 obstack_1grow (mangle_obstack
, code
);
221 switch (TYPE_PRECISION (type
))
223 case 32: code
= 'f'; goto primitive
;
224 case 64: code
= 'd'; goto primitive
;
225 default: goto bad_type
;
228 if (TYPE_ARRAY_P (TREE_TYPE (type
)))
229 mangle_array_type (type
);
231 mangle_pointer_type (type
);
239 /* The compression table is a vector that keeps track of things we've
240 already seen, so they can be reused. For example, java.lang.Object
241 would generate three entries: two package names and a type. If
242 java.lang.String is presented next, the java.lang will be matched
243 against the first two entries (and kept for compression as S_0), and
244 type String would be added to the table. See mangle_record_type.
245 COMPRESSION_NEXT is the index to the location of the next insertion
248 static tree compression_table
;
249 static int compression_next
;
251 /* Find a POINTER_TYPE in the compression table. Use a special
252 function to match pointer entries and start from the end */
255 find_compression_pointer_match (type
)
260 for (i
= compression_next
-1; i
>= 0; i
--)
261 if (entry_match_pointer_p (type
, i
))
266 /* Already recorder arrays are handled like pointer as they're always
267 associated with it. */
270 find_compression_array_match (type
)
273 return find_compression_pointer_match (type
);
276 /* Match the table of type against STRING. */
279 find_compression_array_template_match (string
)
283 for (i
= 0; i
< compression_next
; i
++)
284 if (TREE_VEC_ELT (compression_table
, i
) == string
)
289 /* We go through the compression table and try to find a complete or
290 partial match. The function returns the compression table entry
291 that (evenutally partially) matches TYPE. *NEXT_CURRENT can be set
292 to the rest of TYPE to be mangled. */
295 find_compression_record_match (type
, next_current
)
300 tree current
, saved_current
= NULL_TREE
;
302 /* Search from the beginning for something that matches TYPE, even
304 for (current
= TYPE_PACKAGE_LIST (type
), i
= 0, match
= -1; current
;
305 current
= TREE_CHAIN (current
))
308 for (j
= i
; j
< compression_next
; j
++)
309 if (TREE_VEC_ELT (compression_table
, j
) == TREE_PURPOSE (current
))
312 saved_current
= current
;
318 /* We don't want to match an element that appears in the middle
319 of a package name, so skip forward to the next complete type name.
320 IDENTIFIER_NODEs are partial package names while RECORD_TYPEs
321 represent complete type names. */
322 while (j
< compression_next
323 && TREE_CODE (TREE_VEC_ELT (compression_table
, j
)) ==
332 /* If we have a match, set next_current to the item next to the last
335 *next_current
= TREE_CHAIN (saved_current
);
336 /* We had no match: we'll have to start from the beginning. */
338 *next_current
= TYPE_PACKAGE_LIST (type
);
343 /* Mangle a record type. If a non zero value is returned, it means
344 that a 'N' was emitted (so that a matching 'E' can be emitted if
345 necessary.) FOR_POINTER indicates that this element is for a pointer
346 symbol, meaning it was preceded by a 'P'. */
349 mangle_record_type (type
, for_pointer
)
358 /* Does this name have a package qualifier? */
359 qualified
= QUALIFIED_P (DECL_NAME (TYPE_NAME (type
)));
362 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
364 if (TREE_CODE (type
) != RECORD_TYPE
)
367 if (!TYPE_PACKAGE_LIST (type
))
368 set_type_package_list (type
);
370 match
= find_compression_record_match (type
, ¤t
);
373 /* If we had a pointer, and there's more, we need to emit
374 'N' after 'P' (for_pointer tells us we already emitted it.) */
375 if (for_pointer
&& current
)
377 emit_compression_string (match
);
381 /* Add the new type to the table */
382 compression_table_add (TREE_PURPOSE (current
));
383 /* Add 'N' if we never got a chance to, but only if we have a qualified
384 name. For non-pointer elements, the name is always qualified. */
385 if ((qualified
|| !for_pointer
) && !nadded_p
)
387 /* Use the bare type name for the mangle. */
388 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current
)),
389 IDENTIFIER_LENGTH (TREE_VALUE (current
)));
390 current
= TREE_CHAIN (current
);
396 /* Mangle a pointer type. There are two cases: the pointer is already
397 in the compression table: the compression is emited sans 'P'
398 indicator. Otherwise, a 'P' is emitted and, depending on the type,
399 a partial compression or/plus the rest of the mangling. */
402 mangle_pointer_type (type
)
408 /* Search for the type already in the compression table */
409 if ((match
= find_compression_pointer_match (type
)) >= 0)
411 emit_compression_string (match
);
415 /* This didn't work. We start by mangling the pointed-to type */
417 type
= TREE_TYPE (type
);
418 if (TREE_CODE (type
) != RECORD_TYPE
)
421 obstack_1grow (mangle_obstack
, 'P');
422 if (mangle_record_type (type
, /* for_pointer = */ 1))
423 obstack_1grow (mangle_obstack
, 'E');
425 /* Don't forget to insert the pointer type in the table */
426 compression_table_add (pointer_type
);
429 /* Mangle an array type. Search for an easy solution first, then go
430 through the process of finding out whether the bare array type or even
431 the template indicator where already used an compress appropriately.
432 It handles pointers. */
435 mangle_array_type (p_type
)
438 /* atms: array template mangled string. */
439 static tree atms
= NULL_TREE
;
443 type
= TREE_TYPE (p_type
);
447 elt_type
= TYPE_ARRAY_ELEMENT (type
);
449 /* We cache a bit of the Jarray <> mangle. */
452 atms
= get_identifier ("6JArray");
453 ggc_add_tree_root (&atms
, 1);
456 /* Maybe we have what we're looking in the compression table. */
457 if ((match
= find_compression_array_match (p_type
)) >= 0)
459 emit_compression_string (match
);
463 /* We know for a fact that all arrays are pointers */
464 obstack_1grow (mangle_obstack
, 'P');
465 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
466 if ((match
= find_compression_record_match (type
, NULL
)) > 0)
468 emit_compression_string (match
);
472 /* Maybe we already have just JArray somewhere */
473 if ((match
= find_compression_array_template_match (atms
)) > 0)
474 emit_compression_string (match
);
477 /* Start the template mangled name */
478 obstack_grow (mangle_obstack
,
479 IDENTIFIER_POINTER (atms
), IDENTIFIER_LENGTH (atms
));
480 /* Insert in the compression table */
481 compression_table_add (atms
);
484 /* Mangle Jarray <elt_type> */
485 obstack_1grow (mangle_obstack
, 'I');
486 mangle_type (elt_type
);
487 obstack_1grow (mangle_obstack
, 'E');
489 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
490 compression_table_add (type
);
491 compression_table_add (p_type
);
494 /* Write a substition string for entry I. Substitution string starts a
495 -1 (encoded S_.) The base is 36, and the code shamlessly taken from
499 emit_compression_string (int i
)
502 obstack_1grow (mangle_obstack
, 'S');
505 static const char digits
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
506 unsigned HOST_WIDE_INT n
;
507 unsigned HOST_WIDE_INT m
=1;
508 /* How many digits for I in base 36? */
509 for (n
= i
; n
>= 36; n
/= 36, m
*=36);
510 /* Write the digits out */
514 obstack_1grow (mangle_obstack
, digits
[digit
]);
519 obstack_1grow (mangle_obstack
, '_');
522 /* If search the compression table at index I for a pointer type
523 equivalent to TYPE (meaning that after all the indirection, which
524 might all be unique, we find the same RECORD_TYPE.) */
527 entry_match_pointer_p (type
, i
)
531 tree t
= TREE_VEC_ELT (compression_table
, i
);
533 while (TREE_CODE (type
) == POINTER_TYPE
534 && TREE_CODE (t
) == POINTER_TYPE
)
537 type
= TREE_TYPE (type
);
539 return (TREE_CODE (type
) == RECORD_TYPE
540 && TREE_CODE (t
) == RECORD_TYPE
544 /* Go through all qualification of type and build a list of list node
545 elements containings as a purpose what should be used for a match and
546 inserted in the compression table; and as it value the raw name of the
547 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
550 set_type_package_list (type
)
554 const char *type_string
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type
)));
557 tree list
= NULL_TREE
, elt
;
559 for (ptr
= (char *)type_string
, qualifications
= 0; *ptr
; ptr
++)
563 for (ptr
= (char *)type_string
, i
= 0; i
< qualifications
; ptr
++)
570 /* Can't use an obstack, we're already using it to
571 accumulate the mangling. */
574 identifier
= get_identifier (type_string
);
576 elt
= build_tree_list (identifier
, identifier
);
577 TREE_CHAIN (elt
) = list
;
584 elt
= build_tree_list (type
, get_identifier (type_string
));
585 TREE_CHAIN (elt
) = list
;
587 TYPE_PACKAGE_LIST (type
) = nreverse (list
);
590 /* Add TYPE as the last element of the compression table. Resize the
591 compression table if necessary. */
594 compression_table_add (type
)
597 if (compression_next
== TREE_VEC_LENGTH (compression_table
))
599 tree
new = make_tree_vec (2*compression_next
);
602 for (i
= 0; i
< compression_next
; i
++)
603 TREE_VEC_ELT (new, i
) = TREE_VEC_ELT (compression_table
, i
);
605 ggc_del_root (&compression_table
);
606 compression_table
= new;
607 ggc_add_tree_root (&compression_table
, 1);
609 TREE_VEC_ELT (compression_table
, compression_next
++) = type
;
612 /* Mangling initialization routine. */
615 init_mangling (obstack
)
616 struct obstack
*obstack
;
618 mangle_obstack
= obstack
;
619 if (!compression_table
)
620 compression_table
= make_tree_vec (10);
622 /* Mangling already in progress. */
625 /* Mangled name are to be suffixed */
626 obstack_grow (mangle_obstack
, "_Z", 2);
628 /* Register the compression table with the GC */
629 ggc_add_tree_root (&compression_table
, 1);
632 /* Mangling finalization routine. The mangled name is returned as a
640 if (!compression_table
)
641 /* Mangling already finished. */
644 ggc_del_root (&compression_table
);
645 compression_table
= NULL_TREE
;
646 compression_next
= 0;
647 obstack_1grow (mangle_obstack
, '\0');
648 result
= get_identifier (obstack_base (mangle_obstack
));
649 obstack_free (mangle_obstack
, obstack_base (mangle_obstack
));
651 printf ("// %s\n", IDENTIFIER_POINTER (result
));