]>
Commit | Line | Data |
---|---|---|
377029eb | 1 | /* Functions related to mangling class names for the GNU compiler |
2 | for the Java(TM) language. | |
d353bf18 | 3 | Copyright (C) 1998-2015 Free Software Foundation, Inc. |
377029eb | 4 | |
7d82ed5e | 5 | This file is part of GCC. |
377029eb | 6 | |
7d82ed5e | 7 | GCC is free software; you can redistribute it and/or modify |
377029eb | 8 | it under the terms of the GNU General Public License as published by |
e4b52719 | 9 | the Free Software Foundation; either version 3, or (at your option) |
377029eb | 10 | any later version. |
11 | ||
7d82ed5e | 12 | GCC is distributed in the hope that it will be useful, |
377029eb | 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 | |
e4b52719 | 18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. | |
377029eb | 20 | |
21 | Java and all Java-based marks are trademarks or registered trademarks | |
22 | of Sun Microsystems, Inc. in the United States and other countries. | |
23 | The Free Software Foundation is independent of Sun Microsystems, Inc. */ | |
24 | ||
25 | /* Written by Per Bothner <bothner@cygnus.com> */ | |
26 | ||
377029eb | 27 | #include "config.h" |
014e6e0c | 28 | #include "system.h" |
805e22b2 | 29 | #include "coretypes.h" |
377029eb | 30 | #include "jcf.h" |
b20a8bb4 | 31 | #include "hash-set.h" |
b20a8bb4 | 32 | #include "vec.h" |
b20a8bb4 | 33 | #include "input.h" |
34 | #include "alias.h" | |
35 | #include "symtab.h" | |
36 | #include "options.h" | |
b20a8bb4 | 37 | #include "inchash.h" |
003019ba | 38 | #include "tree.h" |
9ed99284 | 39 | #include "stringpool.h" |
003019ba | 40 | #include "java-tree.h" |
377029eb | 41 | #include "obstack.h" |
0b205f4c | 42 | #include "diagnostic-core.h" |
6599bf3a | 43 | #include "ggc.h" |
dc5e5216 | 44 | #include "langhooks-def.h" |
6599bf3a | 45 | |
dc5e5216 | 46 | static void mangle_class_field (tree); |
47 | static void mangle_vtable (tree); | |
6852521a | 48 | static void mangle_field_decl (tree); |
49 | static void mangle_method_decl (tree); | |
dc5e5216 | 50 | static void mangle_local_cni_method_decl (tree); |
6599bf3a | 51 | |
6852521a | 52 | static void mangle_type (tree); |
53 | static void mangle_pointer_type (tree); | |
54 | static void mangle_array_type (tree); | |
55 | static int mangle_record_type (tree, int); | |
6599bf3a | 56 | |
6852521a | 57 | static int find_compression_pointer_match (tree); |
58 | static int find_compression_array_match (tree); | |
59 | static int find_compression_record_match (tree, tree *); | |
60 | static int find_compression_array_template_match (tree); | |
6599bf3a | 61 | |
6852521a | 62 | static void set_type_package_list (tree); |
63 | static int entry_match_pointer_p (tree, int); | |
64 | static void emit_compression_string (int); | |
6599bf3a | 65 | |
dc5e5216 | 66 | static void init_mangling (void); |
6852521a | 67 | static tree finish_mangling (void); |
68 | static void compression_table_add (tree); | |
6599bf3a | 69 | |
6852521a | 70 | static void mangle_member_name (tree); |
6599bf3a | 71 | |
dc5e5216 | 72 | static struct obstack mangle_obstack_1; |
6599bf3a | 73 | struct obstack *mangle_obstack; |
dc5e5216 | 74 | |
6599bf3a | 75 | #define MANGLE_RAW_STRING(S) \ |
76 | obstack_grow (mangle_obstack, (S), sizeof (S)-1) | |
77 | ||
0d84bf52 | 78 | /* atms: array template mangled string. */ |
79 | static GTY(()) tree atms; | |
80 | ||
6599bf3a | 81 | /* This is the mangling interface: a decl, a class field (.class) and |
82 | the vtable. */ | |
83 | ||
dc5e5216 | 84 | void |
85 | java_mangle_decl (tree decl) | |
6599bf3a | 86 | { |
dc5e5216 | 87 | /* A copy of the check from the beginning of lhd_set_decl_assembler_name. |
88 | Only FUNCTION_DECLs and VAR_DECLs for variables with static storage | |
89 | duration need a real DECL_ASSEMBLER_NAME. */ | |
90 | gcc_assert (TREE_CODE (decl) == FUNCTION_DECL | |
91 | || (TREE_CODE (decl) == VAR_DECL | |
92 | && (TREE_STATIC (decl) | |
93 | || DECL_EXTERNAL (decl) | |
94 | || TREE_PUBLIC (decl)))); | |
95 | ||
96 | /* Mangling only applies to class members. */ | |
97 | if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))) | |
6599bf3a | 98 | { |
dc5e5216 | 99 | init_mangling (); |
100 | switch (TREE_CODE (decl)) | |
101 | { | |
102 | case VAR_DECL: | |
103 | if (DECL_LANG_SPECIFIC (decl)) | |
104 | { | |
105 | if (DECL_CLASS_FIELD_P (decl)) | |
106 | { | |
2934c6b5 | 107 | mangle_class_field (decl); |
dc5e5216 | 108 | break; |
109 | } | |
110 | else if (DECL_VTABLE_P (decl)) | |
111 | { | |
112 | mangle_vtable (DECL_CONTEXT (decl)); | |
113 | break; | |
114 | } | |
115 | } | |
116 | mangle_field_decl (decl); | |
117 | break; | |
118 | ||
119 | case FUNCTION_DECL: | |
120 | if (DECL_LANG_SPECIFIC (decl) && DECL_LOCAL_CNI_METHOD_P (decl)) | |
121 | mangle_local_cni_method_decl (decl); | |
122 | else | |
123 | mangle_method_decl (decl); | |
124 | break; | |
125 | ||
126 | default: | |
127 | gcc_unreachable (); | |
128 | } | |
129 | SET_DECL_ASSEMBLER_NAME (decl, finish_mangling ()); | |
6599bf3a | 130 | } |
dc5e5216 | 131 | else |
132 | lhd_set_decl_assembler_name (decl); | |
6599bf3a | 133 | } |
134 | ||
dc5e5216 | 135 | /* Beginning of the helper functions */ |
136 | ||
137 | static void | |
2934c6b5 | 138 | mangle_class_field (tree decl) |
6599bf3a | 139 | { |
2934c6b5 | 140 | tree type = DECL_CONTEXT (decl); |
d20d8111 | 141 | mangle_record_type (type, /* for_pointer = */ 0); |
2934c6b5 | 142 | if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE) |
143 | MANGLE_RAW_STRING ("6class$"); | |
144 | else | |
145 | MANGLE_RAW_STRING ("7class$$"); | |
6599bf3a | 146 | obstack_1grow (mangle_obstack, 'E'); |
6599bf3a | 147 | } |
148 | ||
dc5e5216 | 149 | static void |
150 | mangle_vtable (tree type) | |
6599bf3a | 151 | { |
6599bf3a | 152 | MANGLE_RAW_STRING ("TV"); |
d20d8111 | 153 | mangle_record_type (type, /* for_pointer = */ 0); |
6599bf3a | 154 | obstack_1grow (mangle_obstack, 'E'); |
6599bf3a | 155 | } |
156 | ||
6599bf3a | 157 | /* This mangles a field decl */ |
158 | ||
159 | static void | |
2883a3ed | 160 | mangle_field_decl (tree decl) |
6599bf3a | 161 | { |
6599bf3a | 162 | /* Mangle the name of the this the field belongs to */ |
d20d8111 | 163 | mangle_record_type (DECL_CONTEXT (decl), /* for_pointer = */ 0); |
6599bf3a | 164 | |
165 | /* Mangle the name of the field */ | |
bca8957b | 166 | mangle_member_name (DECL_NAME (decl)); |
6599bf3a | 167 | |
168 | /* Terminate the mangled name */ | |
169 | obstack_1grow (mangle_obstack, 'E'); | |
6599bf3a | 170 | } |
171 | ||
172 | /* This mangles a method decl, first mangling its name and then all | |
173 | its arguments. */ | |
174 | ||
175 | static void | |
2883a3ed | 176 | mangle_method_decl (tree mdecl) |
6599bf3a | 177 | { |
178 | tree method_name = DECL_NAME (mdecl); | |
179 | tree arglist; | |
6599bf3a | 180 | |
181 | /* Mangle the name of the type that contains mdecl */ | |
d20d8111 | 182 | mangle_record_type (DECL_CONTEXT (mdecl), /* for_pointer = */ 0); |
6599bf3a | 183 | |
e0ee4832 | 184 | /* Mangle the function name. There are two cases: |
6599bf3a | 185 | - mdecl is a constructor, use `C1' for its name, (denotes a |
186 | complete object constructor.) | |
187 | - mdecl is not a constructor, standard mangling is performed. | |
188 | We terminate the mangled function name with a `E'. */ | |
189 | if (ID_INIT_P (method_name)) | |
e0ee4832 | 190 | obstack_grow (mangle_obstack, "C1", 2); |
6599bf3a | 191 | else |
bca8957b | 192 | mangle_member_name (method_name); |
6599bf3a | 193 | obstack_1grow (mangle_obstack, 'E'); |
194 | ||
195 | /* We mangled type.methodName. Now onto the arguments. */ | |
196 | arglist = TYPE_ARG_TYPES (TREE_TYPE (mdecl)); | |
197 | if (TREE_CODE (TREE_TYPE (mdecl)) == METHOD_TYPE) | |
198 | arglist = TREE_CHAIN (arglist); | |
199 | ||
4c8420c9 | 200 | /* Output literal 'J' and mangle the return type IF not a |
201 | constructor. */ | |
202 | if (!ID_INIT_P (method_name)) | |
203 | { | |
204 | obstack_1grow (mangle_obstack, 'J'); | |
205 | mangle_type(TREE_TYPE(TREE_TYPE(mdecl))); | |
206 | } | |
207 | ||
6599bf3a | 208 | /* No arguments is easy. We shortcut it. */ |
209 | if (arglist == end_params_node) | |
210 | obstack_1grow (mangle_obstack, 'v'); | |
211 | else | |
212 | { | |
213 | tree arg; | |
214 | for (arg = arglist; arg != end_params_node; arg = TREE_CHAIN (arg)) | |
215 | mangle_type (TREE_VALUE (arg)); | |
216 | } | |
6599bf3a | 217 | } |
218 | ||
dc5e5216 | 219 | /* This mangles a CNI method for a local class. If the target supports |
220 | hidden aliases, then G++ will have generated one for us. It is the | |
221 | responsibility of java_mark_class_local to check target support, since | |
222 | we need to set DECL_VISIBILITY (or not) much earlier. */ | |
223 | ||
224 | static void | |
225 | mangle_local_cni_method_decl (tree decl) | |
226 | { | |
227 | MANGLE_RAW_STRING ("GA"); | |
228 | mangle_method_decl (decl); | |
229 | } | |
230 | ||
6599bf3a | 231 | /* This mangles a member name, like a function name or a field |
86523f9c | 232 | name. Handle cases were `name' is a C++ keyword. Return a nonzero |
6599bf3a | 233 | value if unicode encoding was required. */ |
234 | ||
bca8957b | 235 | static void |
2883a3ed | 236 | mangle_member_name (tree name) |
6599bf3a | 237 | { |
bca8957b | 238 | append_gpp_mangled_name (IDENTIFIER_POINTER (name), |
239 | IDENTIFIER_LENGTH (name)); | |
377029eb | 240 | } |
241 | ||
6599bf3a | 242 | /* Append the mangled name of TYPE onto OBSTACK. */ |
377029eb | 243 | |
6599bf3a | 244 | static void |
2883a3ed | 245 | mangle_type (tree type) |
6599bf3a | 246 | { |
247 | switch (TREE_CODE (type)) | |
248 | { | |
249 | char code; | |
250 | case BOOLEAN_TYPE: code = 'b'; goto primitive; | |
6599bf3a | 251 | case VOID_TYPE: code = 'v'; goto primitive; |
252 | case INTEGER_TYPE: | |
ea347d91 | 253 | if (type == char_type_node || type == promoted_char_type_node) |
254 | { | |
255 | code = 'w'; | |
256 | goto primitive; | |
257 | } | |
6599bf3a | 258 | /* Get the original type instead of the arguments promoted type. |
259 | Avoid symbol name clashes. Should call a function to do that. | |
260 | FIXME. */ | |
261 | if (type == promoted_short_type_node) | |
262 | type = short_type_node; | |
263 | if (type == promoted_byte_type_node) | |
264 | type = byte_type_node; | |
265 | switch (TYPE_PRECISION (type)) | |
266 | { | |
267 | case 8: code = 'c'; goto primitive; | |
268 | case 16: code = 's'; goto primitive; | |
269 | case 32: code = 'i'; goto primitive; | |
270 | case 64: code = 'x'; goto primitive; | |
271 | default: goto bad_type; | |
272 | } | |
273 | primitive: | |
274 | obstack_1grow (mangle_obstack, code); | |
275 | break; | |
276 | ||
277 | case REAL_TYPE: | |
278 | switch (TYPE_PRECISION (type)) | |
279 | { | |
280 | case 32: code = 'f'; goto primitive; | |
281 | case 64: code = 'd'; goto primitive; | |
282 | default: goto bad_type; | |
283 | } | |
284 | case POINTER_TYPE: | |
285 | if (TYPE_ARRAY_P (TREE_TYPE (type))) | |
286 | mangle_array_type (type); | |
287 | else | |
288 | mangle_pointer_type (type); | |
289 | break; | |
290 | bad_type: | |
291 | default: | |
bc031ffe | 292 | gcc_unreachable (); |
6599bf3a | 293 | } |
294 | } | |
295 | ||
296 | /* The compression table is a vector that keeps track of things we've | |
297 | already seen, so they can be reused. For example, java.lang.Object | |
1df33732 | 298 | would generate three entries: two package names and a type. If |
6599bf3a | 299 | java.lang.String is presented next, the java.lang will be matched |
0d84bf52 | 300 | against the first two entries (and kept for compression as S0_), and |
6599bf3a | 301 | type String would be added to the table. See mangle_record_type. |
302 | COMPRESSION_NEXT is the index to the location of the next insertion | |
303 | of an element. */ | |
304 | ||
1f3233d1 | 305 | static GTY(()) tree compression_table; |
6599bf3a | 306 | static int compression_next; |
307 | ||
308 | /* Find a POINTER_TYPE in the compression table. Use a special | |
309 | function to match pointer entries and start from the end */ | |
310 | ||
311 | static int | |
2883a3ed | 312 | find_compression_pointer_match (tree type) |
6599bf3a | 313 | { |
314 | int i; | |
315 | ||
316 | for (i = compression_next-1; i >= 0; i--) | |
317 | if (entry_match_pointer_p (type, i)) | |
318 | return i; | |
319 | return -1; | |
320 | } | |
321 | ||
322 | /* Already recorder arrays are handled like pointer as they're always | |
323 | associated with it. */ | |
324 | ||
325 | static int | |
2883a3ed | 326 | find_compression_array_match (tree type) |
6599bf3a | 327 | { |
328 | return find_compression_pointer_match (type); | |
329 | } | |
330 | ||
331 | /* Match the table of type against STRING. */ | |
332 | ||
333 | static int | |
2883a3ed | 334 | find_compression_array_template_match (tree string) |
6599bf3a | 335 | { |
336 | int i; | |
337 | for (i = 0; i < compression_next; i++) | |
338 | if (TREE_VEC_ELT (compression_table, i) == string) | |
339 | return i; | |
340 | return -1; | |
341 | } | |
342 | ||
343 | /* We go through the compression table and try to find a complete or | |
344 | partial match. The function returns the compression table entry | |
4f9026a9 | 345 | that (eventually partially) matches TYPE. *NEXT_CURRENT can be set |
6599bf3a | 346 | to the rest of TYPE to be mangled. */ |
347 | ||
348 | static int | |
2883a3ed | 349 | find_compression_record_match (tree type, tree *next_current) |
377029eb | 350 | { |
5a13b7cd | 351 | int i, match = -1; |
6d81beba | 352 | tree current, saved_current = NULL_TREE; |
377029eb | 353 | |
5a13b7cd | 354 | current = TYPE_PACKAGE_LIST (type); |
355 | ||
356 | for (i = 0; i < compression_next; i++) | |
377029eb | 357 | { |
5a13b7cd | 358 | tree compression_entry = TREE_VEC_ELT (compression_table, i); |
359 | if (current && compression_entry == TREE_PURPOSE (current)) | |
360 | { | |
361 | match = i; | |
362 | saved_current = current; | |
363 | current = TREE_CHAIN (current); | |
364 | } | |
365 | else | |
366 | /* We don't want to match an element that appears in the middle | |
367 | of a package name, so skip forward to the next complete type name. | |
368 | IDENTIFIER_NODEs (except for a "6JArray") are partial package | |
369 | names while RECORD_TYPEs represent complete type names. */ | |
370 | while (i < compression_next | |
371 | && TREE_CODE (compression_entry) == IDENTIFIER_NODE | |
372 | && compression_entry != atms) | |
373 | compression_entry = TREE_VEC_ELT (compression_table, ++i); | |
6599bf3a | 374 | } |
375 | ||
376 | if (!next_current) | |
377 | return match; | |
378 | ||
379 | /* If we have a match, set next_current to the item next to the last | |
380 | matched value. */ | |
381 | if (match >= 0) | |
382 | *next_current = TREE_CHAIN (saved_current); | |
383 | /* We had no match: we'll have to start from the beginning. */ | |
384 | if (match < 0) | |
385 | *next_current = TYPE_PACKAGE_LIST (type); | |
386 | ||
387 | return match; | |
388 | } | |
389 | ||
86523f9c | 390 | /* Mangle a record type. If a nonzero value is returned, it means |
6599bf3a | 391 | that a 'N' was emitted (so that a matching 'E' can be emitted if |
d20d8111 | 392 | necessary.) FOR_POINTER indicates that this element is for a pointer |
393 | symbol, meaning it was preceded by a 'P'. */ | |
6599bf3a | 394 | |
395 | static int | |
2883a3ed | 396 | mangle_record_type (tree type, int for_pointer) |
6599bf3a | 397 | { |
398 | tree current; | |
399 | int match; | |
400 | int nadded_p = 0; | |
d20d8111 | 401 | int qualified; |
402 | ||
403 | /* Does this name have a package qualifier? */ | |
404 | qualified = QUALIFIED_P (DECL_NAME (TYPE_NAME (type))); | |
6599bf3a | 405 | |
406 | #define ADD_N() \ | |
407 | do { obstack_1grow (mangle_obstack, 'N'); nadded_p = 1; } while (0) | |
408 | ||
bc031ffe | 409 | gcc_assert (TREE_CODE (type) == RECORD_TYPE); |
6599bf3a | 410 | |
411 | if (!TYPE_PACKAGE_LIST (type)) | |
412 | set_type_package_list (type); | |
413 | ||
414 | match = find_compression_record_match (type, ¤t); | |
415 | if (match >= 0) | |
416 | { | |
417 | /* If we had a pointer, and there's more, we need to emit | |
d20d8111 | 418 | 'N' after 'P' (for_pointer tells us we already emitted it.) */ |
419 | if (for_pointer && current) | |
6599bf3a | 420 | ADD_N(); |
421 | emit_compression_string (match); | |
377029eb | 422 | } |
6599bf3a | 423 | while (current) |
377029eb | 424 | { |
6599bf3a | 425 | /* Add the new type to the table */ |
426 | compression_table_add (TREE_PURPOSE (current)); | |
d20d8111 | 427 | /* Add 'N' if we never got a chance to, but only if we have a qualified |
428 | name. For non-pointer elements, the name is always qualified. */ | |
429 | if ((qualified || !for_pointer) && !nadded_p) | |
6599bf3a | 430 | ADD_N(); |
431 | /* Use the bare type name for the mangle. */ | |
432 | append_gpp_mangled_name (IDENTIFIER_POINTER (TREE_VALUE (current)), | |
433 | IDENTIFIER_LENGTH (TREE_VALUE (current))); | |
434 | current = TREE_CHAIN (current); | |
435 | } | |
436 | return nadded_p; | |
437 | #undef ADD_N | |
438 | } | |
439 | ||
440 | /* Mangle a pointer type. There are two cases: the pointer is already | |
4f9026a9 | 441 | in the compression table: the compression is emitted sans 'P' |
6599bf3a | 442 | indicator. Otherwise, a 'P' is emitted and, depending on the type, |
443 | a partial compression or/plus the rest of the mangling. */ | |
444 | ||
445 | static void | |
2883a3ed | 446 | mangle_pointer_type (tree type) |
6599bf3a | 447 | { |
448 | int match; | |
449 | tree pointer_type; | |
450 | ||
451 | /* Search for the type already in the compression table */ | |
452 | if ((match = find_compression_pointer_match (type)) >= 0) | |
453 | { | |
454 | emit_compression_string (match); | |
455 | return; | |
377029eb | 456 | } |
6599bf3a | 457 | |
458 | /* This didn't work. We start by mangling the pointed-to type */ | |
459 | pointer_type = type; | |
460 | type = TREE_TYPE (type); | |
bc031ffe | 461 | gcc_assert (TREE_CODE (type) == RECORD_TYPE); |
6599bf3a | 462 | |
463 | obstack_1grow (mangle_obstack, 'P'); | |
464 | if (mangle_record_type (type, /* for_pointer = */ 1)) | |
465 | obstack_1grow (mangle_obstack, 'E'); | |
466 | ||
467 | /* Don't forget to insert the pointer type in the table */ | |
468 | compression_table_add (pointer_type); | |
469 | } | |
470 | ||
471 | /* Mangle an array type. Search for an easy solution first, then go | |
472 | through the process of finding out whether the bare array type or even | |
0d84bf52 | 473 | the template indicator were already used and compressed appropriately. |
6599bf3a | 474 | It handles pointers. */ |
475 | ||
476 | static void | |
2883a3ed | 477 | mangle_array_type (tree p_type) |
6599bf3a | 478 | { |
6599bf3a | 479 | tree type, elt_type; |
480 | int match; | |
481 | ||
482 | type = TREE_TYPE (p_type); | |
bc031ffe | 483 | gcc_assert (type); |
f060a027 | 484 | |
6599bf3a | 485 | elt_type = TYPE_ARRAY_ELEMENT (type); |
486 | ||
487 | /* We cache a bit of the Jarray <> mangle. */ | |
488 | if (!atms) | |
489 | { | |
490 | atms = get_identifier ("6JArray"); | |
6599bf3a | 491 | } |
492 | ||
0d84bf52 | 493 | /* Maybe we have what we're looking for in the compression table. */ |
6599bf3a | 494 | if ((match = find_compression_array_match (p_type)) >= 0) |
495 | { | |
496 | emit_compression_string (match); | |
497 | return; | |
498 | } | |
499 | ||
500 | /* We know for a fact that all arrays are pointers */ | |
501 | obstack_1grow (mangle_obstack, 'P'); | |
502 | /* Maybe we already have a Jarray<t> somewhere. PSx_ will be enough. */ | |
503 | if ((match = find_compression_record_match (type, NULL)) > 0) | |
504 | { | |
505 | emit_compression_string (match); | |
506 | return; | |
507 | } | |
508 | ||
509 | /* Maybe we already have just JArray somewhere */ | |
510 | if ((match = find_compression_array_template_match (atms)) > 0) | |
511 | emit_compression_string (match); | |
512 | else | |
377029eb | 513 | { |
6599bf3a | 514 | /* Start the template mangled name */ |
515 | obstack_grow (mangle_obstack, | |
516 | IDENTIFIER_POINTER (atms), IDENTIFIER_LENGTH (atms)); | |
517 | /* Insert in the compression table */ | |
518 | compression_table_add (atms); | |
519 | } | |
520 | ||
521 | /* Mangle Jarray <elt_type> */ | |
522 | obstack_1grow (mangle_obstack, 'I'); | |
523 | mangle_type (elt_type); | |
524 | obstack_1grow (mangle_obstack, 'E'); | |
525 | ||
526 | /* Add `Jarray <elt_type>' and `Jarray <elt_type> *' to the table */ | |
527 | compression_table_add (type); | |
528 | compression_table_add (p_type); | |
529 | } | |
530 | ||
4f9026a9 | 531 | /* Write a substitution string for entry I. Substitution string starts a |
ce2012e7 | 532 | -1 (encoded S_.) The base is 36, and the code shamelessly taken from |
6599bf3a | 533 | cp/mangle.c. */ |
534 | ||
535 | static void | |
536 | emit_compression_string (int i) | |
537 | { | |
538 | i -= 1; /* Adjust */ | |
539 | obstack_1grow (mangle_obstack, 'S'); | |
540 | if (i >= 0) | |
541 | { | |
542 | static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
543 | unsigned HOST_WIDE_INT n; | |
544 | unsigned HOST_WIDE_INT m=1; | |
545 | /* How many digits for I in base 36? */ | |
546 | for (n = i; n >= 36; n /= 36, m *=36); | |
547 | /* Write the digits out */ | |
548 | while (m > 0) | |
377029eb | 549 | { |
6599bf3a | 550 | int digit = i / m; |
551 | obstack_1grow (mangle_obstack, digits [digit]); | |
552 | i -= digit * m; | |
553 | m /= 36; | |
554 | } | |
555 | } | |
556 | obstack_1grow (mangle_obstack, '_'); | |
557 | } | |
558 | ||
559 | /* If search the compression table at index I for a pointer type | |
560 | equivalent to TYPE (meaning that after all the indirection, which | |
561 | might all be unique, we find the same RECORD_TYPE.) */ | |
562 | ||
563 | static int | |
2883a3ed | 564 | entry_match_pointer_p (tree type, int i) |
6599bf3a | 565 | { |
566 | tree t = TREE_VEC_ELT (compression_table, i); | |
567 | ||
568 | while (TREE_CODE (type) == POINTER_TYPE | |
569 | && TREE_CODE (t) == POINTER_TYPE) | |
570 | { | |
571 | t = TREE_TYPE (t); | |
572 | type = TREE_TYPE (type); | |
573 | } | |
574 | return (TREE_CODE (type) == RECORD_TYPE | |
575 | && TREE_CODE (t) == RECORD_TYPE | |
576 | && t == type); | |
577 | } | |
578 | ||
579 | /* Go through all qualification of type and build a list of list node | |
580 | elements containings as a purpose what should be used for a match and | |
581 | inserted in the compression table; and as it value the raw name of the | |
582 | part. The result is stored in TYPE_PACKAGE_LIST to be reused. */ | |
583 | ||
584 | static void | |
2883a3ed | 585 | set_type_package_list (tree type) |
6599bf3a | 586 | { |
587 | int i; | |
588 | const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); | |
920a6d94 | 589 | const char *ptr; |
6599bf3a | 590 | int qualifications; |
591 | tree list = NULL_TREE, elt; | |
592 | ||
920a6d94 | 593 | for (ptr = type_string, qualifications = 0; *ptr; ptr++) |
6599bf3a | 594 | if (*ptr == '.') |
595 | qualifications += 1; | |
596 | ||
920a6d94 | 597 | for (ptr = type_string, i = 0; i < qualifications; ptr++) |
6599bf3a | 598 | { |
599 | if (ptr [0] == '.') | |
600 | { | |
920a6d94 | 601 | tree const identifier |
602 | = get_identifier_with_length (type_string, ptr - type_string); | |
603 | ||
6599bf3a | 604 | elt = build_tree_list (identifier, identifier); |
605 | TREE_CHAIN (elt) = list; | |
606 | list = elt; | |
607 | type_string = ptr+1; | |
608 | i += 1; | |
377029eb | 609 | } |
610 | } | |
6599bf3a | 611 | |
612 | elt = build_tree_list (type, get_identifier (type_string)); | |
613 | TREE_CHAIN (elt) = list; | |
614 | list = elt; | |
615 | TYPE_PACKAGE_LIST (type) = nreverse (list); | |
616 | } | |
617 | ||
618 | /* Add TYPE as the last element of the compression table. Resize the | |
619 | compression table if necessary. */ | |
620 | ||
621 | static void | |
2883a3ed | 622 | compression_table_add (tree type) |
6599bf3a | 623 | { |
624 | if (compression_next == TREE_VEC_LENGTH (compression_table)) | |
625 | { | |
ead29d98 | 626 | tree new_table = make_tree_vec (2*compression_next); |
6599bf3a | 627 | int i; |
628 | ||
629 | for (i = 0; i < compression_next; i++) | |
ead29d98 | 630 | TREE_VEC_ELT (new_table, i) = TREE_VEC_ELT (compression_table, i); |
6599bf3a | 631 | |
ead29d98 | 632 | compression_table = new_table; |
6599bf3a | 633 | } |
634 | TREE_VEC_ELT (compression_table, compression_next++) = type; | |
635 | } | |
636 | ||
0ac26f75 | 637 | /* Mangle an embedded resource file name. "_ZGr" is the prefix. A |
638 | '_' is prepended to the name so that names starting with a digit | |
639 | can be demangled. The length and then the resulting name itself | |
640 | are appended while escaping '$', '.', and '/' to: "$$", "$_", and | |
641 | "$S". */ | |
642 | ||
643 | tree | |
644 | java_mangle_resource_name (const char *name) | |
645 | { | |
646 | int len = strlen (name); | |
647 | char *buf = (char *) alloca (2 * len + 1); | |
648 | char *pos; | |
649 | const unsigned char *w1 = (const unsigned char *) name; | |
650 | const unsigned char *w2; | |
651 | const unsigned char *limit = w1 + len; | |
652 | ||
653 | pos = buf; | |
654 | ||
655 | init_mangling (); | |
656 | MANGLE_RAW_STRING ("Gr"); | |
657 | ||
658 | *pos++ = '_'; | |
659 | while (w1 < limit) | |
660 | { | |
661 | int ch; | |
662 | w2 = w1; | |
663 | ch = UTF8_GET (w1, limit); | |
664 | gcc_assert (ch > 0); | |
665 | switch (ch) | |
666 | { | |
667 | case '$': | |
668 | *pos++ = '$'; | |
669 | *pos++ = '$'; | |
670 | break; | |
671 | case '.': | |
672 | *pos++ = '$'; | |
673 | *pos++ = '_'; | |
674 | break; | |
675 | case '/': | |
676 | *pos++ = '$'; | |
677 | *pos++ = 'S'; | |
678 | break; | |
679 | default: | |
680 | memcpy (pos, w2, w1 - w2); | |
681 | pos += w1 - w2; | |
682 | break; | |
683 | } | |
684 | } | |
685 | append_gpp_mangled_name (buf, pos - buf); | |
686 | ||
687 | return finish_mangling (); | |
688 | } | |
689 | ||
6599bf3a | 690 | /* Mangling initialization routine. */ |
691 | ||
692 | static void | |
dc5e5216 | 693 | init_mangling (void) |
6599bf3a | 694 | { |
dc5e5216 | 695 | if (!mangle_obstack) |
696 | { | |
697 | mangle_obstack = &mangle_obstack_1; | |
698 | gcc_obstack_init (mangle_obstack); | |
699 | } | |
700 | ||
701 | gcc_assert (compression_table == NULL); | |
702 | compression_table = make_tree_vec (10); | |
6599bf3a | 703 | |
704 | /* Mangled name are to be suffixed */ | |
dc5e5216 | 705 | MANGLE_RAW_STRING ("_Z"); |
6599bf3a | 706 | } |
707 | ||
708 | /* Mangling finalization routine. The mangled name is returned as a | |
709 | IDENTIFIER_NODE. */ | |
710 | ||
711 | static tree | |
2883a3ed | 712 | finish_mangling (void) |
6599bf3a | 713 | { |
714 | tree result; | |
715 | ||
dc5e5216 | 716 | gcc_assert (compression_table); |
6599bf3a | 717 | |
6599bf3a | 718 | compression_table = NULL_TREE; |
719 | compression_next = 0; | |
720 | obstack_1grow (mangle_obstack, '\0'); | |
cc0a8c77 | 721 | result = get_identifier ((char *) obstack_base (mangle_obstack)); |
6599bf3a | 722 | obstack_free (mangle_obstack, obstack_base (mangle_obstack)); |
dc5e5216 | 723 | |
6599bf3a | 724 | return result; |
377029eb | 725 | } |
1f3233d1 | 726 | |
727 | #include "gt-java-mangle.h" |