]>
Commit | Line | Data |
---|---|---|
bb2ec1b3 TT |
1 | /* Convert symbols from GDB to GCC |
2 | ||
1d506c26 | 3 | Copyright (C) 2014-2024 Free Software Foundation, Inc. |
bb2ec1b3 TT |
4 | |
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | ||
21 | #include "defs.h" | |
22 | #include "compile-internal.h" | |
b7dc48b4 | 23 | #include "compile-c.h" |
bb2ec1b3 TT |
24 | #include "symtab.h" |
25 | #include "parser-defs.h" | |
26 | #include "block.h" | |
27 | #include "objfiles.h" | |
28 | #include "compile.h" | |
29 | #include "value.h" | |
30 | #include "exceptions.h" | |
31 | #include "gdbtypes.h" | |
82ca8957 | 32 | #include "dwarf2/loc.h" |
99d9c3b9 | 33 | #include "inferior.h" |
bb2ec1b3 | 34 | |
bb2ec1b3 | 35 | |
bb2ec1b3 TT |
36 | /* Compute the name of the pointer representing a local symbol's |
37 | address. */ | |
38 | ||
946d3d10 | 39 | gdb::unique_xmalloc_ptr<char> |
6f36b6d2 | 40 | c_symbol_substitution_name (struct symbol *sym) |
bb2ec1b3 | 41 | { |
8f84fb0e | 42 | return gdb::unique_xmalloc_ptr<char> |
987012b8 | 43 | (concat ("__", sym->natural_name (), "_ptr", (char *) NULL)); |
bb2ec1b3 TT |
44 | } |
45 | ||
46 | /* Convert a given symbol, SYM, to the compiler's representation. | |
47 | CONTEXT is the compiler instance. IS_GLOBAL is true if the | |
48 | symbol came from the global scope. IS_LOCAL is true if the symbol | |
49 | came from a local scope. (Note that the two are not strictly | |
50 | inverses because the symbol might have come from the static | |
51 | scope.) */ | |
52 | ||
53 | static void | |
9cdfd9a2 | 54 | convert_one_symbol (compile_c_instance *context, |
63e43d3a | 55 | struct block_symbol sym, |
bb2ec1b3 TT |
56 | int is_global, |
57 | int is_local) | |
58 | { | |
59 | gcc_type sym_type; | |
4206d69e | 60 | const char *filename = sym.symbol->symtab ()->filename; |
72a8f763 | 61 | unsigned int line = sym.symbol->line (); |
bb2ec1b3 | 62 | |
9cdfd9a2 | 63 | context->error_symbol_once (sym.symbol); |
bb2ec1b3 | 64 | |
66d7f48f | 65 | if (sym.symbol->aclass () == LOC_LABEL) |
bb2ec1b3 TT |
66 | sym_type = 0; |
67 | else | |
5f9c5a63 | 68 | sym_type = context->convert_type (sym.symbol->type ()); |
bb2ec1b3 | 69 | |
6c9c307c | 70 | if (sym.symbol->domain () == STRUCT_DOMAIN) |
bb2ec1b3 TT |
71 | { |
72 | /* Binding a tag, so we don't need to build a decl. */ | |
987012b8 | 73 | context->plugin ().tagbind (sym.symbol->natural_name (), |
18cdc6d8 | 74 | sym_type, filename, line); |
bb2ec1b3 TT |
75 | } |
76 | else | |
77 | { | |
78 | gcc_decl decl; | |
79 | enum gcc_c_symbol_kind kind; | |
80 | CORE_ADDR addr = 0; | |
8f84fb0e | 81 | gdb::unique_xmalloc_ptr<char> symbol_name; |
bb2ec1b3 | 82 | |
66d7f48f | 83 | switch (sym.symbol->aclass ()) |
bb2ec1b3 TT |
84 | { |
85 | case LOC_TYPEDEF: | |
86 | kind = GCC_C_SYMBOL_TYPEDEF; | |
87 | break; | |
88 | ||
89 | case LOC_LABEL: | |
90 | kind = GCC_C_SYMBOL_LABEL; | |
4aeddc50 | 91 | addr = sym.symbol->value_address (); |
bb2ec1b3 TT |
92 | break; |
93 | ||
94 | case LOC_BLOCK: | |
95 | kind = GCC_C_SYMBOL_FUNCTION; | |
6395b628 | 96 | addr = sym.symbol->value_block ()->entry_pc (); |
5f9c5a63 | 97 | if (is_global && sym.symbol->type ()->is_gnu_ifunc ()) |
99d9c3b9 | 98 | addr = gnu_ifunc_resolve_addr (current_inferior ()->arch (), addr); |
bb2ec1b3 TT |
99 | break; |
100 | ||
101 | case LOC_CONST: | |
5f9c5a63 | 102 | if (sym.symbol->type ()->code () == TYPE_CODE_ENUM) |
bb2ec1b3 TT |
103 | { |
104 | /* Already handled by convert_enum. */ | |
105 | return; | |
106 | } | |
9cdfd9a2 | 107 | context->plugin ().build_constant |
987012b8 | 108 | (sym_type, sym.symbol->natural_name (), |
4aeddc50 | 109 | sym.symbol->value_longest (), |
63e43d3a | 110 | filename, line); |
bb2ec1b3 TT |
111 | return; |
112 | ||
113 | case LOC_CONST_BYTES: | |
114 | error (_("Unsupported LOC_CONST_BYTES for symbol \"%s\"."), | |
987012b8 | 115 | sym.symbol->print_name ()); |
bb2ec1b3 TT |
116 | |
117 | case LOC_UNDEF: | |
f34652de | 118 | internal_error (_("LOC_UNDEF found for \"%s\"."), |
987012b8 | 119 | sym.symbol->print_name ()); |
bb2ec1b3 TT |
120 | |
121 | case LOC_COMMON_BLOCK: | |
122 | error (_("Fortran common block is unsupported for compilation " | |
123 | "evaluaton of symbol \"%s\"."), | |
987012b8 | 124 | sym.symbol->print_name ()); |
bb2ec1b3 TT |
125 | |
126 | case LOC_OPTIMIZED_OUT: | |
127 | error (_("Symbol \"%s\" cannot be used for compilation evaluation " | |
128 | "as it is optimized out."), | |
987012b8 | 129 | sym.symbol->print_name ()); |
bb2ec1b3 TT |
130 | |
131 | case LOC_COMPUTED: | |
132 | if (is_local) | |
133 | goto substitution; | |
134 | /* Probably TLS here. */ | |
135 | warning (_("Symbol \"%s\" is thread-local and currently can only " | |
136 | "be referenced from the current thread in " | |
137 | "compiled code."), | |
987012b8 | 138 | sym.symbol->print_name ()); |
d182e398 | 139 | [[fallthrough]]; |
bb2ec1b3 TT |
140 | case LOC_UNRESOLVED: |
141 | /* 'symbol_name' cannot be used here as that one is used only for | |
142 | local variables from compile_dwarf_expr_to_c. | |
143 | Global variables can be accessed by GCC only by their address, not | |
144 | by their name. */ | |
145 | { | |
146 | struct value *val; | |
bd2b40ac | 147 | frame_info_ptr frame = NULL; |
bb2ec1b3 | 148 | |
63e43d3a | 149 | if (symbol_read_needs_frame (sym.symbol)) |
bb2ec1b3 TT |
150 | { |
151 | frame = get_selected_frame (NULL); | |
152 | if (frame == NULL) | |
153 | error (_("Symbol \"%s\" cannot be used because " | |
154 | "there is no selected frame"), | |
987012b8 | 155 | sym.symbol->print_name ()); |
bb2ec1b3 TT |
156 | } |
157 | ||
63e43d3a | 158 | val = read_var_value (sym.symbol, sym.block, frame); |
736355f2 | 159 | if (val->lval () != lval_memory) |
bb2ec1b3 TT |
160 | error (_("Symbol \"%s\" cannot be used for compilation " |
161 | "evaluation as its address has not been found."), | |
987012b8 | 162 | sym.symbol->print_name ()); |
bb2ec1b3 TT |
163 | |
164 | kind = GCC_C_SYMBOL_VARIABLE; | |
9feb2d07 | 165 | addr = val->address (); |
bb2ec1b3 TT |
166 | } |
167 | break; | |
168 | ||
169 | ||
170 | case LOC_REGISTER: | |
171 | case LOC_ARG: | |
172 | case LOC_REF_ARG: | |
173 | case LOC_REGPARM_ADDR: | |
174 | case LOC_LOCAL: | |
175 | substitution: | |
176 | kind = GCC_C_SYMBOL_VARIABLE; | |
6f36b6d2 | 177 | symbol_name = c_symbol_substitution_name (sym.symbol); |
bb2ec1b3 TT |
178 | break; |
179 | ||
180 | case LOC_STATIC: | |
181 | kind = GCC_C_SYMBOL_VARIABLE; | |
4aeddc50 | 182 | addr = sym.symbol->value_address (); |
bb2ec1b3 TT |
183 | break; |
184 | ||
185 | case LOC_FINAL_VALUE: | |
186 | default: | |
187 | gdb_assert_not_reached ("Unreachable case in convert_one_symbol."); | |
188 | ||
189 | } | |
190 | ||
191 | /* Don't emit local variable decls for a raw expression. */ | |
9cdfd9a2 | 192 | if (context->scope () != COMPILE_I_RAW_SCOPE |
bb2ec1b3 TT |
193 | || symbol_name == NULL) |
194 | { | |
9cdfd9a2 | 195 | decl = context->plugin ().build_decl |
987012b8 | 196 | (sym.symbol->natural_name (), |
63e43d3a PMR |
197 | kind, |
198 | sym_type, | |
8f84fb0e | 199 | symbol_name.get (), addr, |
63e43d3a | 200 | filename, line); |
bb2ec1b3 | 201 | |
9cdfd9a2 | 202 | context->plugin ().bind (decl, is_global); |
bb2ec1b3 | 203 | } |
bb2ec1b3 TT |
204 | } |
205 | } | |
206 | ||
207 | /* Convert a full symbol to its gcc form. CONTEXT is the compiler to | |
208 | use, IDENTIFIER is the name of the symbol, SYM is the symbol | |
209 | itself, and DOMAIN is the domain which was searched. */ | |
210 | ||
211 | static void | |
9cdfd9a2 | 212 | convert_symbol_sym (compile_c_instance *context, const char *identifier, |
d12307c1 | 213 | struct block_symbol sym, domain_enum domain) |
bb2ec1b3 | 214 | { |
bb2ec1b3 TT |
215 | int is_local_symbol; |
216 | ||
bb2ec1b3 TT |
217 | /* If we found a symbol and it is not in the static or global |
218 | scope, then we should first convert any static or global scope | |
219 | symbol of the same name. This lets this unusual case work: | |
220 | ||
221 | int x; // Global. | |
222 | int func(void) | |
223 | { | |
224 | int x; | |
225 | // At this spot, evaluate "extern int x; x" | |
226 | } | |
227 | */ | |
228 | ||
78004096 TT |
229 | const struct block *static_block = nullptr; |
230 | if (sym.block != nullptr) | |
d24e14a0 | 231 | static_block = sym.block->static_block (); |
bb2ec1b3 | 232 | /* STATIC_BLOCK is NULL if FOUND_BLOCK is the global block. */ |
d12307c1 | 233 | is_local_symbol = (sym.block != static_block && static_block != NULL); |
bb2ec1b3 TT |
234 | if (is_local_symbol) |
235 | { | |
d12307c1 | 236 | struct block_symbol global_sym; |
bb2ec1b3 TT |
237 | |
238 | global_sym = lookup_symbol (identifier, NULL, domain, NULL); | |
239 | /* If the outer symbol is in the static block, we ignore it, as | |
240 | it cannot be referenced. */ | |
d12307c1 | 241 | if (global_sym.symbol != NULL |
d24e14a0 | 242 | && global_sym.block != global_sym.block->static_block ()) |
bb2ec1b3 TT |
243 | { |
244 | if (compile_debug) | |
6cb06a8c TT |
245 | gdb_printf (gdb_stdlog, |
246 | "gcc_convert_symbol \"%s\": global symbol\n", | |
247 | identifier); | |
63e43d3a | 248 | convert_one_symbol (context, global_sym, 1, 0); |
bb2ec1b3 TT |
249 | } |
250 | } | |
251 | ||
252 | if (compile_debug) | |
6cb06a8c TT |
253 | gdb_printf (gdb_stdlog, |
254 | "gcc_convert_symbol \"%s\": local symbol\n", | |
255 | identifier); | |
63e43d3a | 256 | convert_one_symbol (context, sym, 0, is_local_symbol); |
bb2ec1b3 TT |
257 | } |
258 | ||
259 | /* Convert a minimal symbol to its gcc form. CONTEXT is the compiler | |
260 | to use and BMSYM is the minimal symbol to convert. */ | |
261 | ||
262 | static void | |
9cdfd9a2 | 263 | convert_symbol_bmsym (compile_c_instance *context, |
bb2ec1b3 TT |
264 | struct bound_minimal_symbol bmsym) |
265 | { | |
266 | struct minimal_symbol *msym = bmsym.minsym; | |
267 | struct objfile *objfile = bmsym.objfile; | |
268 | struct type *type; | |
269 | enum gcc_c_symbol_kind kind; | |
270 | gcc_type sym_type; | |
271 | gcc_decl decl; | |
272 | CORE_ADDR addr; | |
273 | ||
4aeddc50 | 274 | addr = msym->value_address (objfile); |
081a1c2c | 275 | |
bb2ec1b3 | 276 | /* Conversion copied from write_exp_msymbol. */ |
60f62e2b | 277 | switch (msym->type ()) |
bb2ec1b3 TT |
278 | { |
279 | case mst_text: | |
280 | case mst_file_text: | |
281 | case mst_solib_trampoline: | |
a8ed3dde | 282 | type = builtin_type (objfile)->nodebug_text_symbol; |
bb2ec1b3 TT |
283 | kind = GCC_C_SYMBOL_FUNCTION; |
284 | break; | |
285 | ||
286 | case mst_text_gnu_ifunc: | |
a8ed3dde | 287 | type = builtin_type (objfile)->nodebug_text_gnu_ifunc_symbol; |
bb2ec1b3 | 288 | kind = GCC_C_SYMBOL_FUNCTION; |
99d9c3b9 | 289 | addr = gnu_ifunc_resolve_addr (current_inferior ()->arch (), addr); |
bb2ec1b3 TT |
290 | break; |
291 | ||
292 | case mst_data: | |
293 | case mst_file_data: | |
294 | case mst_bss: | |
295 | case mst_file_bss: | |
a8ed3dde | 296 | type = builtin_type (objfile)->nodebug_data_symbol; |
bb2ec1b3 TT |
297 | kind = GCC_C_SYMBOL_VARIABLE; |
298 | break; | |
299 | ||
300 | case mst_slot_got_plt: | |
a8ed3dde | 301 | type = builtin_type (objfile)->nodebug_got_plt_symbol; |
bb2ec1b3 TT |
302 | kind = GCC_C_SYMBOL_FUNCTION; |
303 | break; | |
304 | ||
305 | default: | |
a8ed3dde | 306 | type = builtin_type (objfile)->nodebug_unknown_symbol; |
bb2ec1b3 TT |
307 | kind = GCC_C_SYMBOL_VARIABLE; |
308 | break; | |
309 | } | |
310 | ||
9cdfd9a2 | 311 | sym_type = context->convert_type (type); |
c9d95fa3 | 312 | decl = context->plugin ().build_decl (msym->natural_name (), |
18cdc6d8 KS |
313 | kind, sym_type, NULL, addr, |
314 | NULL, 0); | |
9cdfd9a2 | 315 | context->plugin ().bind (decl, 1 /* is_global */); |
bb2ec1b3 TT |
316 | } |
317 | ||
318 | /* See compile-internal.h. */ | |
319 | ||
320 | void | |
321 | gcc_convert_symbol (void *datum, | |
322 | struct gcc_c_context *gcc_context, | |
323 | enum gcc_c_oracle_request request, | |
324 | const char *identifier) | |
325 | { | |
9cdfd9a2 KS |
326 | compile_c_instance *context |
327 | = static_cast<compile_c_instance *> (datum); | |
bb2ec1b3 | 328 | domain_enum domain; |
bb2ec1b3 TT |
329 | int found = 0; |
330 | ||
331 | switch (request) | |
332 | { | |
333 | case GCC_C_ORACLE_SYMBOL: | |
334 | domain = VAR_DOMAIN; | |
335 | break; | |
336 | case GCC_C_ORACLE_TAG: | |
337 | domain = STRUCT_DOMAIN; | |
338 | break; | |
339 | case GCC_C_ORACLE_LABEL: | |
340 | domain = LABEL_DOMAIN; | |
341 | break; | |
342 | default: | |
343 | gdb_assert_not_reached ("Unrecognized oracle request."); | |
344 | } | |
345 | ||
346 | /* We can't allow exceptions to escape out of this callback. Safest | |
347 | is to simply emit a gcc error. */ | |
a70b8144 | 348 | try |
bb2ec1b3 | 349 | { |
d12307c1 | 350 | struct block_symbol sym; |
bb2ec1b3 | 351 | |
9cdfd9a2 | 352 | sym = lookup_symbol (identifier, context->block (), domain, NULL); |
d12307c1 | 353 | if (sym.symbol != NULL) |
bb2ec1b3 TT |
354 | { |
355 | convert_symbol_sym (context, identifier, sym, domain); | |
356 | found = 1; | |
357 | } | |
358 | else if (domain == VAR_DOMAIN) | |
359 | { | |
360 | struct bound_minimal_symbol bmsym; | |
361 | ||
362 | bmsym = lookup_minimal_symbol (identifier, NULL, NULL); | |
363 | if (bmsym.minsym != NULL) | |
364 | { | |
365 | convert_symbol_bmsym (context, bmsym); | |
366 | found = 1; | |
367 | } | |
368 | } | |
369 | } | |
370 | ||
230d2906 | 371 | catch (const gdb_exception &e) |
492d29ea | 372 | { |
3d6e9d23 | 373 | context->plugin ().error (e.what ()); |
492d29ea | 374 | } |
bb2ec1b3 TT |
375 | |
376 | if (compile_debug && !found) | |
6cb06a8c TT |
377 | gdb_printf (gdb_stdlog, |
378 | "gcc_convert_symbol \"%s\": lookup_symbol failed\n", | |
379 | identifier); | |
bb2ec1b3 TT |
380 | return; |
381 | } | |
382 | ||
383 | /* See compile-internal.h. */ | |
384 | ||
385 | gcc_address | |
386 | gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context, | |
387 | const char *identifier) | |
388 | { | |
9cdfd9a2 KS |
389 | compile_c_instance *context |
390 | = static_cast<compile_c_instance *> (datum); | |
bb2ec1b3 TT |
391 | gcc_address result = 0; |
392 | int found = 0; | |
393 | ||
394 | /* We can't allow exceptions to escape out of this callback. Safest | |
395 | is to simply emit a gcc error. */ | |
a70b8144 | 396 | try |
bb2ec1b3 TT |
397 | { |
398 | struct symbol *sym; | |
399 | ||
400 | /* We only need global functions here. */ | |
d12307c1 | 401 | sym = lookup_symbol (identifier, NULL, VAR_DOMAIN, NULL).symbol; |
66d7f48f | 402 | if (sym != NULL && sym->aclass () == LOC_BLOCK) |
bb2ec1b3 TT |
403 | { |
404 | if (compile_debug) | |
6cb06a8c TT |
405 | gdb_printf (gdb_stdlog, |
406 | "gcc_symbol_address \"%s\": full symbol\n", | |
407 | identifier); | |
6395b628 | 408 | result = sym->value_block ()->entry_pc (); |
5f9c5a63 | 409 | if (sym->type ()->is_gnu_ifunc ()) |
99d9c3b9 SM |
410 | result = gnu_ifunc_resolve_addr (current_inferior ()->arch (), |
411 | result); | |
bb2ec1b3 TT |
412 | found = 1; |
413 | } | |
414 | else | |
415 | { | |
416 | struct bound_minimal_symbol msym; | |
417 | ||
418 | msym = lookup_bound_minimal_symbol (identifier); | |
419 | if (msym.minsym != NULL) | |
420 | { | |
421 | if (compile_debug) | |
6cb06a8c TT |
422 | gdb_printf (gdb_stdlog, |
423 | "gcc_symbol_address \"%s\": minimal " | |
424 | "symbol\n", | |
425 | identifier); | |
4aeddc50 | 426 | result = msym.value_address (); |
60f62e2b | 427 | if (msym.minsym->type () == mst_text_gnu_ifunc) |
99d9c3b9 SM |
428 | result = gnu_ifunc_resolve_addr (current_inferior ()->arch (), |
429 | result); | |
bb2ec1b3 TT |
430 | found = 1; |
431 | } | |
432 | } | |
433 | } | |
434 | ||
230d2906 | 435 | catch (const gdb_exception_error &e) |
492d29ea | 436 | { |
3d6e9d23 | 437 | context->plugin ().error (e.what ()); |
492d29ea | 438 | } |
bb2ec1b3 TT |
439 | |
440 | if (compile_debug && !found) | |
6cb06a8c TT |
441 | gdb_printf (gdb_stdlog, |
442 | "gcc_symbol_address \"%s\": failed\n", | |
443 | identifier); | |
bb2ec1b3 TT |
444 | return result; |
445 | } | |
446 | ||
447 | \f | |
448 | ||
449 | /* A hash function for symbol names. */ | |
450 | ||
451 | static hashval_t | |
452 | hash_symname (const void *a) | |
453 | { | |
9a3c8263 | 454 | const struct symbol *sym = (const struct symbol *) a; |
bb2ec1b3 | 455 | |
987012b8 | 456 | return htab_hash_string (sym->natural_name ()); |
bb2ec1b3 TT |
457 | } |
458 | ||
459 | /* A comparison function for hash tables that just looks at symbol | |
460 | names. */ | |
461 | ||
462 | static int | |
463 | eq_symname (const void *a, const void *b) | |
464 | { | |
9a3c8263 SM |
465 | const struct symbol *syma = (const struct symbol *) a; |
466 | const struct symbol *symb = (const struct symbol *) b; | |
bb2ec1b3 | 467 | |
987012b8 | 468 | return strcmp (syma->natural_name (), symb->natural_name ()) == 0; |
bb2ec1b3 TT |
469 | } |
470 | ||
471 | /* If a symbol with the same name as SYM is already in HASHTAB, return | |
472 | 1. Otherwise, add SYM to HASHTAB and return 0. */ | |
473 | ||
474 | static int | |
475 | symbol_seen (htab_t hashtab, struct symbol *sym) | |
476 | { | |
477 | void **slot; | |
478 | ||
479 | slot = htab_find_slot (hashtab, sym, INSERT); | |
480 | if (*slot != NULL) | |
481 | return 1; | |
482 | ||
483 | *slot = sym; | |
484 | return 0; | |
485 | } | |
486 | ||
487 | /* Generate C code to compute the length of a VLA. */ | |
488 | ||
489 | static void | |
9cdfd9a2 | 490 | generate_vla_size (compile_instance *compiler, |
d82b3862 | 491 | string_file *stream, |
bb2ec1b3 | 492 | struct gdbarch *gdbarch, |
3637a558 | 493 | std::vector<bool> ®isters_used, |
bb2ec1b3 TT |
494 | CORE_ADDR pc, |
495 | struct type *type, | |
496 | struct symbol *sym) | |
497 | { | |
498 | type = check_typedef (type); | |
499 | ||
aa006118 | 500 | if (TYPE_IS_REFERENCE (type)) |
27710edb | 501 | type = check_typedef (type->target_type ()); |
bb2ec1b3 | 502 | |
78134374 | 503 | switch (type->code ()) |
bb2ec1b3 TT |
504 | { |
505 | case TYPE_CODE_RANGE: | |
506 | { | |
3b606f38 SM |
507 | if (type->bounds ()->high.kind () == PROP_LOCEXPR |
508 | || type->bounds ()->high.kind () == PROP_LOCLIST) | |
bb2ec1b3 | 509 | { |
599088e3 | 510 | const struct dynamic_prop *prop = &type->bounds ()->high; |
8f84fb0e | 511 | std::string name = c_get_range_decl_name (prop); |
bb2ec1b3 | 512 | |
8f84fb0e | 513 | dwarf2_compile_property_to_c (stream, name.c_str (), |
bb2ec1b3 TT |
514 | gdbarch, registers_used, |
515 | prop, pc, sym); | |
bb2ec1b3 TT |
516 | } |
517 | } | |
518 | break; | |
519 | ||
520 | case TYPE_CODE_ARRAY: | |
521 | generate_vla_size (compiler, stream, gdbarch, registers_used, pc, | |
3d967001 | 522 | type->index_type (), sym); |
bb2ec1b3 | 523 | generate_vla_size (compiler, stream, gdbarch, registers_used, pc, |
27710edb | 524 | type->target_type (), sym); |
bb2ec1b3 TT |
525 | break; |
526 | ||
527 | case TYPE_CODE_UNION: | |
528 | case TYPE_CODE_STRUCT: | |
529 | { | |
530 | int i; | |
531 | ||
1f704f76 | 532 | for (i = 0; i < type->num_fields (); ++i) |
c819a338 | 533 | if (!type->field (i).is_static ()) |
bb2ec1b3 | 534 | generate_vla_size (compiler, stream, gdbarch, registers_used, pc, |
940da03e | 535 | type->field (i).type (), sym); |
bb2ec1b3 TT |
536 | } |
537 | break; | |
538 | } | |
539 | } | |
540 | ||
541 | /* Generate C code to compute the address of SYM. */ | |
542 | ||
543 | static void | |
9cdfd9a2 | 544 | generate_c_for_for_one_variable (compile_instance *compiler, |
d82b3862 | 545 | string_file *stream, |
bb2ec1b3 | 546 | struct gdbarch *gdbarch, |
3637a558 | 547 | std::vector<bool> ®isters_used, |
bb2ec1b3 TT |
548 | CORE_ADDR pc, |
549 | struct symbol *sym) | |
550 | { | |
bb2ec1b3 | 551 | |
a70b8144 | 552 | try |
bb2ec1b3 | 553 | { |
5f9c5a63 | 554 | if (is_dynamic_type (sym->type ())) |
bb2ec1b3 | 555 | { |
d7e74731 PA |
556 | /* We need to emit to a temporary buffer in case an error |
557 | occurs in the middle. */ | |
558 | string_file local_file; | |
bb2ec1b3 | 559 | |
d82b3862 | 560 | generate_vla_size (compiler, &local_file, gdbarch, registers_used, pc, |
5f9c5a63 | 561 | sym->type (), sym); |
bb2ec1b3 | 562 | |
d82b3862 | 563 | stream->write (local_file.c_str (), local_file.size ()); |
bb2ec1b3 TT |
564 | } |
565 | ||
566 | if (SYMBOL_COMPUTED_OPS (sym) != NULL) | |
567 | { | |
8f84fb0e | 568 | gdb::unique_xmalloc_ptr<char> generated_name |
6f36b6d2 | 569 | = c_symbol_substitution_name (sym); |
bb2ec1b3 TT |
570 | /* We need to emit to a temporary buffer in case an error |
571 | occurs in the middle. */ | |
d7e74731 | 572 | string_file local_file; |
bb2ec1b3 | 573 | |
d82b3862 | 574 | SYMBOL_COMPUTED_OPS (sym)->generate_c_location (sym, &local_file, |
bb2ec1b3 TT |
575 | gdbarch, |
576 | registers_used, | |
8f84fb0e TT |
577 | pc, |
578 | generated_name.get ()); | |
d82b3862 | 579 | stream->write (local_file.c_str (), local_file.size ()); |
bb2ec1b3 TT |
580 | } |
581 | else | |
582 | { | |
66d7f48f | 583 | switch (sym->aclass ()) |
bb2ec1b3 TT |
584 | { |
585 | case LOC_REGISTER: | |
586 | case LOC_ARG: | |
587 | case LOC_REF_ARG: | |
588 | case LOC_REGPARM_ADDR: | |
589 | case LOC_LOCAL: | |
590 | error (_("Local symbol unhandled when generating C code.")); | |
591 | ||
592 | case LOC_COMPUTED: | |
557b4d76 SM |
593 | gdb_assert_not_reached ("LOC_COMPUTED variable " |
594 | "missing a method."); | |
bb2ec1b3 TT |
595 | |
596 | default: | |
597 | /* Nothing to do for all other cases, as they don't represent | |
598 | local variables. */ | |
599 | break; | |
600 | } | |
601 | } | |
602 | } | |
603 | ||
230d2906 | 604 | catch (const gdb_exception_error &e) |
7556d4a4 | 605 | { |
3d6e9d23 | 606 | compiler->insert_symbol_error (sym, e.what ()); |
7556d4a4 | 607 | } |
bb2ec1b3 TT |
608 | } |
609 | ||
b7dc48b4 | 610 | /* See compile-c.h. */ |
bb2ec1b3 | 611 | |
3637a558 | 612 | std::vector<bool> |
9cdfd9a2 | 613 | generate_c_for_variable_locations (compile_instance *compiler, |
d82b3862 | 614 | string_file *stream, |
bb2ec1b3 TT |
615 | struct gdbarch *gdbarch, |
616 | const struct block *block, | |
617 | CORE_ADDR pc) | |
618 | { | |
78004096 TT |
619 | if (block == nullptr) |
620 | return {}; | |
621 | ||
d24e14a0 | 622 | const struct block *static_block = block->static_block (); |
bb2ec1b3 TT |
623 | |
624 | /* If we're already in the static or global block, there is nothing | |
625 | to write. */ | |
626 | if (static_block == NULL || block == static_block) | |
3637a558 | 627 | return {}; |
bb2ec1b3 | 628 | |
3637a558 | 629 | std::vector<bool> registers_used (gdbarch_num_regs (gdbarch)); |
bb2ec1b3 TT |
630 | |
631 | /* Ensure that a given name is only entered once. This reflects the | |
632 | reality of shadowing. */ | |
fc4007c9 TT |
633 | htab_up symhash (htab_create_alloc (1, hash_symname, eq_symname, NULL, |
634 | xcalloc, xfree)); | |
bb2ec1b3 TT |
635 | |
636 | while (1) | |
637 | { | |
bb2ec1b3 TT |
638 | /* Iterate over symbols in this block, generating code to |
639 | compute the location of each local variable. */ | |
1c49bb45 | 640 | for (struct symbol *sym : block_iterator_range (block)) |
bb2ec1b3 | 641 | { |
fc4007c9 | 642 | if (!symbol_seen (symhash.get (), sym)) |
bb2ec1b3 | 643 | generate_c_for_for_one_variable (compiler, stream, gdbarch, |
3637a558 | 644 | registers_used, pc, sym); |
bb2ec1b3 TT |
645 | } |
646 | ||
647 | /* If we just finished the outermost block of a function, we're | |
648 | done. */ | |
6c00f721 | 649 | if (block->function () != NULL) |
bb2ec1b3 | 650 | break; |
f135fe72 | 651 | block = block->superblock (); |
bb2ec1b3 TT |
652 | } |
653 | ||
bb2ec1b3 TT |
654 | return registers_used; |
655 | } |