Commit | Line | Data |
---|---|---|
078a0207 | 1 | /* C/C++ language support for compilation. |
bb2ec1b3 | 2 | |
42a4f53d | 3 | Copyright (C) 2014-2019 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 | #include "defs.h" | |
21 | #include "compile-internal.h" | |
b7dc48b4 | 22 | #include "compile-c.h" |
078a0207 | 23 | #include "compile-cplus.h" |
bb2ec1b3 TT |
24 | #include "compile.h" |
25 | #include "gdb-dlfcn.h" | |
26 | #include "c-lang.h" | |
27 | #include "macrotab.h" | |
28 | #include "macroscope.h" | |
29 | #include "regcache.h" | |
14bc53a8 | 30 | #include "common/function-view.h" |
d269dfc6 | 31 | #include "common/preprocessor.h" |
bb2ec1b3 TT |
32 | |
33 | /* See compile-internal.h. */ | |
34 | ||
35 | const char * | |
36 | c_get_mode_for_size (int size) | |
37 | { | |
38 | const char *mode = NULL; | |
39 | ||
40 | switch (size) | |
41 | { | |
42 | case 1: | |
43 | mode = "QI"; | |
44 | break; | |
45 | case 2: | |
46 | mode = "HI"; | |
47 | break; | |
48 | case 4: | |
49 | mode = "SI"; | |
50 | break; | |
51 | case 8: | |
52 | mode = "DI"; | |
53 | break; | |
54 | default: | |
55 | internal_error (__FILE__, __LINE__, _("Invalid GCC mode size %d."), size); | |
56 | } | |
57 | ||
58 | return mode; | |
59 | } | |
60 | ||
61 | /* See compile-internal.h. */ | |
62 | ||
8f84fb0e | 63 | std::string |
bb2ec1b3 TT |
64 | c_get_range_decl_name (const struct dynamic_prop *prop) |
65 | { | |
8f84fb0e | 66 | return string_printf ("__gdb_prop_%s", host_address_to_string (prop)); |
bb2ec1b3 TT |
67 | } |
68 | ||
69 | \f | |
70 | ||
078a0207 KS |
71 | /* Load the plug-in library FE_LIBCC and return the initialization function |
72 | FE_CONTEXT. */ | |
bb2ec1b3 | 73 | |
078a0207 KS |
74 | template <typename FUNCTYPE> |
75 | FUNCTYPE * | |
76 | load_libcompile (const char *fe_libcc, const char *fe_context) | |
bb2ec1b3 | 77 | { |
078a0207 | 78 | FUNCTYPE *func; |
bb2ec1b3 | 79 | |
078a0207 KS |
80 | /* gdb_dlopen will call error () on an error, so no need to check |
81 | value. */ | |
82 | gdb_dlhandle_up handle = gdb_dlopen (fe_libcc); | |
83 | func = (FUNCTYPE *) gdb_dlsym (handle, fe_context); | |
bb2ec1b3 TT |
84 | |
85 | if (func == NULL) | |
078a0207 | 86 | error (_("could not find symbol %s in library %s"), fe_context, fe_libcc); |
0e8621a0 TT |
87 | |
88 | /* Leave the library open. */ | |
89 | handle.release (); | |
bb2ec1b3 TT |
90 | return func; |
91 | } | |
92 | ||
93 | /* Return the compile instance associated with the current context. | |
078a0207 KS |
94 | This function calls the symbol returned from the load_libcompile |
95 | function. FE_LIBCC is the library to load. BASE_VERSION is the | |
96 | base compile plug-in version we support. API_VERSION is the | |
97 | API version supported. */ | |
bb2ec1b3 | 98 | |
078a0207 KS |
99 | template <typename INSTTYPE, typename FUNCTYPE, typename CTXTYPE, |
100 | typename BASE_VERSION_TYPE, typename API_VERSION_TYPE> | |
9cdfd9a2 | 101 | compile_instance * |
078a0207 KS |
102 | get_compile_context (const char *fe_libcc, const char *fe_context, |
103 | BASE_VERSION_TYPE base_version, | |
104 | API_VERSION_TYPE api_version) | |
bb2ec1b3 | 105 | { |
078a0207 KS |
106 | static FUNCTYPE *func; |
107 | static CTXTYPE *context; | |
bb2ec1b3 TT |
108 | |
109 | if (func == NULL) | |
110 | { | |
078a0207 | 111 | func = load_libcompile<FUNCTYPE> (fe_libcc, fe_context); |
bb2ec1b3 TT |
112 | gdb_assert (func != NULL); |
113 | } | |
114 | ||
078a0207 | 115 | context = (*func) (base_version, api_version); |
bb2ec1b3 TT |
116 | if (context == NULL) |
117 | error (_("The loaded version of GCC does not support the required version " | |
118 | "of the API.")); | |
119 | ||
078a0207 KS |
120 | return new INSTTYPE (context); |
121 | } | |
122 | ||
123 | /* A C-language implementation of get_compile_context. */ | |
124 | ||
125 | compile_instance * | |
126 | c_get_compile_context () | |
127 | { | |
128 | return get_compile_context | |
129 | <compile_c_instance, gcc_c_fe_context_function, gcc_c_context, | |
130 | gcc_base_api_version, gcc_c_api_version> | |
131 | (STRINGIFY (GCC_C_FE_LIBCC), STRINGIFY (GCC_C_FE_CONTEXT), | |
132 | GCC_FE_VERSION_0, GCC_C_FE_VERSION_0); | |
133 | } | |
134 | ||
135 | /* A C++-language implementation of get_compile_context. */ | |
136 | ||
137 | compile_instance * | |
138 | cplus_get_compile_context () | |
139 | { | |
140 | return get_compile_context | |
141 | <compile_cplus_instance, gcc_cp_fe_context_function, gcc_cp_context, | |
142 | gcc_base_api_version, gcc_cp_api_version> | |
143 | (STRINGIFY (GCC_CP_FE_LIBCC), STRINGIFY (GCC_CP_FE_CONTEXT), | |
144 | GCC_FE_VERSION_0, GCC_CP_FE_VERSION_0); | |
bb2ec1b3 TT |
145 | } |
146 | ||
147 | \f | |
148 | ||
149 | /* Write one macro definition. */ | |
150 | ||
151 | static void | |
152 | print_one_macro (const char *name, const struct macro_definition *macro, | |
153 | struct macro_source_file *source, int line, | |
14bc53a8 | 154 | ui_file *file) |
bb2ec1b3 | 155 | { |
bb2ec1b3 TT |
156 | /* Don't print command-line defines. They will be supplied another |
157 | way. */ | |
158 | if (line == 0) | |
159 | return; | |
160 | ||
3a9558c4 JK |
161 | /* None of -Wno-builtin-macro-redefined, #undef first |
162 | or plain #define of the same value would avoid a warning. */ | |
163 | fprintf_filtered (file, "#ifndef %s\n# define %s", name, name); | |
bb2ec1b3 TT |
164 | |
165 | if (macro->kind == macro_function_like) | |
166 | { | |
167 | int i; | |
168 | ||
169 | fputs_filtered ("(", file); | |
170 | for (i = 0; i < macro->argc; i++) | |
171 | { | |
172 | fputs_filtered (macro->argv[i], file); | |
173 | if (i + 1 < macro->argc) | |
174 | fputs_filtered (", ", file); | |
175 | } | |
176 | fputs_filtered (")", file); | |
177 | } | |
178 | ||
3a9558c4 | 179 | fprintf_filtered (file, " %s\n#endif\n", macro->replacement); |
bb2ec1b3 TT |
180 | } |
181 | ||
182 | /* Write macro definitions at PC to FILE. */ | |
183 | ||
184 | static void | |
185 | write_macro_definitions (const struct block *block, CORE_ADDR pc, | |
186 | struct ui_file *file) | |
187 | { | |
f6c2623e | 188 | gdb::unique_xmalloc_ptr<struct macro_scope> scope; |
bb2ec1b3 TT |
189 | |
190 | if (block != NULL) | |
191 | scope = sal_macro_scope (find_pc_line (pc, 0)); | |
192 | else | |
193 | scope = default_macro_scope (); | |
194 | if (scope == NULL) | |
195 | scope = user_macro_scope (); | |
196 | ||
197 | if (scope != NULL && scope->file != NULL && scope->file->table != NULL) | |
14bc53a8 PA |
198 | { |
199 | macro_for_each_in_scope (scope->file, scope->line, | |
200 | [&] (const char *name, | |
201 | const macro_definition *macro, | |
202 | macro_source_file *source, | |
203 | int line) | |
204 | { | |
205 | print_one_macro (name, macro, source, line, file); | |
206 | }); | |
207 | } | |
bb2ec1b3 TT |
208 | } |
209 | ||
bb2ec1b3 TT |
210 | /* Generate a structure holding all the registers used by the function |
211 | we're generating. */ | |
212 | ||
213 | static void | |
214 | generate_register_struct (struct ui_file *stream, struct gdbarch *gdbarch, | |
215 | const unsigned char *registers_used) | |
216 | { | |
217 | int i; | |
218 | int seen = 0; | |
219 | ||
220 | fputs_unfiltered ("struct " COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG " {\n", | |
221 | stream); | |
222 | ||
223 | if (registers_used != NULL) | |
224 | for (i = 0; i < gdbarch_num_regs (gdbarch); ++i) | |
225 | { | |
226 | if (registers_used[i]) | |
227 | { | |
228 | struct type *regtype = check_typedef (register_type (gdbarch, i)); | |
8f84fb0e | 229 | std::string regname = compile_register_name_mangled (gdbarch, i); |
bb2ec1b3 TT |
230 | |
231 | seen = 1; | |
232 | ||
233 | /* You might think we could use type_print here. However, | |
234 | target descriptions often use types with names like | |
235 | "int64_t", which may not be defined in the inferior | |
236 | (and in any case would not be looked up due to the | |
237 | #pragma business). So, we take a much simpler | |
238 | approach: for pointer- or integer-typed registers, emit | |
239 | the field in the most direct way; and for other | |
240 | register types (typically flags or vectors), emit a | |
241 | maximally-aligned array of the correct size. */ | |
242 | ||
243 | fputs_unfiltered (" ", stream); | |
244 | switch (TYPE_CODE (regtype)) | |
245 | { | |
246 | case TYPE_CODE_PTR: | |
8f84fb0e TT |
247 | fprintf_filtered (stream, "__gdb_uintptr %s", |
248 | regname.c_str ()); | |
bb2ec1b3 TT |
249 | break; |
250 | ||
251 | case TYPE_CODE_INT: | |
252 | { | |
253 | const char *mode | |
254 | = c_get_mode_for_size (TYPE_LENGTH (regtype)); | |
255 | ||
256 | if (mode != NULL) | |
257 | { | |
258 | if (TYPE_UNSIGNED (regtype)) | |
259 | fputs_unfiltered ("unsigned ", stream); | |
260 | fprintf_unfiltered (stream, | |
261 | "int %s" | |
262 | " __attribute__ ((__mode__(__%s__)))", | |
8f84fb0e | 263 | regname.c_str (), |
bb2ec1b3 TT |
264 | mode); |
265 | break; | |
266 | } | |
267 | } | |
268 | ||
269 | /* Fall through. */ | |
270 | ||
271 | default: | |
272 | fprintf_unfiltered (stream, | |
273 | " unsigned char %s[%d]" | |
274 | " __attribute__((__aligned__(" | |
275 | "__BIGGEST_ALIGNMENT__)))", | |
8f84fb0e | 276 | regname.c_str (), |
bb2ec1b3 TT |
277 | TYPE_LENGTH (regtype)); |
278 | } | |
279 | fputs_unfiltered (";\n", stream); | |
bb2ec1b3 TT |
280 | } |
281 | } | |
282 | ||
283 | if (!seen) | |
284 | fputs_unfiltered (" char " COMPILE_I_SIMPLE_REGISTER_DUMMY ";\n", | |
285 | stream); | |
286 | ||
287 | fputs_unfiltered ("};\n\n", stream); | |
288 | } | |
289 | ||
ad3a68e9 | 290 | /* C-language policy to emit a push user expression pragma into BUF. */ |
bb2ec1b3 | 291 | |
ad3a68e9 | 292 | struct c_push_user_expression |
bb2ec1b3 | 293 | { |
ad3a68e9 KS |
294 | void push_user_expression (struct ui_file *buf) |
295 | { | |
296 | fputs_unfiltered ("#pragma GCC user_expression\n", buf); | |
297 | } | |
298 | }; | |
bb2ec1b3 | 299 | |
ad3a68e9 KS |
300 | /* C-language policy to emit a pop user expression pragma into BUF. |
301 | For C, this is a nop. */ | |
bb2ec1b3 | 302 | |
ad3a68e9 KS |
303 | struct pop_user_expression_nop |
304 | { | |
305 | void pop_user_expression (struct ui_file *buf) | |
306 | { | |
307 | /* Nothing to do. */ | |
308 | } | |
309 | }; | |
310 | ||
311 | /* C-language policy to construct a code header for a block of code. | |
312 | Takes a scope TYPE argument which selects the correct header to | |
313 | insert into BUF. */ | |
bb2ec1b3 | 314 | |
ad3a68e9 KS |
315 | struct c_add_code_header |
316 | { | |
317 | void add_code_header (enum compile_i_scope_types type, struct ui_file *buf) | |
318 | { | |
319 | switch (type) | |
320 | { | |
321 | case COMPILE_I_SIMPLE_SCOPE: | |
322 | fputs_unfiltered ("void " | |
323 | GCC_FE_WRAPPER_FUNCTION | |
324 | " (struct " | |
325 | COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG | |
326 | " *" | |
327 | COMPILE_I_SIMPLE_REGISTER_ARG_NAME | |
328 | ") {\n", | |
329 | buf); | |
330 | break; | |
331 | ||
332 | case COMPILE_I_PRINT_ADDRESS_SCOPE: | |
333 | case COMPILE_I_PRINT_VALUE_SCOPE: | |
334 | /* <string.h> is needed for a memcpy call below. */ | |
335 | fputs_unfiltered ("#include <string.h>\n" | |
336 | "void " | |
337 | GCC_FE_WRAPPER_FUNCTION | |
338 | " (struct " | |
339 | COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG | |
340 | " *" | |
341 | COMPILE_I_SIMPLE_REGISTER_ARG_NAME | |
342 | ", " | |
343 | COMPILE_I_PRINT_OUT_ARG_TYPE | |
344 | " " | |
345 | COMPILE_I_PRINT_OUT_ARG | |
346 | ") {\n", | |
347 | buf); | |
348 | break; | |
349 | ||
350 | case COMPILE_I_RAW_SCOPE: | |
351 | break; | |
352 | ||
353 | default: | |
354 | gdb_assert_not_reached (_("Unknown compiler scope reached.")); | |
355 | } | |
356 | } | |
357 | }; | |
bb2ec1b3 | 358 | |
ad3a68e9 KS |
359 | /* C-language policy to construct a code footer for a block of code. |
360 | Takes a scope TYPE which selects the correct footer to insert into BUF. */ | |
bb2ec1b3 | 361 | |
ad3a68e9 KS |
362 | struct c_add_code_footer |
363 | { | |
364 | void add_code_footer (enum compile_i_scope_types type, struct ui_file *buf) | |
365 | { | |
366 | switch (type) | |
367 | { | |
368 | case COMPILE_I_SIMPLE_SCOPE: | |
369 | case COMPILE_I_PRINT_ADDRESS_SCOPE: | |
370 | case COMPILE_I_PRINT_VALUE_SCOPE: | |
371 | fputs_unfiltered ("}\n", buf); | |
372 | break; | |
3a9558c4 | 373 | |
ad3a68e9 KS |
374 | case COMPILE_I_RAW_SCOPE: |
375 | break; | |
bb2ec1b3 | 376 | |
ad3a68e9 KS |
377 | default: |
378 | gdb_assert_not_reached (_("Unknown compiler scope reached.")); | |
379 | } | |
380 | } | |
381 | }; | |
bb2ec1b3 | 382 | |
ad3a68e9 KS |
383 | /* C-language policy to emit the user code snippet INPUT into BUF based on the |
384 | scope TYPE. */ | |
bb2ec1b3 | 385 | |
ad3a68e9 KS |
386 | struct c_add_input |
387 | { | |
388 | void add_input (enum compile_i_scope_types type, const char *input, | |
389 | struct ui_file *buf) | |
390 | { | |
391 | switch (type) | |
392 | { | |
393 | case COMPILE_I_PRINT_ADDRESS_SCOPE: | |
394 | case COMPILE_I_PRINT_VALUE_SCOPE: | |
395 | fprintf_unfiltered (buf, | |
396 | "__auto_type " COMPILE_I_EXPR_VAL " = %s;\n" | |
397 | "typeof (%s) *" COMPILE_I_EXPR_PTR_TYPE ";\n" | |
398 | "memcpy (" COMPILE_I_PRINT_OUT_ARG ", %s" | |
399 | COMPILE_I_EXPR_VAL ",\n" | |
400 | "sizeof (*" COMPILE_I_EXPR_PTR_TYPE "));\n" | |
401 | , input, input, | |
402 | (type == COMPILE_I_PRINT_ADDRESS_SCOPE | |
403 | ? "&" : "")); | |
404 | break; | |
405 | ||
406 | default: | |
407 | fputs_unfiltered (input, buf); | |
408 | break; | |
409 | } | |
410 | fputs_unfiltered ("\n", buf); | |
411 | } | |
412 | }; | |
bb2ec1b3 | 413 | |
078a0207 KS |
414 | /* C++-language policy to emit a push user expression pragma into |
415 | BUF. */ | |
416 | ||
417 | struct cplus_push_user_expression | |
418 | { | |
419 | void push_user_expression (struct ui_file *buf) | |
420 | { | |
421 | fputs_unfiltered ("#pragma GCC push_user_expression\n", buf); | |
422 | } | |
423 | }; | |
424 | ||
425 | /* C++-language policy to emit a pop user expression pragma into BUF. */ | |
426 | ||
427 | struct cplus_pop_user_expression | |
428 | { | |
429 | void pop_user_expression (struct ui_file *buf) | |
430 | { | |
431 | fputs_unfiltered ("#pragma GCC pop_user_expression\n", buf); | |
432 | } | |
433 | }; | |
434 | ||
435 | /* C++-language policy to construct a code header for a block of code. | |
436 | Takes a scope TYPE argument which selects the correct header to | |
437 | insert into BUF. */ | |
438 | ||
439 | struct cplus_add_code_header | |
440 | { | |
441 | void add_code_header (enum compile_i_scope_types type, struct ui_file *buf) | |
442 | { | |
443 | switch (type) | |
444 | { | |
445 | case COMPILE_I_SIMPLE_SCOPE: | |
446 | fputs_unfiltered ("void " | |
447 | GCC_FE_WRAPPER_FUNCTION | |
448 | " (struct " | |
449 | COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG | |
450 | " *" | |
451 | COMPILE_I_SIMPLE_REGISTER_ARG_NAME | |
452 | ") {\n", | |
453 | buf); | |
454 | break; | |
455 | ||
456 | case COMPILE_I_PRINT_ADDRESS_SCOPE: | |
457 | case COMPILE_I_PRINT_VALUE_SCOPE: | |
458 | fputs_unfiltered ( | |
459 | "#include <cstring>\n" | |
460 | "#include <bits/move.h>\n" | |
461 | "void " | |
462 | GCC_FE_WRAPPER_FUNCTION | |
463 | " (struct " | |
464 | COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG | |
465 | " *" | |
466 | COMPILE_I_SIMPLE_REGISTER_ARG_NAME | |
467 | ", " | |
468 | COMPILE_I_PRINT_OUT_ARG_TYPE | |
469 | " " | |
470 | COMPILE_I_PRINT_OUT_ARG | |
471 | ") {\n", | |
472 | buf); | |
473 | break; | |
474 | ||
475 | case COMPILE_I_RAW_SCOPE: | |
476 | break; | |
477 | ||
478 | default: | |
479 | gdb_assert_not_reached (_("Unknown compiler scope reached.")); | |
480 | } | |
481 | } | |
482 | }; | |
483 | ||
484 | /* C++-language policy to emit the user code snippet INPUT into BUF based on | |
485 | the scope TYPE. */ | |
486 | ||
487 | struct cplus_add_input | |
488 | { | |
489 | void add_input (enum compile_i_scope_types type, const char *input, | |
490 | struct ui_file *buf) | |
491 | { | |
492 | switch (type) | |
493 | { | |
494 | case COMPILE_I_PRINT_VALUE_SCOPE: | |
495 | case COMPILE_I_PRINT_ADDRESS_SCOPE: | |
496 | fprintf_unfiltered | |
497 | (buf, | |
498 | /* "auto" strips ref- and cv- qualifiers, so we need to also strip | |
499 | those from COMPILE_I_EXPR_PTR_TYPE. */ | |
500 | "auto " COMPILE_I_EXPR_VAL " = %s;\n" | |
501 | "typedef " | |
502 | "std::add_pointer<std::remove_cv<decltype (%s)>::type>::type " | |
503 | " __gdb_expr_ptr;\n" | |
504 | "__gdb_expr_ptr " COMPILE_I_EXPR_PTR_TYPE ";\n" | |
505 | "std::memcpy (" COMPILE_I_PRINT_OUT_ARG ", %s (" | |
506 | COMPILE_I_EXPR_VAL "),\n" | |
507 | "\tsizeof (*" COMPILE_I_EXPR_PTR_TYPE "));\n" | |
508 | ,input, input, | |
509 | (type == COMPILE_I_PRINT_ADDRESS_SCOPE | |
510 | ? "__builtin_addressof" : "")); | |
511 | break; | |
512 | ||
513 | default: | |
514 | fputs_unfiltered (input, buf); | |
515 | break; | |
516 | } | |
517 | fputs_unfiltered ("\n", buf); | |
518 | } | |
519 | }; | |
520 | ||
ad3a68e9 | 521 | /* A host class representing a compile program. |
36de76f9 | 522 | |
ad3a68e9 KS |
523 | CompileInstanceType is the type of the compile_instance for the |
524 | language. | |
525 | ||
526 | PushUserExpressionPolicy and PopUserExpressionPolicy are used to | |
527 | push and pop user expression pragmas to the compile plug-in. | |
528 | ||
529 | AddCodeHeaderPolicy and AddCodeFooterPolicy are used to add the appropriate | |
530 | code header and footer, respectively. | |
36de76f9 | 531 | |
ad3a68e9 | 532 | AddInputPolicy adds the actual user code. */ |
bb2ec1b3 | 533 | |
ad3a68e9 KS |
534 | template <class CompileInstanceType, class PushUserExpressionPolicy, |
535 | class PopUserExpressionPolicy, class AddCodeHeaderPolicy, | |
536 | class AddCodeFooterPolicy, class AddInputPolicy> | |
537 | class compile_program | |
538 | : private PushUserExpressionPolicy, private PopUserExpressionPolicy, | |
539 | private AddCodeHeaderPolicy, private AddCodeFooterPolicy, | |
540 | private AddInputPolicy | |
541 | { | |
542 | public: | |
543 | ||
544 | /* Construct a compile_program using the compiler instance INST | |
545 | using the architecture given by GDBARCH. */ | |
546 | compile_program (CompileInstanceType *inst, struct gdbarch *gdbarch) | |
547 | : m_instance (inst), m_arch (gdbarch) | |
548 | { | |
549 | } | |
550 | ||
551 | /* Take the source code provided by the user with the 'compile' | |
552 | command and compute the additional wrapping, macro, variable and | |
553 | register operations needed. INPUT is the source code derived from | |
554 | the 'compile' command, EXPR_BLOCK denotes the block relevant contextually | |
555 | to the inferior when the expression was created, and EXPR_PC | |
556 | indicates the value of $PC. | |
557 | ||
558 | Returns the text of the program to compile. */ | |
559 | std::string compute (const char *input, const struct block *expr_block, | |
560 | CORE_ADDR expr_pc) | |
561 | { | |
562 | string_file var_stream; | |
563 | string_file buf; | |
564 | ||
565 | /* Do not generate local variable information for "raw" | |
566 | compilations. In this case we aren't emitting our own function | |
567 | and the user's code may only refer to globals. */ | |
568 | if (m_instance->scope () != COMPILE_I_RAW_SCOPE) | |
569 | { | |
570 | /* Generate the code to compute variable locations, but do it | |
571 | before generating the function header, so we can define the | |
572 | register struct before the function body. This requires a | |
573 | temporary stream. */ | |
574 | gdb::unique_xmalloc_ptr<unsigned char> registers_used | |
d82b3862 | 575 | = generate_c_for_variable_locations (m_instance, &var_stream, m_arch, |
ad3a68e9 KS |
576 | expr_block, expr_pc); |
577 | ||
578 | buf.puts ("typedef unsigned int" | |
579 | " __attribute__ ((__mode__(__pointer__)))" | |
580 | " __gdb_uintptr;\n"); | |
581 | buf.puts ("typedef int" | |
582 | " __attribute__ ((__mode__(__pointer__)))" | |
583 | " __gdb_intptr;\n"); | |
584 | ||
585 | /* Iterate all log2 sizes in bytes supported by c_get_mode_for_size. */ | |
586 | for (int i = 0; i < 4; ++i) | |
587 | { | |
588 | const char *mode = c_get_mode_for_size (1 << i); | |
589 | ||
590 | gdb_assert (mode != NULL); | |
591 | buf.printf ("typedef int" | |
592 | " __attribute__ ((__mode__(__%s__)))" | |
593 | " __gdb_int_%s;\n", | |
594 | mode, mode); | |
595 | } | |
596 | ||
597 | generate_register_struct (&buf, m_arch, registers_used.get ()); | |
598 | } | |
599 | ||
600 | AddCodeHeaderPolicy::add_code_header (m_instance->scope (), &buf); | |
601 | ||
602 | if (m_instance->scope () == COMPILE_I_SIMPLE_SCOPE | |
603 | || m_instance->scope () == COMPILE_I_PRINT_ADDRESS_SCOPE | |
604 | || m_instance->scope () == COMPILE_I_PRINT_VALUE_SCOPE) | |
605 | { | |
606 | buf.write (var_stream.c_str (), var_stream.size ()); | |
607 | PushUserExpressionPolicy::push_user_expression (&buf); | |
608 | } | |
bb2ec1b3 | 609 | |
ad3a68e9 KS |
610 | write_macro_definitions (expr_block, expr_pc, &buf); |
611 | ||
612 | /* The user expression has to be in its own scope, so that "extern" | |
613 | works properly. Otherwise gcc thinks that the "extern" | |
614 | declaration is in the same scope as the declaration provided by | |
615 | gdb. */ | |
616 | if (m_instance->scope () != COMPILE_I_RAW_SCOPE) | |
617 | buf.puts ("{\n"); | |
618 | ||
619 | buf.puts ("#line 1 \"gdb command line\"\n"); | |
620 | ||
621 | AddInputPolicy::add_input (m_instance->scope (), input, &buf); | |
622 | ||
623 | /* For larger user expressions the automatic semicolons may be | |
624 | confusing. */ | |
625 | if (strchr (input, '\n') == NULL) | |
626 | buf.puts (";\n"); | |
627 | ||
628 | if (m_instance->scope () != COMPILE_I_RAW_SCOPE) | |
629 | buf.puts ("}\n"); | |
630 | ||
631 | if (m_instance->scope () == COMPILE_I_SIMPLE_SCOPE | |
632 | || m_instance->scope () == COMPILE_I_PRINT_ADDRESS_SCOPE | |
633 | || m_instance->scope () == COMPILE_I_PRINT_VALUE_SCOPE) | |
634 | PopUserExpressionPolicy::pop_user_expression (&buf); | |
635 | ||
636 | AddCodeFooterPolicy::add_code_footer (m_instance->scope (), &buf); | |
637 | return buf.string (); | |
638 | } | |
639 | ||
640 | private: | |
641 | ||
642 | /* The compile instance to be used for compilation and | |
643 | type-conversion. */ | |
644 | CompileInstanceType *m_instance; | |
645 | ||
646 | /* The architecture to be used. */ | |
647 | struct gdbarch *m_arch; | |
648 | }; | |
649 | ||
078a0207 | 650 | /* The types used for C and C++ program computations. */ |
ad3a68e9 KS |
651 | |
652 | typedef compile_program<compile_c_instance, | |
653 | c_push_user_expression, pop_user_expression_nop, | |
654 | c_add_code_header, c_add_code_footer, | |
655 | c_add_input> c_compile_program; | |
656 | ||
078a0207 KS |
657 | typedef compile_program<compile_cplus_instance, |
658 | cplus_push_user_expression, cplus_pop_user_expression, | |
659 | cplus_add_code_header, c_add_code_footer, | |
660 | cplus_add_input> cplus_compile_program; | |
661 | ||
ad3a68e9 KS |
662 | /* The la_compute_program method for C. */ |
663 | ||
664 | std::string | |
665 | c_compute_program (compile_instance *inst, | |
666 | const char *input, | |
667 | struct gdbarch *gdbarch, | |
668 | const struct block *expr_block, | |
669 | CORE_ADDR expr_pc) | |
670 | { | |
671 | compile_c_instance *c_inst = static_cast<compile_c_instance *> (inst); | |
672 | c_compile_program program (c_inst, gdbarch); | |
bb2ec1b3 | 673 | |
ad3a68e9 | 674 | return program.compute (input, expr_block, expr_pc); |
bb2ec1b3 | 675 | } |
078a0207 KS |
676 | |
677 | /* The la_compute_program method for C++. */ | |
678 | ||
679 | std::string | |
680 | cplus_compute_program (compile_instance *inst, | |
681 | const char *input, | |
682 | struct gdbarch *gdbarch, | |
683 | const struct block *expr_block, | |
684 | CORE_ADDR expr_pc) | |
685 | { | |
686 | compile_cplus_instance *cplus_inst | |
687 | = static_cast<compile_cplus_instance *> (inst); | |
688 | cplus_compile_program program (cplus_inst, gdbarch); | |
689 | ||
690 | return program.compute (input, expr_block, expr_pc); | |
691 | } |