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> */
30 #include "coretypes.h"
34 #include "java-tree.h"
40 static void mangle_field_decl
PARAMS ((tree
));
41 static void mangle_method_decl
PARAMS ((tree
));
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));
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
));
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));
57 static void init_mangling
PARAMS ((struct obstack
*));
58 static tree finish_mangling
PARAMS ((void));
59 static void compression_table_add
PARAMS ((tree
));
61 static void mangle_member_name
PARAMS ((tree
));
63 /* We use an incoming obstack, always to be provided to the interface
65 struct obstack
*mangle_obstack
;
66 #define MANGLE_RAW_STRING(S) \
67 obstack_grow (mangle_obstack, (S), sizeof (S)-1)
69 /* This is the mangling interface: a decl, a class field (.class) and
73 java_mangle_decl (obstack
, decl
)
74 struct obstack
*obstack
;
77 init_mangling (obstack
);
78 switch (TREE_CODE (decl
))
81 mangle_field_decl (decl
);
84 mangle_method_decl (decl
);
87 internal_error ("can't mangle %s", tree_code_name
[TREE_CODE (decl
)]);
89 return finish_mangling ();
93 java_mangle_class_field (obstack
, type
)
94 struct obstack
*obstack
;
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 ();
105 java_mangle_vtable (obstack
, type
)
106 struct obstack
*obstack
;
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 ();
116 /* Beginning of the helper functions */
118 /* This mangles a field decl */
121 mangle_field_decl (decl
)
124 /* Mangle the name of the this the field belongs to */
125 mangle_record_type (DECL_CONTEXT (decl
), /* for_pointer = */ 0);
127 /* Mangle the name of the field */
128 mangle_member_name (DECL_NAME (decl
));
130 /* Terminate the mangled name */
131 obstack_1grow (mangle_obstack
, 'E');
134 /* This mangles a method decl, first mangling its name and then all
138 mangle_method_decl (mdecl
)
141 tree method_name
= DECL_NAME (mdecl
);
144 /* Mangle the name of the type that contains mdecl */
145 mangle_record_type (DECL_CONTEXT (mdecl
), /* for_pointer = */ 0);
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);
155 mangle_member_name (method_name
);
156 obstack_1grow (mangle_obstack
, 'E');
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
);
163 /* No arguments is easy. We shortcut it. */
164 if (arglist
== end_params_node
)
165 obstack_1grow (mangle_obstack
, 'v');
169 for (arg
= arglist
; arg
!= end_params_node
; arg
= TREE_CHAIN (arg
))
170 mangle_type (TREE_VALUE (arg
));
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. */
179 mangle_member_name (name
)
182 append_gpp_mangled_name (IDENTIFIER_POINTER (name
),
183 IDENTIFIER_LENGTH (name
));
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
, '$');
190 /* Append the mangled name of TYPE onto OBSTACK. */
196 switch (TREE_CODE (type
))
199 case BOOLEAN_TYPE
: code
= 'b'; goto primitive
;
200 case CHAR_TYPE
: code
= 'w'; goto primitive
;
201 case VOID_TYPE
: code
= 'v'; goto primitive
;
203 /* Get the original type instead of the arguments promoted type.
204 Avoid symbol name clashes. Should call a function to do that.
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
))
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
;
219 obstack_1grow (mangle_obstack
, code
);
223 switch (TYPE_PRECISION (type
))
225 case 32: code
= 'f'; goto primitive
;
226 case 64: code
= 'd'; goto primitive
;
227 default: goto bad_type
;
230 if (TYPE_ARRAY_P (TREE_TYPE (type
)))
231 mangle_array_type (type
);
233 mangle_pointer_type (type
);
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
250 static GTY(()) tree compression_table
;
251 static int compression_next
;
253 /* Find a POINTER_TYPE in the compression table. Use a special
254 function to match pointer entries and start from the end */
257 find_compression_pointer_match (type
)
262 for (i
= compression_next
-1; i
>= 0; i
--)
263 if (entry_match_pointer_p (type
, i
))
268 /* Already recorder arrays are handled like pointer as they're always
269 associated with it. */
272 find_compression_array_match (type
)
275 return find_compression_pointer_match (type
);
278 /* Match the table of type against STRING. */
281 find_compression_array_template_match (string
)
285 for (i
= 0; i
< compression_next
; i
++)
286 if (TREE_VEC_ELT (compression_table
, i
) == string
)
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. */
297 find_compression_record_match (type
, next_current
)
302 tree current
, saved_current
= NULL_TREE
;
304 /* Search from the beginning for something that matches TYPE, even
306 for (current
= TYPE_PACKAGE_LIST (type
), i
= 0, match
= -1; current
;
307 current
= TREE_CHAIN (current
))
310 for (j
= i
; j
< compression_next
; j
++)
311 if (TREE_VEC_ELT (compression_table
, j
) == TREE_PURPOSE (current
))
314 saved_current
= current
;
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
)) ==
334 /* If we have a match, set next_current to the item next to the last
337 *next_current
= TREE_CHAIN (saved_current
);
338 /* We had no match: we'll have to start from the beginning. */
340 *next_current
= TYPE_PACKAGE_LIST (type
);
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'. */
351 mangle_record_type (type
, for_pointer
)
360 /* Does this name have a package qualifier? */
361 qualified
= QUALIFIED_P (DECL_NAME (TYPE_NAME (type
)));
364 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
366 if (TREE_CODE (type
) != RECORD_TYPE
)
369 if (!TYPE_PACKAGE_LIST (type
))
370 set_type_package_list (type
);
372 match
= find_compression_record_match (type
, ¤t
);
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
)
379 emit_compression_string (match
);
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
)
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
);
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. */
404 mangle_pointer_type (type
)
410 /* Search for the type already in the compression table */
411 if ((match
= find_compression_pointer_match (type
)) >= 0)
413 emit_compression_string (match
);
417 /* This didn't work. We start by mangling the pointed-to type */
419 type
= TREE_TYPE (type
);
420 if (TREE_CODE (type
) != RECORD_TYPE
)
423 obstack_1grow (mangle_obstack
, 'P');
424 if (mangle_record_type (type
, /* for_pointer = */ 1))
425 obstack_1grow (mangle_obstack
, 'E');
427 /* Don't forget to insert the pointer type in the table */
428 compression_table_add (pointer_type
);
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. */
436 /* atms: array template mangled string. */
437 static GTY(()) tree atms
;
439 mangle_array_type (p_type
)
445 type
= TREE_TYPE (p_type
);
449 elt_type
= TYPE_ARRAY_ELEMENT (type
);
451 /* We cache a bit of the Jarray <> mangle. */
454 atms
= get_identifier ("6JArray");
457 /* Maybe we have what we're looking in the compression table. */
458 if ((match
= find_compression_array_match (p_type
)) >= 0)
460 emit_compression_string (match
);
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)
469 emit_compression_string (match
);
473 /* Maybe we already have just JArray somewhere */
474 if ((match
= find_compression_array_template_match (atms
)) > 0)
475 emit_compression_string (match
);
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
);
485 /* Mangle Jarray <elt_type> */
486 obstack_1grow (mangle_obstack
, 'I');
487 mangle_type (elt_type
);
488 obstack_1grow (mangle_obstack
, 'E');
490 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
491 compression_table_add (type
);
492 compression_table_add (p_type
);
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
500 emit_compression_string (int i
)
503 obstack_1grow (mangle_obstack
, 'S');
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 */
515 obstack_1grow (mangle_obstack
, digits
[digit
]);
520 obstack_1grow (mangle_obstack
, '_');
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.) */
528 entry_match_pointer_p (type
, i
)
532 tree t
= TREE_VEC_ELT (compression_table
, i
);
534 while (TREE_CODE (type
) == POINTER_TYPE
535 && TREE_CODE (t
) == POINTER_TYPE
)
538 type
= TREE_TYPE (type
);
540 return (TREE_CODE (type
) == RECORD_TYPE
541 && TREE_CODE (t
) == RECORD_TYPE
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. */
551 set_type_package_list (type
)
555 const char *type_string
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type
)));
558 tree list
= NULL_TREE
, elt
;
560 for (ptr
= (char *)type_string
, qualifications
= 0; *ptr
; ptr
++)
564 for (ptr
= (char *)type_string
, i
= 0; i
< qualifications
; ptr
++)
571 /* Can't use an obstack, we're already using it to
572 accumulate the mangling. */
575 identifier
= get_identifier (type_string
);
577 elt
= build_tree_list (identifier
, identifier
);
578 TREE_CHAIN (elt
) = list
;
585 elt
= build_tree_list (type
, get_identifier (type_string
));
586 TREE_CHAIN (elt
) = list
;
588 TYPE_PACKAGE_LIST (type
) = nreverse (list
);
591 /* Add TYPE as the last element of the compression table. Resize the
592 compression table if necessary. */
595 compression_table_add (type
)
598 if (compression_next
== TREE_VEC_LENGTH (compression_table
))
600 tree
new = make_tree_vec (2*compression_next
);
603 for (i
= 0; i
< compression_next
; i
++)
604 TREE_VEC_ELT (new, i
) = TREE_VEC_ELT (compression_table
, i
);
606 compression_table
= new;
608 TREE_VEC_ELT (compression_table
, compression_next
++) = type
;
611 /* Mangling initialization routine. */
614 init_mangling (obstack
)
615 struct obstack
*obstack
;
617 mangle_obstack
= obstack
;
618 if (!compression_table
)
619 compression_table
= make_tree_vec (10);
621 /* Mangling already in progress. */
624 /* Mangled name are to be suffixed */
625 obstack_grow (mangle_obstack
, "_Z", 2);
628 /* Mangling finalization routine. The mangled name is returned as a
636 if (!compression_table
)
637 /* Mangling already finished. */
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
));
646 printf ("// %s\n", IDENTIFIER_POINTER (result
));
651 #include "gt-java-mangle.h"