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