OSDN Git Service

* mangle.c (set_type_package_list): Constify.
[pf3gnuchains/gcc-fork.git] / gcc / java / mangle.c
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, 2006, 2007
4    Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
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.
12
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.
17
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, 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. 
22
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.  */
26
27 /* Written by Per Bothner <bothner@cygnus.com> */
28
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 "ggc.h"
39 #include "langhooks-def.h"
40
41 static void mangle_class_field (tree);
42 static void mangle_vtable (tree);
43 static void mangle_field_decl (tree);
44 static void mangle_method_decl (tree);
45 static void mangle_local_cni_method_decl (tree);
46
47 static void mangle_type (tree);
48 static void mangle_pointer_type (tree);
49 static void mangle_array_type (tree);
50 static int  mangle_record_type (tree, int);
51
52 static int find_compression_pointer_match (tree);
53 static int find_compression_array_match (tree);
54 static int find_compression_record_match (tree, tree *);
55 static int find_compression_array_template_match (tree);
56
57 static void set_type_package_list (tree);
58 static int  entry_match_pointer_p (tree, int);
59 static void emit_compression_string (int);
60
61 static void init_mangling (void);
62 static tree finish_mangling (void);
63 static void compression_table_add (tree);
64
65 static void mangle_member_name (tree);
66
67 static struct obstack mangle_obstack_1;
68 struct obstack *mangle_obstack;
69
70 #define MANGLE_RAW_STRING(S) \
71   obstack_grow (mangle_obstack, (S), sizeof (S)-1)
72
73 /* atms: array template mangled string. */
74 static GTY(()) tree atms;
75
76 static int
77 utf8_cmp (const unsigned char *str, int length, const char *name)
78 {
79   const unsigned char *limit = str + length;
80   int i;
81
82   for (i = 0; name[i]; ++i)
83     {
84       int ch = UTF8_GET (str, limit);
85       if (ch != name[i])
86         return ch - name[i];
87     }
88
89   return str == limit ? 0 : 1;
90 }
91
92 /* A sorted list of all C++ keywords.  */
93 static const char *const cxx_keywords[] =
94 {
95   "_Complex",
96   "__alignof",
97   "__alignof__",
98   "__asm",
99   "__asm__",
100   "__attribute",
101   "__attribute__",
102   "__builtin_va_arg",
103   "__complex",
104   "__complex__",
105   "__const",
106   "__const__",
107   "__extension__",
108   "__imag",
109   "__imag__",
110   "__inline",
111   "__inline__",
112   "__label__",
113   "__null",
114   "__real",
115   "__real__",
116   "__restrict",
117   "__restrict__",
118   "__signed",
119   "__signed__",
120   "__typeof",
121   "__typeof__",
122   "__volatile",
123   "__volatile__",
124   "and",
125   "and_eq",
126   "asm",
127   "auto",
128   "bitand",
129   "bitor",
130   "bool",
131   "break",
132   "case",
133   "catch",
134   "char",
135   "class",
136   "compl",
137   "const",
138   "const_cast",
139   "continue",
140   "default",
141   "delete",
142   "do",
143   "double",
144   "dynamic_cast",
145   "else",
146   "enum",
147   "explicit",
148   "export",
149   "extern",
150   "false",
151   "float",
152   "for",
153   "friend",
154   "goto",
155   "if",
156   "inline",
157   "int",
158   "long",
159   "mutable",
160   "namespace",
161   "new",
162   "not",
163   "not_eq",
164   "operator",
165   "or",
166   "or_eq",
167   "private",
168   "protected",
169   "public",
170   "register",
171   "reinterpret_cast",
172   "return",
173   "short",
174   "signed",
175   "sizeof",
176   "static",
177   "static_cast",
178   "struct",
179   "switch",
180   "template",
181   "this",      
182   "throw",
183   "true",
184   "try",
185   "typedef",
186   "typeid",
187   "typename",
188   "typeof",
189   "union",
190   "unsigned",
191   "using",
192   "virtual",
193   "void",
194   "volatile",
195   "wchar_t",
196   "while",
197   "xor",
198   "xor_eq"
199 };
200
201 /* Return true if NAME is a C++ keyword.  */
202 static int
203 cxx_keyword_p (const char *name, int length)
204 {
205   int last = ARRAY_SIZE (cxx_keywords);
206   int first = 0;
207   int mid = (last + first) / 2;
208   int old = -1;
209
210   for (mid = (last + first) / 2;
211        mid != old;
212        old = mid, mid = (last + first) / 2)
213     {
214       int kwl = strlen (cxx_keywords[mid]);
215       int min_length = kwl > length ? length : kwl;
216       int r = utf8_cmp ((const unsigned char *) name, min_length, cxx_keywords[mid]);
217
218       if (r == 0)
219         {
220           int i;
221           /* We've found a match if all the remaining characters are `$'.  */
222           for (i = min_length; i < length && name[i] == '$'; ++i)
223             ;
224           if (i == length)
225             return 1;
226           r = 1;
227         }
228
229       if (r < 0)
230         last = mid;
231       else
232         first = mid;
233     }
234   return 0;
235 }
236
237 /* This is the mangling interface: a decl, a class field (.class) and
238    the vtable. */
239
240 void
241 java_mangle_decl (tree decl)
242 {
243   if (TREE_CODE (decl) == RECORD_TYPE)
244     mangle_type (decl);
245
246   /* A copy of the check from the beginning of lhd_set_decl_assembler_name.
247      Only FUNCTION_DECLs and VAR_DECLs for variables with static storage
248      duration need a real DECL_ASSEMBLER_NAME.  */
249   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
250               || (TREE_CODE (decl) == VAR_DECL
251                   && (TREE_STATIC (decl)
252                       || DECL_EXTERNAL (decl)
253                       || TREE_PUBLIC (decl))));
254   
255   /* Mangling only applies to class members.  */
256   if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
257     {
258       init_mangling ();
259       switch (TREE_CODE (decl))
260         {
261         case VAR_DECL:
262           if (DECL_LANG_SPECIFIC (decl))
263             {
264               if (DECL_CLASS_FIELD_P (decl))
265                 {
266                   mangle_class_field (decl);
267                   break;
268                 }
269               else if (DECL_VTABLE_P (decl))
270                 {
271                   mangle_vtable (DECL_CONTEXT (decl));
272                   break;
273                 }
274             }
275           mangle_field_decl (decl);
276           break;
277
278         case FUNCTION_DECL:
279           if (DECL_LANG_SPECIFIC (decl) && DECL_LOCAL_CNI_METHOD_P (decl))
280             mangle_local_cni_method_decl (decl);
281           else
282             mangle_method_decl (decl);
283           break;
284
285         default:
286           gcc_unreachable ();
287         }
288       SET_DECL_ASSEMBLER_NAME (decl, finish_mangling ());
289     }
290   else
291     lhd_set_decl_assembler_name (decl);
292 }
293
294 /* Beginning of the helper functions */
295
296 static void
297 mangle_class_field (tree decl)
298 {
299   tree type = DECL_CONTEXT (decl);
300   mangle_record_type (type, /* for_pointer = */ 0);
301   if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
302     MANGLE_RAW_STRING ("6class$");
303   else
304     MANGLE_RAW_STRING ("7class$$");
305   obstack_1grow (mangle_obstack, 'E');
306 }
307
308 static void
309 mangle_vtable (tree type)
310 {
311   MANGLE_RAW_STRING ("TV");
312   mangle_record_type (type, /* for_pointer = */ 0);
313   obstack_1grow (mangle_obstack, 'E');
314 }
315
316 /* This mangles a field decl */
317
318 static void
319 mangle_field_decl (tree decl)
320 {
321   /* Mangle the name of the this the field belongs to */
322   mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0);
323   
324   /* Mangle the name of the field */
325   mangle_member_name (DECL_NAME (decl));
326
327   /* Terminate the mangled name */
328   obstack_1grow (mangle_obstack, 'E');
329 }
330
331 /* This mangles a method decl, first mangling its name and then all
332    its arguments. */
333
334 static void
335 mangle_method_decl (tree mdecl)
336 {
337   tree method_name = DECL_NAME (mdecl);
338   tree arglist;
339
340   /* Mangle the name of the type that contains mdecl */
341   mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0);
342
343   /* Mangle the function name.  There are two cases:
344        - mdecl is a constructor, use `C1' for its name, (denotes a
345          complete object constructor.)
346        - mdecl is not a constructor, standard mangling is performed.
347      We terminate the mangled function name with a `E'. */
348   if (ID_INIT_P (method_name))
349     obstack_grow (mangle_obstack, "C1", 2);
350   else
351     mangle_member_name (method_name);
352   obstack_1grow (mangle_obstack, 'E');
353
354   /* We mangled type.methodName. Now onto the arguments. */
355   arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl));
356   if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE)
357     arglist = TREE_CHAIN (arglist);
358   
359   /* Output literal 'J' and mangle the return type IF not a 
360      constructor.  */
361   if (!ID_INIT_P (method_name))
362     {
363       obstack_1grow (mangle_obstack, 'J');
364       mangle_type(TREE_TYPE(TREE_TYPE(mdecl)));
365     }
366   
367   /* No arguments is easy. We shortcut it. */
368   if (arglist == end_params_node)
369     obstack_1grow (mangle_obstack, 'v');
370   else
371     {
372       tree arg;
373       for (arg = arglist; arg != end_params_node;  arg = TREE_CHAIN (arg))
374         mangle_type (TREE_VALUE (arg));
375     }
376 }
377
378 /* This mangles a CNI method for a local class.  If the target supports
379    hidden aliases, then G++ will have generated one for us.  It is the
380    responsibility of java_mark_class_local to check target support, since
381    we need to set DECL_VISIBILITY (or not) much earlier.  */
382
383 static void
384 mangle_local_cni_method_decl (tree decl)
385 {
386   MANGLE_RAW_STRING ("GA");
387   mangle_method_decl (decl);
388 }
389
390 /* This mangles a member name, like a function name or a field
391    name. Handle cases were `name' is a C++ keyword.  Return a nonzero
392    value if unicode encoding was required.  */
393
394 static void
395 mangle_member_name (tree name)
396 {
397   append_gpp_mangled_name (IDENTIFIER_POINTER (name),
398                            IDENTIFIER_LENGTH (name));
399
400   /* If NAME happens to be a C++ keyword, add `$'.  */
401   if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
402     obstack_1grow (mangle_obstack, '$');
403 }
404
405 /* Append the mangled name of TYPE onto OBSTACK.  */
406
407 static void
408 mangle_type (tree type)
409 {
410   switch (TREE_CODE (type))
411     {
412       char code;
413     case BOOLEAN_TYPE: code = 'b';  goto primitive;
414     case VOID_TYPE:    code = 'v';  goto primitive;
415     case INTEGER_TYPE:
416       if (type == char_type_node || type == promoted_char_type_node)
417         {
418           code = 'w';
419           goto primitive;
420         }
421       /* Get the original type instead of the arguments promoted type.
422          Avoid symbol name clashes. Should call a function to do that.
423          FIXME.  */
424       if (type == promoted_short_type_node)
425         type = short_type_node;
426       if (type == promoted_byte_type_node)
427         type = byte_type_node;
428       switch (TYPE_PRECISION (type))
429         {
430         case  8:       code = 'c';  goto primitive;
431         case 16:       code = 's';  goto primitive;
432         case 32:       code = 'i';  goto primitive;
433         case 64:       code = 'x';  goto primitive;
434         default:  goto bad_type;
435         }
436     primitive:
437       obstack_1grow (mangle_obstack, code);
438       break;
439
440     case REAL_TYPE:
441       switch (TYPE_PRECISION (type))
442         {
443         case 32:       code = 'f';  goto primitive;
444         case 64:       code = 'd';  goto primitive;
445         default:  goto bad_type;
446         }
447     case POINTER_TYPE:
448       if (TYPE_ARRAY_P (TREE_TYPE (type)))
449         mangle_array_type (type);
450       else
451         mangle_pointer_type (type);
452       break;
453     bad_type:
454     default:
455       gcc_unreachable ();
456     }
457 }
458
459 /* The compression table is a vector that keeps track of things we've
460    already seen, so they can be reused. For example, java.lang.Object
461    would generate three entries: two package names and a type. If
462    java.lang.String is presented next, the java.lang will be matched
463    against the first two entries (and kept for compression as S0_), and
464    type String would be added to the table. See mangle_record_type.
465    COMPRESSION_NEXT is the index to the location of the next insertion
466    of an element.  */
467
468 static GTY(()) tree compression_table;
469 static int  compression_next;
470
471 /* Find a POINTER_TYPE in the compression table. Use a special
472    function to match pointer entries and start from the end */
473
474 static int
475 find_compression_pointer_match (tree type)
476 {
477   int i;
478
479   for (i = compression_next-1; i >= 0; i--)
480     if (entry_match_pointer_p (type, i))
481       return i;
482   return -1;
483 }
484
485 /* Already recorder arrays are handled like pointer as they're always
486    associated with it.  */
487
488 static int
489 find_compression_array_match (tree type)
490 {
491   return find_compression_pointer_match (type);
492 }
493
494 /* Match the table of type against STRING.  */
495
496 static int
497 find_compression_array_template_match (tree string)
498 {
499   int i;
500   for (i = 0; i < compression_next; i++)
501     if (TREE_VEC_ELT (compression_table, i) == string) 
502       return i;
503   return -1;
504 }
505
506 /* We go through the compression table and try to find a complete or
507    partial match. The function returns the compression table entry
508    that (eventually partially) matches TYPE. *NEXT_CURRENT can be set
509    to the rest of TYPE to be mangled. */
510
511 static int
512 find_compression_record_match (tree type, tree *next_current)
513 {
514   int i, match = -1;
515   tree current, saved_current = NULL_TREE;
516
517   current = TYPE_PACKAGE_LIST (type);
518       
519   for (i = 0; i < compression_next; i++)
520     {
521       tree compression_entry = TREE_VEC_ELT (compression_table, i);
522       if (current && compression_entry == TREE_PURPOSE (current))
523         {
524           match = i;
525           saved_current = current;
526           current = TREE_CHAIN (current);
527         }
528       else
529         /* We don't want to match an element that appears in the middle
530            of a package name, so skip forward to the next complete type name.
531            IDENTIFIER_NODEs (except for a "6JArray") are partial package
532            names while RECORD_TYPEs represent complete type names. */
533         while (i < compression_next 
534                && TREE_CODE (compression_entry) == IDENTIFIER_NODE
535                && compression_entry != atms)
536           compression_entry = TREE_VEC_ELT (compression_table, ++i);
537     }
538
539   if (!next_current)
540     return match;
541
542   /* If we have a match, set next_current to the item next to the last
543      matched value. */
544   if (match >= 0)
545     *next_current = TREE_CHAIN (saved_current);
546   /* We had no match: we'll have to start from the beginning. */
547   if (match < 0)
548     *next_current = TYPE_PACKAGE_LIST (type);
549
550   return match;
551 }
552
553 /* Mangle a record type. If a nonzero value is returned, it means
554    that a 'N' was emitted (so that a matching 'E' can be emitted if
555    necessary.)  FOR_POINTER indicates that this element is for a pointer
556    symbol, meaning it was preceded by a 'P'. */
557
558 static int
559 mangle_record_type (tree type, int for_pointer)
560 {
561   tree current;
562   int match;
563   int nadded_p = 0;
564   int qualified;
565   
566   /* Does this name have a package qualifier? */
567   qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type)));
568
569 #define ADD_N() \
570   do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0)
571
572   gcc_assert (TREE_CODE (type) == RECORD_TYPE);
573
574   if (!TYPE_PACKAGE_LIST (type))
575     set_type_package_list (type);
576
577   match = find_compression_record_match (type, &current);
578   if (match >= 0)
579     {
580       /* If we had a pointer, and there's more, we need to emit
581          'N' after 'P' (for_pointer tells us we already emitted it.) */
582       if (for_pointer && current)
583         ADD_N();
584       emit_compression_string (match);
585     }
586   while (current)
587     {
588       /* Add the new type to the table */
589       compression_table_add (TREE_PURPOSE (current));
590       /* Add 'N' if we never got a chance to, but only if we have a qualified
591          name.  For non-pointer elements, the name is always qualified. */
592       if ((qualified || !for_pointer) && !nadded_p)
593         ADD_N();
594       /* Use the bare type name for the mangle. */
595       append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)),
596                                IDENTIFIER_LENGTH (TREE_VALUE (current)));
597       current = TREE_CHAIN (current);
598     }
599   return nadded_p;
600 #undef ADD_N
601 }
602
603 /* Mangle a pointer type. There are two cases: the pointer is already
604    in the compression table: the compression is emitted sans 'P'
605    indicator. Otherwise, a 'P' is emitted and, depending on the type,
606    a partial compression or/plus the rest of the mangling. */
607
608 static void
609 mangle_pointer_type (tree type)
610 {
611   int match;
612   tree pointer_type;
613
614   /* Search for the type already in the compression table */
615   if ((match = find_compression_pointer_match (type)) >= 0) 
616     {
617       emit_compression_string (match);
618       return;
619     }
620   
621   /* This didn't work. We start by mangling the pointed-to type */
622   pointer_type = type;
623   type = TREE_TYPE (type);
624   gcc_assert (TREE_CODE (type) == RECORD_TYPE);
625   
626   obstack_1grow (mangle_obstack, 'P');
627   if (mangle_record_type (type, /* for_pointer = */ 1))
628     obstack_1grow (mangle_obstack, 'E');
629
630   /* Don't forget to insert the pointer type in the table */
631   compression_table_add (pointer_type);
632 }
633
634 /* Mangle an array type. Search for an easy solution first, then go
635    through the process of finding out whether the bare array type or even
636    the template indicator were already used and compressed appropriately.
637    It handles pointers. */
638
639 static void
640 mangle_array_type (tree p_type)
641 {
642   tree type, elt_type;
643   int match;
644
645   type = TREE_TYPE (p_type);
646   gcc_assert (type);
647
648   elt_type = TYPE_ARRAY_ELEMENT (type);
649
650   /* We cache a bit of the Jarray <> mangle. */
651   if (!atms)
652     {
653       atms = get_identifier ("6JArray");
654     }
655
656   /* Maybe we have what we're looking for in the compression table. */
657   if ((match = find_compression_array_match (p_type)) >= 0)
658     {
659       emit_compression_string (match);
660       return;
661     }
662
663   /* We know for a fact that all arrays are pointers */
664   obstack_1grow (mangle_obstack, 'P');
665   /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */
666   if ((match = find_compression_record_match (type, NULL)) > 0)
667     {
668       emit_compression_string (match);
669       return;
670     }
671
672   /* Maybe we already have just JArray somewhere */
673   if ((match = find_compression_array_template_match (atms)) > 0)
674     emit_compression_string (match);
675   else
676     {
677       /* Start the template mangled name */
678       obstack_grow (mangle_obstack, 
679                     IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms));
680       /* Insert in the compression table */
681       compression_table_add (atms);
682     } 
683
684   /* Mangle Jarray <elt_type> */
685   obstack_1grow (mangle_obstack, 'I');
686   mangle_type (elt_type);
687   obstack_1grow (mangle_obstack, 'E');
688
689   /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */
690   compression_table_add (type);
691   compression_table_add (p_type);
692 }
693
694 /* Write a substitution string for entry I. Substitution string starts a
695    -1 (encoded S_.) The base is 36, and the code shamelessly taken from
696    cp/mangle.c.  */
697
698 static void
699 emit_compression_string (int i)
700 {
701   i -= 1;                       /* Adjust */
702   obstack_1grow (mangle_obstack, 'S');
703   if (i >= 0)
704     {
705       static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
706       unsigned HOST_WIDE_INT n;
707       unsigned HOST_WIDE_INT m=1;
708       /* How many digits for I in base 36? */
709       for (n = i; n >= 36; n /= 36, m *=36);
710       /* Write the digits out */
711       while (m > 0)
712         {
713           int digit = i / m;
714           obstack_1grow (mangle_obstack, digits [digit]);
715           i -= digit * m;
716           m /= 36;
717         }
718     }
719   obstack_1grow (mangle_obstack, '_');
720 }
721
722 /* If search the compression table at index I for a pointer type
723    equivalent to TYPE (meaning that after all the indirection, which
724    might all be unique, we find the same RECORD_TYPE.) */
725
726 static int
727 entry_match_pointer_p (tree type, int i)
728 {
729   tree t = TREE_VEC_ELT (compression_table, i);
730   
731   while (TREE_CODE (type) == POINTER_TYPE
732          && TREE_CODE (t) == POINTER_TYPE)
733     {
734       t = TREE_TYPE (t);
735       type = TREE_TYPE (type);
736     }
737   return (TREE_CODE (type) == RECORD_TYPE
738           && TREE_CODE (t) == RECORD_TYPE
739           && t == type);
740 }
741
742 /* Go through all qualification of type and build a list of list node
743    elements containings as a purpose what should be used for a match and
744    inserted in the compression table; and as it value the raw name of the
745    part. The result is stored in TYPE_PACKAGE_LIST to be reused.  */
746
747 static void
748 set_type_package_list (tree type)
749 {
750   int i;
751   const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
752   const char *ptr;
753   int qualifications;
754   tree list = NULL_TREE, elt;
755
756   for (ptr = type_string, qualifications = 0; *ptr; ptr++)
757     if (*ptr == '.')
758       qualifications += 1;
759
760   for (ptr = type_string, i = 0; i < qualifications; ptr++)
761     {
762       if (ptr [0] == '.')
763         {
764           tree const identifier
765             = get_identifier_with_length (type_string, ptr - type_string);
766
767           elt = build_tree_list (identifier, identifier);
768           TREE_CHAIN (elt) = list;
769           list = elt;
770           type_string = ptr+1;
771           i += 1;
772         }
773     }
774
775   elt = build_tree_list (type, get_identifier (type_string));
776   TREE_CHAIN (elt) = list;
777   list = elt;
778   TYPE_PACKAGE_LIST (type) = nreverse (list);
779 }
780
781 /* Add TYPE as the last element of the compression table. Resize the
782    compression table if necessary.  */
783
784 static void
785 compression_table_add (tree type)
786 {
787   if (compression_next == TREE_VEC_LENGTH (compression_table))
788     {
789       tree new = make_tree_vec (2*compression_next);
790       int i;
791
792       for (i = 0; i < compression_next; i++)
793         TREE_VEC_ELT (new, i) = TREE_VEC_ELT (compression_table, i);
794
795       compression_table = new;
796     }
797   TREE_VEC_ELT (compression_table, compression_next++) = type;
798 }
799
800 /* Mangling initialization routine.  */
801
802 static void
803 init_mangling (void)
804 {
805   if (!mangle_obstack)
806     {
807       mangle_obstack = &mangle_obstack_1;
808       gcc_obstack_init (mangle_obstack);
809     }
810
811   gcc_assert (compression_table == NULL);
812   compression_table = make_tree_vec (10);
813
814   /* Mangled name are to be suffixed */
815   MANGLE_RAW_STRING ("_Z");
816 }
817
818 /* Mangling finalization routine. The mangled name is returned as a
819    IDENTIFIER_NODE.  */
820
821 static tree
822 finish_mangling (void)
823 {
824   tree result;
825
826   gcc_assert (compression_table);
827
828   compression_table = NULL_TREE;
829   compression_next = 0;
830   obstack_1grow (mangle_obstack, '\0');
831   result = get_identifier (obstack_base (mangle_obstack));
832   obstack_free (mangle_obstack, obstack_base (mangle_obstack));
833
834   return result;
835 }
836
837 #include "gt-java-mangle.h"