xref: /openbsd-src/gnu/usr.bin/gcc/gcc/java/mangle.c (revision c87b03e512fc05ed6e0222f6fb0ae86264b1d05b)
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 "jcf.h"
31 #include "tree.h"
32 #include "java-tree.h"
33 #include "obstack.h"
34 #include "toplev.h"
35 #include "obstack.h"
36 #include "ggc.h"
37 
38 static void mangle_field_decl PARAMS ((tree));
39 static void mangle_method_decl PARAMS ((tree));
40 
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));
45 
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));
50 
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));
54 
55 static void init_mangling PARAMS ((struct obstack *));
56 static tree finish_mangling PARAMS ((void));
57 static void compression_table_add PARAMS ((tree));
58 
59 static void mangle_member_name PARAMS ((tree));
60 
61 /* We use an incoming obstack, always to be provided to the interface
62    functions. */
63 struct obstack *mangle_obstack;
64 #define MANGLE_RAW_STRING(S) \
65   obstack_grow (mangle_obstack, (S), sizeof (S)-1)
66 
67 /* This is the mangling interface: a decl, a class field (.class) and
68    the vtable. */
69 
70 tree
java_mangle_decl(obstack,decl)71 java_mangle_decl (obstack, decl)
72      struct obstack *obstack;
73      tree decl;
74 {
75   init_mangling (obstack);
76   switch (TREE_CODE (decl))
77     {
78     case VAR_DECL:
79       mangle_field_decl (decl);
80       break;
81     case FUNCTION_DECL:
82       mangle_method_decl (decl);
83       break;
84     default:
85       internal_error ("can't mangle %s", tree_code_name [TREE_CODE (decl)]);
86     }
87   return finish_mangling ();
88 }
89 
90 tree
java_mangle_class_field(obstack,type)91 java_mangle_class_field (obstack, type)
92      struct obstack *obstack;
93      tree type;
94 {
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 ();
100 }
101 
102 tree
java_mangle_vtable(obstack,type)103 java_mangle_vtable (obstack, type)
104      struct obstack *obstack;
105      tree type;
106 {
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 ();
112 }
113 
114 /* Beginning of the helper functions */
115 
116 /* This mangles a field decl */
117 
118 static void
mangle_field_decl(decl)119 mangle_field_decl (decl)
120      tree decl;
121 {
122   /* Mangle the name of the this the field belongs to */
123   mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
124 
125   /* Mangle the name of the field */
126   mangle_member_name (DECL_NAME (decl));
127 
128   /* Terminate the mangled name */
129   obstack_1grow (mangle_obstack, 'E');
130 }
131 
132 /* This mangles a method decl, first mangling its name and then all
133    its arguments. */
134 
135 static void
mangle_method_decl(mdecl)136 mangle_method_decl (mdecl)
137      tree mdecl;
138 {
139   tree method_name = DECL_NAME (mdecl);
140   tree arglist;
141 
142   /* Mangle the name of the type that contains mdecl */
143   mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
144 
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);
152   else
153     mangle_member_name (method_name);
154   obstack_1grow (mangle_obstack, 'E');
155 
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);
160 
161   /* No arguments is easy. We shortcut it. */
162   if (arglist == end_params_node)
163     obstack_1grow (mangle_obstack, 'v');
164   else
165     {
166       tree arg;
167       for (arg = arglist; arg != end_params_node;  arg = TREE_CHAIN (arg))
168 	mangle_type (TREE_VALUE (arg));
169     }
170 }
171 
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 nonzero
174    value if unicode encoding was required.  */
175 
176 static void
mangle_member_name(name)177 mangle_member_name (name)
178      tree name;
179 {
180   append_gpp_mangled_name (IDENTIFIER_POINTER (name),
181 			   IDENTIFIER_LENGTH (name));
182 
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, '$');
186 }
187 
188 /* Append the mangled name of TYPE onto OBSTACK.  */
189 
190 static void
mangle_type(type)191 mangle_type (type)
192      tree type;
193 {
194   switch (TREE_CODE (type))
195     {
196       char code;
197     case BOOLEAN_TYPE: code = 'b';  goto primitive;
198     case CHAR_TYPE:    code = 'w';  goto primitive;
199     case VOID_TYPE:    code = 'v';  goto primitive;
200     case INTEGER_TYPE:
201       /* Get the original type instead of the arguments promoted type.
202 	 Avoid symbol name clashes. Should call a function to do that.
203 	 FIXME.  */
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))
209 	{
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;
215 	}
216     primitive:
217       obstack_1grow (mangle_obstack, code);
218       break;
219 
220     case REAL_TYPE:
221       switch (TYPE_PRECISION (type))
222 	{
223 	case 32:       code = 'f';  goto primitive;
224 	case 64:       code = 'd';  goto primitive;
225 	default:  goto bad_type;
226 	}
227     case POINTER_TYPE:
228       if (TYPE_ARRAY_P (TREE_TYPE (type)))
229 	mangle_array_type (type);
230       else
231 	mangle_pointer_type (type);
232       break;
233     bad_type:
234     default:
235       abort ();
236     }
237 }
238 
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
246    of an element.  */
247 
248 static GTY(()) tree compression_table;
249 static int  compression_next;
250 
251 /* Find a POINTER_TYPE in the compression table. Use a special
252    function to match pointer entries and start from the end */
253 
254 static int
find_compression_pointer_match(type)255 find_compression_pointer_match (type)
256      tree type;
257 {
258   int i;
259 
260   for (i = compression_next-1; i >= 0; i--)
261     if (entry_match_pointer_p (type, i))
262       return i;
263   return -1;
264 }
265 
266 /* Already recorder arrays are handled like pointer as they're always
267    associated with it.  */
268 
269 static int
find_compression_array_match(type)270 find_compression_array_match (type)
271      tree type;
272 {
273   return find_compression_pointer_match (type);
274 }
275 
276 /* Match the table of type against STRING.  */
277 
278 static int
find_compression_array_template_match(string)279 find_compression_array_template_match (string)
280      tree string;
281 {
282   int i;
283   for (i = 0; i < compression_next; i++)
284     if (TREE_VEC_ELT (compression_table, i) == string)
285       return i;
286   return -1;
287 }
288 
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. */
293 
294 static int
find_compression_record_match(type,next_current)295 find_compression_record_match (type, next_current)
296      tree type;
297      tree *next_current;
298 {
299   int i, match;
300   tree current, saved_current = NULL_TREE;
301 
302   /* Search from the beginning for something that matches TYPE, even
303      partially. */
304   for (current = TYPE_PACKAGE_LIST (type), i = 0, match = -1; current;
305        current = TREE_CHAIN (current))
306     {
307       int j;
308       for (j = i; j < compression_next; j++)
309 	if (TREE_VEC_ELT (compression_table, j) == TREE_PURPOSE (current))
310 	  {
311 	    match = i = j;
312 	    saved_current = current;
313 	    i++;
314 	    break;
315 	  }
316 	else
317 	  {
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)) ==
324 		      IDENTIFIER_NODE)
325 	      j++;
326 	  }
327     }
328 
329   if (!next_current)
330     return match;
331 
332   /* If we have a match, set next_current to the item next to the last
333      matched value. */
334   if (match >= 0)
335     *next_current = TREE_CHAIN (saved_current);
336   /* We had no match: we'll have to start from the beginning. */
337   if (match < 0)
338     *next_current = TYPE_PACKAGE_LIST (type);
339 
340   return match;
341 }
342 
343 /* Mangle a record type. If a nonzero 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'. */
347 
348 static int
mangle_record_type(type,for_pointer)349 mangle_record_type (type, for_pointer)
350      tree type;
351      int for_pointer;
352 {
353   tree current;
354   int match;
355   int nadded_p = 0;
356   int qualified;
357 
358   /* Does this name have a package qualifier? */
359   qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
360 
361 #define ADD_N() \
362   do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
363 
364   if (TREE_CODE (type) != RECORD_TYPE)
365     abort ();
366 
367   if (!TYPE_PACKAGE_LIST (type))
368     set_type_package_list (type);
369 
370   match = find_compression_record_match (type, &current);
371   if (match >= 0)
372     {
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)
376 	ADD_N();
377       emit_compression_string (match);
378     }
379   while (current)
380     {
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)
386 	ADD_N();
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);
391     }
392   return nadded_p;
393 #undef ADD_N
394 }
395 
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. */
400 
401 static void
mangle_pointer_type(type)402 mangle_pointer_type (type)
403      tree type;
404 {
405   int match;
406   tree pointer_type;
407 
408   /* Search for the type already in the compression table */
409   if ((match = find_compression_pointer_match (type)) >= 0)
410     {
411       emit_compression_string (match);
412       return;
413     }
414 
415   /* This didn't work. We start by mangling the pointed-to type */
416   pointer_type = type;
417   type = TREE_TYPE (type);
418   if (TREE_CODE (type) != RECORD_TYPE)
419     abort ();
420 
421   obstack_1grow (mangle_obstack, 'P');
422   if (mangle_record_type (type, /* for_pointer = */ 1))
423     obstack_1grow (mangle_obstack, 'E');
424 
425   /* Don't forget to insert the pointer type in the table */
426   compression_table_add (pointer_type);
427 }
428 
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. */
433 
434 /* atms: array template mangled string. */
435 static GTY(()) tree atms;
436 static void
mangle_array_type(p_type)437 mangle_array_type (p_type)
438      tree p_type;
439 {
440   tree type, elt_type;
441   int match;
442 
443   type = TREE_TYPE (p_type);
444   if (!type)
445     abort ();
446 
447   elt_type = TYPE_ARRAY_ELEMENT (type);
448 
449   /* We cache a bit of the Jarray <> mangle. */
450   if (!atms)
451     {
452       atms = get_identifier ("6JArray");
453     }
454 
455   /* Maybe we have what we're looking in the compression table. */
456   if ((match = find_compression_array_match (p_type)) >= 0)
457     {
458       emit_compression_string (match);
459       return;
460     }
461 
462   /* We know for a fact that all arrays are pointers */
463   obstack_1grow (mangle_obstack, 'P');
464   /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
465   if ((match = find_compression_record_match (type, NULL)) > 0)
466     {
467       emit_compression_string (match);
468       return;
469     }
470 
471   /* Maybe we already have just JArray somewhere */
472   if ((match = find_compression_array_template_match (atms)) > 0)
473     emit_compression_string (match);
474   else
475     {
476       /* Start the template mangled name */
477       obstack_grow (mangle_obstack,
478 		    IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
479       /* Insert in the compression table */
480       compression_table_add (atms);
481     }
482 
483   /* Mangle Jarray <elt_type> */
484   obstack_1grow (mangle_obstack, 'I');
485   mangle_type (elt_type);
486   obstack_1grow (mangle_obstack, 'E');
487 
488   /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
489   compression_table_add (type);
490   compression_table_add (p_type);
491 }
492 
493 /* Write a substition string for entry I. Substitution string starts a
494    -1 (encoded S_.) The base is 36, and the code shamlessly taken from
495    cp/mangle.c.  */
496 
497 static void
emit_compression_string(int i)498 emit_compression_string (int i)
499 {
500   i -= 1;			/* Adjust */
501   obstack_1grow (mangle_obstack, 'S');
502   if (i >= 0)
503     {
504       static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
505       unsigned HOST_WIDE_INT n;
506       unsigned HOST_WIDE_INT m=1;
507       /* How many digits for I in base 36? */
508       for (n = i; n >= 36; n /= 36, m *=36);
509       /* Write the digits out */
510       while (m > 0)
511 	{
512 	  int digit = i / m;
513 	  obstack_1grow (mangle_obstack, digits [digit]);
514 	  i -= digit * m;
515 	  m /= 36;
516 	}
517     }
518   obstack_1grow (mangle_obstack, '_');
519 }
520 
521 /* If search the compression table at index I for a pointer type
522    equivalent to TYPE (meaning that after all the indirection, which
523    might all be unique, we find the same RECORD_TYPE.) */
524 
525 static int
entry_match_pointer_p(type,i)526 entry_match_pointer_p (type, i)
527      tree type;
528      int i;
529 {
530   tree t = TREE_VEC_ELT (compression_table, i);
531 
532   while (TREE_CODE (type) == POINTER_TYPE
533 	 && TREE_CODE (t) == POINTER_TYPE)
534     {
535       t = TREE_TYPE (t);
536       type = TREE_TYPE (type);
537     }
538   return (TREE_CODE (type) == RECORD_TYPE
539 	  && TREE_CODE (t) == RECORD_TYPE
540 	  && t == type);
541 }
542 
543 /* Go through all qualification of type and build a list of list node
544    elements containings as a purpose what should be used for a match and
545    inserted in the compression table; and as it value the raw name of the
546    part. The result is stored in TYPE_PACKAGE_LIST to be reused.  */
547 
548 static void
set_type_package_list(type)549 set_type_package_list (type)
550      tree type;
551 {
552   int i;
553   const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
554   char *ptr;
555   int qualifications;
556   tree list = NULL_TREE, elt;
557 
558   for (ptr = (char *)type_string, qualifications = 0; *ptr; ptr++)
559     if (*ptr == '.')
560       qualifications += 1;
561 
562   for (ptr = (char *)type_string, i = 0; i < qualifications; ptr++)
563     {
564       if (ptr [0] == '.')
565 	{
566 	  char c;
567 	  tree identifier;
568 
569 	  /* Can't use an obstack, we're already using it to
570 	     accumulate the mangling. */
571 	  c = ptr [0];
572 	  ptr [0] = '\0';
573 	  identifier = get_identifier (type_string);
574 	  ptr [0] = c;
575 	  elt = build_tree_list (identifier, identifier);
576 	  TREE_CHAIN (elt) = list;
577 	  list = elt;
578 	  type_string = ptr+1;
579 	  i += 1;
580 	}
581     }
582 
583   elt = build_tree_list (type, get_identifier (type_string));
584   TREE_CHAIN (elt) = list;
585   list = elt;
586   TYPE_PACKAGE_LIST (type) = nreverse (list);
587 }
588 
589 /* Add TYPE as the last element of the compression table. Resize the
590    compression table if necessary.  */
591 
592 static void
compression_table_add(type)593 compression_table_add (type)
594      tree type;
595 {
596   if (compression_next == TREE_VEC_LENGTH (compression_table))
597     {
598       tree new = make_tree_vec (2*compression_next);
599       int i;
600 
601       for (i = 0; i < compression_next; i++)
602 	TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
603 
604       compression_table = new;
605     }
606   TREE_VEC_ELT (compression_table, compression_next++) = type;
607 }
608 
609 /* Mangling initialization routine.  */
610 
611 static void
init_mangling(obstack)612 init_mangling (obstack)
613      struct obstack *obstack;
614 {
615   mangle_obstack = obstack;
616   if (!compression_table)
617     compression_table = make_tree_vec (10);
618   else
619     /* Mangling already in progress.  */
620     abort ();
621 
622   /* Mangled name are to be suffixed */
623   obstack_grow (mangle_obstack, "_Z", 2);
624 }
625 
626 /* Mangling finalization routine. The mangled name is returned as a
627    IDENTIFIER_NODE.  */
628 
629 static tree
finish_mangling()630 finish_mangling ()
631 {
632   tree result;
633 
634   if (!compression_table)
635     /* Mangling already finished.  */
636     abort ();
637 
638   compression_table = NULL_TREE;
639   compression_next = 0;
640   obstack_1grow (mangle_obstack, '\0');
641   result = get_identifier (obstack_base (mangle_obstack));
642   obstack_free (mangle_obstack, obstack_base (mangle_obstack));
643 #if 0
644   printf ("// %s\n", IDENTIFIER_POINTER (result));
645 #endif
646   return result;
647 }
648 
649 #include "gt-java-mangle.h"
650