ifcvt.c (noce_try_addcc): Do not call emit_conditional_add with weird operands.
[official-gcc.git] / gcc / java / mangle.c
blob9a6b80217ede19ae6f640db89acd495c15b81843
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.
6 This file is part of GCC.
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.
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.
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.
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. */
27 /* Written by Per Bothner <bothner@cygnus.com> */
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"
41 static void mangle_field_decl (tree);
42 static void mangle_method_decl (tree);
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);
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);
54 static void set_type_package_list (tree);
55 static int entry_match_pointer_p (tree, int);
56 static void emit_compression_string (int);
58 static void init_mangling (struct obstack *);
59 static tree finish_mangling (void);
60 static void compression_table_add (tree);
62 static void mangle_member_name (tree);
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)
70 /* This is the mangling interface: a decl, a class field (.class) and
71 the vtable. */
73 tree
74 java_mangle_decl (obstack, decl)
75 struct obstack *obstack;
76 tree decl;
78 init_mangling (obstack);
79 switch (TREE_CODE (decl))
81 case VAR_DECL:
82 mangle_field_decl (decl);
83 break;
84 case FUNCTION_DECL:
85 mangle_method_decl (decl);
86 break;
87 default:
88 internal_error ("can't mangle %s", tree_code_name [TREE_CODE (decl)]);
90 return finish_mangling ();
93 tree
94 java_mangle_class_field (obstack, type)
95 struct obstack *obstack;
96 tree type;
98 init_mangling (obstack);
99 mangle_record_type (type, /* for_pointer = */ 0);
100 MANGLE_RAW_STRING ("6class$");
101 obstack_1grow (mangle_obstack, 'E');
102 return finish_mangling ();
105 tree
106 java_mangle_vtable (obstack, type)
107 struct obstack *obstack;
108 tree type;
110 init_mangling (obstack);
111 MANGLE_RAW_STRING ("TV");
112 mangle_record_type (type, /* for_pointer = */ 0);
113 obstack_1grow (mangle_obstack, 'E');
114 return finish_mangling ();
117 /* Beginning of the helper functions */
119 /* This mangles a field decl */
121 static void
122 mangle_field_decl (decl)
123 tree decl;
125 /* Mangle the name of the this the field belongs to */
126 mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
128 /* Mangle the name of the field */
129 mangle_member_name (DECL_NAME (decl));
131 /* Terminate the mangled name */
132 obstack_1grow (mangle_obstack, 'E');
135 /* This mangles a method decl, first mangling its name and then all
136 its arguments. */
138 static void
139 mangle_method_decl (mdecl)
140 tree mdecl;
142 tree method_name = DECL_NAME (mdecl);
143 tree arglist;
145 /* Mangle the name of the type that contains mdecl */
146 mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
148 /* Mangle the function name. There are two cases:
149 - mdecl is a constructor, use `C1' for its name, (denotes a
150 complete object constructor.)
151 - mdecl is not a constructor, standard mangling is performed.
152 We terminate the mangled function name with a `E'. */
153 if (ID_INIT_P (method_name))
154 obstack_grow (mangle_obstack, "C1", 2);
155 else
156 mangle_member_name (method_name);
157 obstack_1grow (mangle_obstack, 'E');
159 /* We mangled type.methodName. Now onto the arguments. */
160 arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
161 if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
162 arglist = TREE_CHAIN (arglist);
164 /* No arguments is easy. We shortcut it. */
165 if (arglist == end_params_node)
166 obstack_1grow (mangle_obstack, 'v');
167 else
169 tree arg;
170 for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg))
171 mangle_type (TREE_VALUE (arg));
175 /* This mangles a member name, like a function name or a field
176 name. Handle cases were `name' is a C++ keyword. Return a nonzero
177 value if unicode encoding was required. */
179 static void
180 mangle_member_name (name)
181 tree name;
183 append_gpp_mangled_name (IDENTIFIER_POINTER (name),
184 IDENTIFIER_LENGTH (name));
186 /* If NAME happens to be a C++ keyword, add `$'. */
187 if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
188 obstack_1grow (mangle_obstack, '$');
191 /* Append the mangled name of TYPE onto OBSTACK. */
193 static void
194 mangle_type (type)
195 tree type;
197 switch (TREE_CODE (type))
199 char code;
200 case BOOLEAN_TYPE: code = 'b'; goto primitive;
201 case CHAR_TYPE: code = 'w'; goto primitive;
202 case VOID_TYPE: code = 'v'; goto primitive;
203 case INTEGER_TYPE:
204 /* Get the original type instead of the arguments promoted type.
205 Avoid symbol name clashes. Should call a function to do that.
206 FIXME. */
207 if (type == promoted_short_type_node)
208 type = short_type_node;
209 if (type == promoted_byte_type_node)
210 type = byte_type_node;
211 switch (TYPE_PRECISION (type))
213 case 8: code = 'c'; goto primitive;
214 case 16: code = 's'; goto primitive;
215 case 32: code = 'i'; goto primitive;
216 case 64: code = 'x'; goto primitive;
217 default: goto bad_type;
219 primitive:
220 obstack_1grow (mangle_obstack, code);
221 break;
223 case REAL_TYPE:
224 switch (TYPE_PRECISION (type))
226 case 32: code = 'f'; goto primitive;
227 case 64: code = 'd'; goto primitive;
228 default: goto bad_type;
230 case POINTER_TYPE:
231 if (TYPE_ARRAY_P (TREE_TYPE (type)))
232 mangle_array_type (type);
233 else
234 mangle_pointer_type (type);
235 break;
236 bad_type:
237 default:
238 abort ();
242 /* The compression table is a vector that keeps track of things we've
243 already seen, so they can be reused. For example, java.lang.Object
244 would generate three entries: two package names and a type. If
245 java.lang.String is presented next, the java.lang will be matched
246 against the first two entries (and kept for compression as S_0), and
247 type String would be added to the table. See mangle_record_type.
248 COMPRESSION_NEXT is the index to the location of the next insertion
249 of an element. */
251 static GTY(()) tree compression_table;
252 static int compression_next;
254 /* Find a POINTER_TYPE in the compression table. Use a special
255 function to match pointer entries and start from the end */
257 static int
258 find_compression_pointer_match (type)
259 tree type;
261 int i;
263 for (i = compression_next-1; i >= 0; i--)
264 if (entry_match_pointer_p (type, i))
265 return i;
266 return -1;
269 /* Already recorder arrays are handled like pointer as they're always
270 associated with it. */
272 static int
273 find_compression_array_match (type)
274 tree type;
276 return find_compression_pointer_match (type);
279 /* Match the table of type against STRING. */
281 static int
282 find_compression_array_template_match (string)
283 tree string;
285 int i;
286 for (i = 0; i < compression_next; i++)
287 if (TREE_VEC_ELT (compression_table, i) == string)
288 return i;
289 return -1;
292 /* We go through the compression table and try to find a complete or
293 partial match. The function returns the compression table entry
294 that (evenutally partially) matches TYPE. *NEXT_CURRENT can be set
295 to the rest of TYPE to be mangled. */
297 static int
298 find_compression_record_match (type, next_current)
299 tree type;
300 tree *next_current;
302 int i, match;
303 tree current, saved_current = NULL_TREE;
305 /* Search from the beginning for something that matches TYPE, even
306 partially. */
307 for (current = TYPE_PACKAGE_LIST (type), i = 0, match = -1; current;
308 current = TREE_CHAIN (current))
310 int j;
311 for (j = i; j < compression_next; j++)
312 if (TREE_VEC_ELT (compression_table, j) == TREE_PURPOSE (current))
314 match = i = j;
315 saved_current = current;
316 i++;
317 break;
319 else
321 /* We don't want to match an element that appears in the middle
322 of a package name, so skip forward to the next complete type name.
323 IDENTIFIER_NODEs are partial package names while RECORD_TYPEs
324 represent complete type names. */
325 while (j < compression_next
326 && TREE_CODE (TREE_VEC_ELT (compression_table, j)) ==
327 IDENTIFIER_NODE)
328 j++;
332 if (!next_current)
333 return match;
335 /* If we have a match, set next_current to the item next to the last
336 matched value. */
337 if (match >= 0)
338 *next_current = TREE_CHAIN (saved_current);
339 /* We had no match: we'll have to start from the beginning. */
340 if (match < 0)
341 *next_current = TYPE_PACKAGE_LIST (type);
343 return match;
346 /* Mangle a record type. If a nonzero value is returned, it means
347 that a 'N' was emitted (so that a matching 'E' can be emitted if
348 necessary.) FOR_POINTER indicates that this element is for a pointer
349 symbol, meaning it was preceded by a 'P'. */
351 static int
352 mangle_record_type (type, for_pointer)
353 tree type;
354 int for_pointer;
356 tree current;
357 int match;
358 int nadded_p = 0;
359 int qualified;
361 /* Does this name have a package qualifier? */
362 qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
364 #define ADD_N() \
365 do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
367 if (TREE_CODE (type) != RECORD_TYPE)
368 abort ();
370 if (!TYPE_PACKAGE_LIST (type))
371 set_type_package_list (type);
373 match = find_compression_record_match (type, &current);
374 if (match >= 0)
376 /* If we had a pointer, and there's more, we need to emit
377 'N' after 'P' (for_pointer tells us we already emitted it.) */
378 if (for_pointer && current)
379 ADD_N();
380 emit_compression_string (match);
382 while (current)
384 /* Add the new type to the table */
385 compression_table_add (TREE_PURPOSE (current));
386 /* Add 'N' if we never got a chance to, but only if we have a qualified
387 name. For non-pointer elements, the name is always qualified. */
388 if ((qualified || !for_pointer) && !nadded_p)
389 ADD_N();
390 /* Use the bare type name for the mangle. */
391 append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
392 IDENTIFIER_LENGTH (TREE_VALUE (current)));
393 current = TREE_CHAIN (current);
395 return nadded_p;
396 #undef ADD_N
399 /* Mangle a pointer type. There are two cases: the pointer is already
400 in the compression table: the compression is emited sans 'P'
401 indicator. Otherwise, a 'P' is emitted and, depending on the type,
402 a partial compression or/plus the rest of the mangling. */
404 static void
405 mangle_pointer_type (type)
406 tree type;
408 int match;
409 tree pointer_type;
411 /* Search for the type already in the compression table */
412 if ((match = find_compression_pointer_match (type)) >= 0)
414 emit_compression_string (match);
415 return;
418 /* This didn't work. We start by mangling the pointed-to type */
419 pointer_type = type;
420 type = TREE_TYPE (type);
421 if (TREE_CODE (type) != RECORD_TYPE)
422 abort ();
424 obstack_1grow (mangle_obstack, 'P');
425 if (mangle_record_type (type, /* for_pointer = */ 1))
426 obstack_1grow (mangle_obstack, 'E');
428 /* Don't forget to insert the pointer type in the table */
429 compression_table_add (pointer_type);
432 /* Mangle an array type. Search for an easy solution first, then go
433 through the process of finding out whether the bare array type or even
434 the template indicator where already used an compress appropriately.
435 It handles pointers. */
437 /* atms: array template mangled string. */
438 static GTY(()) tree atms;
439 static void
440 mangle_array_type (p_type)
441 tree p_type;
443 tree type, elt_type;
444 int match;
446 type = TREE_TYPE (p_type);
447 if (!type)
448 abort ();
450 elt_type = TYPE_ARRAY_ELEMENT (type);
452 /* We cache a bit of the Jarray <> mangle. */
453 if (!atms)
455 atms = get_identifier ("6JArray");
458 /* Maybe we have what we're looking in the compression table. */
459 if ((match = find_compression_array_match (p_type)) >= 0)
461 emit_compression_string (match);
462 return;
465 /* We know for a fact that all arrays are pointers */
466 obstack_1grow (mangle_obstack, 'P');
467 /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
468 if ((match = find_compression_record_match (type, NULL)) > 0)
470 emit_compression_string (match);
471 return;
474 /* Maybe we already have just JArray somewhere */
475 if ((match = find_compression_array_template_match (atms)) > 0)
476 emit_compression_string (match);
477 else
479 /* Start the template mangled name */
480 obstack_grow (mangle_obstack,
481 IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
482 /* Insert in the compression table */
483 compression_table_add (atms);
486 /* Mangle Jarray <elt_type> */
487 obstack_1grow (mangle_obstack, 'I');
488 mangle_type (elt_type);
489 obstack_1grow (mangle_obstack, 'E');
491 /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
492 compression_table_add (type);
493 compression_table_add (p_type);
496 /* Write a substition string for entry I. Substitution string starts a
497 -1 (encoded S_.) The base is 36, and the code shamlessly taken from
498 cp/mangle.c. */
500 static void
501 emit_compression_string (int i)
503 i -= 1; /* Adjust */
504 obstack_1grow (mangle_obstack, 'S');
505 if (i >= 0)
507 static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
508 unsigned HOST_WIDE_INT n;
509 unsigned HOST_WIDE_INT m=1;
510 /* How many digits for I in base 36? */
511 for (n = i; n >= 36; n /= 36, m *=36);
512 /* Write the digits out */
513 while (m > 0)
515 int digit = i / m;
516 obstack_1grow (mangle_obstack, digits [digit]);
517 i -= digit * m;
518 m /= 36;
521 obstack_1grow (mangle_obstack, '_');
524 /* If search the compression table at index I for a pointer type
525 equivalent to TYPE (meaning that after all the indirection, which
526 might all be unique, we find the same RECORD_TYPE.) */
528 static int
529 entry_match_pointer_p (type, i)
530 tree type;
531 int i;
533 tree t = TREE_VEC_ELT (compression_table, i);
535 while (TREE_CODE (type) == POINTER_TYPE
536 && TREE_CODE (t) == POINTER_TYPE)
538 t = TREE_TYPE (t);
539 type = TREE_TYPE (type);
541 return (TREE_CODE (type) == RECORD_TYPE
542 && TREE_CODE (t) == RECORD_TYPE
543 && t == type);
546 /* Go through all qualification of type and build a list of list node
547 elements containings as a purpose what should be used for a match and
548 inserted in the compression table; and as it value the raw name of the
549 part. The result is stored in TYPE_PACKAGE_LIST to be reused. */
551 static void
552 set_type_package_list (type)
553 tree type;
555 int i;
556 const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
557 char *ptr;
558 int qualifications;
559 tree list = NULL_TREE, elt;
561 for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
562 if (*ptr == '.')
563 qualifications += 1;
565 for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
567 if (ptr [0] == '.')
569 char c;
570 tree identifier;
572 /* Can't use an obstack, we're already using it to
573 accumulate the mangling. */
574 c = ptr [0];
575 ptr [0] = '\0';
576 identifier = get_identifier (type_string);
577 ptr [0] = c;
578 elt = build_tree_list (identifier, identifier);
579 TREE_CHAIN (elt) = list;
580 list = elt;
581 type_string = ptr+1;
582 i += 1;
586 elt = build_tree_list (type, get_identifier (type_string));
587 TREE_CHAIN (elt) = list;
588 list = elt;
589 TYPE_PACKAGE_LIST (type) = nreverse (list);
592 /* Add TYPE as the last element of the compression table. Resize the
593 compression table if necessary. */
595 static void
596 compression_table_add (type)
597 tree type;
599 if (compression_next == TREE_VEC_LENGTH (compression_table))
601 tree new = make_tree_vec (2*compression_next);
602 int i;
604 for (i = 0; i < compression_next; i++)
605 TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
607 compression_table = new;
609 TREE_VEC_ELT (compression_table, compression_next++) = type;
612 /* Mangling initialization routine. */
614 static void
615 init_mangling (obstack)
616 struct obstack *obstack;
618 mangle_obstack = obstack;
619 if (!compression_table)
620 compression_table = make_tree_vec (10);
621 else
622 /* Mangling already in progress. */
623 abort ();
625 /* Mangled name are to be suffixed */
626 obstack_grow (mangle_obstack, "_Z", 2);
629 /* Mangling finalization routine. The mangled name is returned as a
630 IDENTIFIER_NODE. */
632 static tree
633 finish_mangling ()
635 tree result;
637 if (!compression_table)
638 /* Mangling already finished. */
639 abort ();
641 compression_table = NULL_TREE;
642 compression_next = 0;
643 obstack_1grow (mangle_obstack, '\0');
644 result = get_identifier (obstack_base (mangle_obstack));
645 obstack_free (mangle_obstack, obstack_base (mangle_obstack));
646 #if 0
647 printf ("// %s\n", IDENTIFIER_POINTER (result));
648 #endif
649 return result;
652 #include "gt-java-mangle.h"