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