]>
Commit | Line | Data |
---|---|---|
863e76f9 | 1 | /* Internals of libgccjit: classes for recording calls made to the JIT API. |
f1717362 | 2 | Copyright (C) 2013-2016 Free Software Foundation, Inc. |
863e76f9 | 3 | Contributed by David Malcolm <dmalcolm@redhat.com>. |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it | |
8 | under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but | |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GCC; see the file COPYING3. If not see | |
19 | <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | #ifndef JIT_RECORDING_H | |
22 | #define JIT_RECORDING_H | |
23 | ||
24 | #include "jit-common.h" | |
3a9ccc11 | 25 | #include "jit-logging.h" |
863e76f9 | 26 | |
17c0b84b | 27 | class timer; |
28 | ||
863e76f9 | 29 | namespace gcc { |
30 | ||
31 | namespace jit { | |
32 | ||
33 | class result; | |
34 | class dump; | |
c97b0d1d | 35 | class reproducer; |
863e76f9 | 36 | |
37 | /********************************************************************** | |
38 | Recording. | |
39 | **********************************************************************/ | |
40 | ||
41 | namespace recording { | |
42 | ||
43 | playback::location * | |
44 | playback_location (replayer *r, location *loc); | |
45 | ||
46 | const char * | |
47 | playback_string (string *str); | |
48 | ||
49 | playback::block * | |
50 | playback_block (block *b); | |
51 | ||
66b69275 | 52 | /* A recording of a call to gcc_jit_context_enable_dump. */ |
53 | struct requested_dump | |
54 | { | |
55 | const char *m_dumpname; | |
56 | char **m_out_ptr; | |
57 | }; | |
58 | ||
863e76f9 | 59 | /* A JIT-compilation context. */ |
3a9ccc11 | 60 | class context : public log_user |
863e76f9 | 61 | { |
62 | public: | |
63 | context (context *parent_ctxt); | |
64 | ~context (); | |
65 | ||
7140b255 | 66 | builtins_manager * |
67 | get_builtins_manager (); | |
68 | ||
863e76f9 | 69 | void record (memento *m); |
70 | void replay_into (replayer *r); | |
71 | void disassociate_from_playback (); | |
72 | ||
73 | string * | |
74 | new_string (const char *text); | |
75 | ||
76 | location * | |
77 | new_location (const char *filename, | |
78 | int line, | |
c97b0d1d | 79 | int column, |
80 | bool created_by_user); | |
863e76f9 | 81 | |
82 | type * | |
83 | get_type (enum gcc_jit_types type); | |
84 | ||
85 | type * | |
86 | get_int_type (int num_bytes, int is_signed); | |
87 | ||
88 | type * | |
89 | new_array_type (location *loc, | |
90 | type *element_type, | |
91 | int num_elements); | |
92 | ||
93 | field * | |
94 | new_field (location *loc, | |
95 | type *type, | |
96 | const char *name); | |
97 | ||
98 | struct_ * | |
99 | new_struct_type (location *loc, | |
100 | const char *name); | |
101 | ||
102 | union_ * | |
103 | new_union_type (location *loc, | |
104 | const char *name); | |
105 | ||
786b0007 | 106 | function_type * |
107 | new_function_type (type *return_type, | |
108 | int num_params, | |
109 | type **param_types, | |
110 | int is_variadic); | |
111 | ||
863e76f9 | 112 | type * |
113 | new_function_ptr_type (location *loc, | |
114 | type *return_type, | |
115 | int num_params, | |
116 | type **param_types, | |
117 | int is_variadic); | |
118 | ||
119 | param * | |
120 | new_param (location *loc, | |
121 | type *type, | |
122 | const char *name); | |
123 | ||
124 | function * | |
125 | new_function (location *loc, | |
126 | enum gcc_jit_function_kind kind, | |
127 | type *return_type, | |
128 | const char *name, | |
129 | int num_params, | |
130 | param **params, | |
131 | int is_variadic, | |
132 | enum built_in_function builtin_id); | |
133 | ||
134 | function * | |
135 | get_builtin_function (const char *name); | |
136 | ||
137 | lvalue * | |
138 | new_global (location *loc, | |
15b6c83e | 139 | enum gcc_jit_global_kind kind, |
863e76f9 | 140 | type *type, |
141 | const char *name); | |
142 | ||
feea5a1f | 143 | template <typename HOST_TYPE> |
863e76f9 | 144 | rvalue * |
feea5a1f | 145 | new_rvalue_from_const (type *type, |
146 | HOST_TYPE value); | |
863e76f9 | 147 | |
148 | rvalue * | |
149 | new_string_literal (const char *value); | |
150 | ||
151 | rvalue * | |
152 | new_unary_op (location *loc, | |
153 | enum gcc_jit_unary_op op, | |
154 | type *result_type, | |
155 | rvalue *a); | |
156 | ||
157 | rvalue * | |
158 | new_binary_op (location *loc, | |
159 | enum gcc_jit_binary_op op, | |
160 | type *result_type, | |
161 | rvalue *a, rvalue *b); | |
162 | ||
163 | rvalue * | |
164 | new_comparison (location *loc, | |
165 | enum gcc_jit_comparison op, | |
166 | rvalue *a, rvalue *b); | |
167 | ||
168 | rvalue * | |
169 | new_call (location *loc, | |
170 | function *func, | |
171 | int numargs, rvalue **args); | |
172 | ||
173 | rvalue * | |
174 | new_call_through_ptr (location *loc, | |
175 | rvalue *fn_ptr, | |
176 | int numargs, rvalue **args); | |
177 | ||
178 | rvalue * | |
179 | new_cast (location *loc, | |
180 | rvalue *expr, | |
181 | type *type_); | |
182 | ||
183 | lvalue * | |
184 | new_array_access (location *loc, | |
185 | rvalue *ptr, | |
186 | rvalue *index); | |
187 | ||
a24ef8d2 | 188 | case_ * |
189 | new_case (rvalue *min_value, | |
190 | rvalue *max_value, | |
191 | block *block); | |
192 | ||
863e76f9 | 193 | void |
194 | set_str_option (enum gcc_jit_str_option opt, | |
195 | const char *value); | |
196 | ||
197 | void | |
198 | set_int_option (enum gcc_jit_int_option opt, | |
199 | int value); | |
200 | ||
201 | void | |
202 | set_bool_option (enum gcc_jit_bool_option opt, | |
203 | int value); | |
204 | ||
04feb56e | 205 | void |
206 | set_inner_bool_option (enum inner_bool_option inner_opt, | |
207 | int value); | |
208 | ||
adb2df55 | 209 | void |
210 | add_command_line_option (const char *optname); | |
211 | ||
212 | void | |
213 | append_command_line_options (vec <char *> *argvec); | |
214 | ||
66b69275 | 215 | void |
216 | enable_dump (const char *dumpname, | |
217 | char **out_ptr); | |
218 | ||
863e76f9 | 219 | const char * |
220 | get_str_option (enum gcc_jit_str_option opt) const | |
221 | { | |
222 | return m_str_options[opt]; | |
223 | } | |
224 | ||
225 | int | |
226 | get_int_option (enum gcc_jit_int_option opt) const | |
227 | { | |
228 | return m_int_options[opt]; | |
229 | } | |
230 | ||
231 | int | |
232 | get_bool_option (enum gcc_jit_bool_option opt) const | |
233 | { | |
234 | return m_bool_options[opt]; | |
235 | } | |
236 | ||
04feb56e | 237 | int |
238 | get_inner_bool_option (enum inner_bool_option opt) const | |
239 | { | |
240 | return m_inner_bool_options[opt]; | |
241 | } | |
242 | ||
863e76f9 | 243 | result * |
244 | compile (); | |
245 | ||
69834ed9 | 246 | void |
247 | compile_to_file (enum gcc_jit_output_kind output_kind, | |
248 | const char *output_path); | |
249 | ||
863e76f9 | 250 | void |
251 | add_error (location *loc, const char *fmt, ...) | |
252 | GNU_PRINTF(3, 4); | |
253 | ||
254 | void | |
255 | add_error_va (location *loc, const char *fmt, va_list ap) | |
256 | GNU_PRINTF(3, 0); | |
257 | ||
258 | const char * | |
259 | get_first_error () const; | |
260 | ||
b56bc4a2 | 261 | const char * |
262 | get_last_error () const; | |
263 | ||
863e76f9 | 264 | bool errors_occurred () const |
265 | { | |
266 | if (m_parent_ctxt) | |
267 | if (m_parent_ctxt->errors_occurred ()) | |
268 | return true; | |
269 | return m_error_count; | |
270 | } | |
271 | ||
272 | type *get_opaque_FILE_type (); | |
273 | ||
274 | void dump_to_file (const char *path, bool update_locations); | |
275 | ||
c97b0d1d | 276 | void dump_reproducer_to_file (const char *path); |
277 | ||
66b69275 | 278 | void |
279 | get_all_requested_dumps (vec <recording::requested_dump> *out); | |
280 | ||
17c0b84b | 281 | void set_timer (timer *t) { m_timer = t; } |
282 | timer *get_timer () const { return m_timer; } | |
283 | ||
863e76f9 | 284 | private: |
2c845fbc | 285 | void log_all_options () const; |
286 | void log_str_option (enum gcc_jit_str_option opt) const; | |
287 | void log_int_option (enum gcc_jit_int_option opt) const; | |
288 | void log_bool_option (enum gcc_jit_bool_option opt) const; | |
04feb56e | 289 | void log_inner_bool_option (enum inner_bool_option opt) const; |
2c845fbc | 290 | |
863e76f9 | 291 | void validate (); |
292 | ||
293 | private: | |
294 | context *m_parent_ctxt; | |
295 | ||
c97b0d1d | 296 | /* The ultimate ancestor of the contexts within a family tree of |
297 | contexts. This has itself as its own m_toplevel_ctxt. */ | |
298 | context *m_toplevel_ctxt; | |
299 | ||
17c0b84b | 300 | timer *m_timer; |
301 | ||
863e76f9 | 302 | int m_error_count; |
303 | ||
304 | char *m_first_error_str; | |
305 | bool m_owns_first_error_str; | |
306 | ||
b56bc4a2 | 307 | char *m_last_error_str; |
308 | bool m_owns_last_error_str; | |
309 | ||
4149f31e | 310 | char *m_str_options[GCC_JIT_NUM_STR_OPTIONS]; |
863e76f9 | 311 | int m_int_options[GCC_JIT_NUM_INT_OPTIONS]; |
312 | bool m_bool_options[GCC_JIT_NUM_BOOL_OPTIONS]; | |
04feb56e | 313 | bool m_inner_bool_options[NUM_INNER_BOOL_OPTIONS]; |
adb2df55 | 314 | auto_vec <char *> m_command_line_options; |
863e76f9 | 315 | |
66b69275 | 316 | /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */ |
317 | auto_vec<requested_dump> m_requested_dumps; | |
318 | ||
863e76f9 | 319 | /* Recorded API usage. */ |
b9a4cef3 | 320 | auto_vec<memento *> m_mementos; |
863e76f9 | 321 | |
322 | /* Specific recordings, for use by dump_to_file. */ | |
b9a4cef3 | 323 | auto_vec<compound_type *> m_compound_types; |
15b6c83e | 324 | auto_vec<global *> m_globals; |
b9a4cef3 | 325 | auto_vec<function *> m_functions; |
863e76f9 | 326 | |
327 | type *m_basic_types[NUM_GCC_JIT_TYPES]; | |
328 | type *m_FILE_type; | |
329 | ||
330 | builtins_manager *m_builtins_manager; // lazily created | |
331 | }; | |
332 | ||
333 | ||
334 | /* An object with lifetime managed by the context i.e. | |
335 | it lives until the context is released, at which | |
336 | point it itself is cleaned up. */ | |
337 | ||
338 | class memento | |
339 | { | |
340 | public: | |
341 | virtual ~memento () {} | |
342 | ||
343 | /* Hook for replaying this. */ | |
344 | virtual void replay_into (replayer *r) = 0; | |
345 | ||
346 | void set_playback_obj (void *obj) { m_playback_obj = obj; } | |
347 | ||
348 | ||
349 | /* Get the context that owns this object. | |
350 | ||
351 | Implements the post-error-checking part of | |
352 | gcc_jit_object_get_context. */ | |
353 | context *get_context () { return m_ctxt; } | |
354 | ||
355 | memento * | |
356 | as_object () { return this; } | |
357 | ||
358 | /* Debugging hook, for use in generating error messages etc. | |
359 | Implements the post-error-checking part of | |
360 | gcc_jit_object_get_debug_string. */ | |
361 | const char * | |
362 | get_debug_string (); | |
363 | ||
364 | virtual void write_to_dump (dump &d); | |
c97b0d1d | 365 | virtual void write_reproducer (reproducer &r) = 0; |
366 | virtual location *dyn_cast_location () { return NULL; } | |
863e76f9 | 367 | |
368 | protected: | |
369 | memento (context *ctxt) | |
370 | : m_ctxt (ctxt), | |
371 | m_playback_obj (NULL), | |
372 | m_debug_string (NULL) | |
373 | { | |
374 | gcc_assert (ctxt); | |
375 | } | |
376 | ||
377 | string *new_string (const char *text) { return m_ctxt->new_string (text); } | |
378 | ||
379 | private: | |
380 | virtual string * make_debug_string () = 0; | |
381 | ||
382 | public: | |
383 | context *m_ctxt; | |
384 | ||
385 | protected: | |
386 | void *m_playback_obj; | |
387 | ||
388 | private: | |
389 | string *m_debug_string; | |
390 | }; | |
391 | ||
392 | /* or just use std::string? */ | |
393 | class string : public memento | |
394 | { | |
395 | public: | |
396 | string (context *ctxt, const char *text); | |
397 | ~string (); | |
398 | ||
399 | const char *c_str () { return m_buffer; } | |
400 | ||
401 | static string * from_printf (context *ctxt, const char *fmt, ...) | |
402 | GNU_PRINTF(2, 3); | |
403 | ||
404 | void replay_into (replayer *) {} | |
405 | ||
406 | private: | |
407 | string * make_debug_string (); | |
c97b0d1d | 408 | void write_reproducer (reproducer &r); |
863e76f9 | 409 | |
410 | private: | |
411 | size_t m_len; | |
412 | char *m_buffer; | |
413 | }; | |
414 | ||
415 | class location : public memento | |
416 | { | |
417 | public: | |
c97b0d1d | 418 | location (context *ctxt, string *filename, int line, int column, |
419 | bool created_by_user) | |
863e76f9 | 420 | : memento (ctxt), |
421 | m_filename (filename), | |
422 | m_line (line), | |
c97b0d1d | 423 | m_column (column), |
424 | m_created_by_user (created_by_user) | |
863e76f9 | 425 | {} |
426 | ||
427 | void replay_into (replayer *r); | |
428 | ||
429 | playback::location * | |
430 | playback_location (replayer *r) | |
431 | { | |
432 | /* Normally during playback, we can walk forwards through the list of | |
433 | recording objects, playing them back. The ordering of recording | |
434 | ensures that everything that a recording object refers to has | |
435 | already been played back, so we can simply look up the relevant | |
436 | m_playback_obj. | |
437 | ||
438 | Locations are an exception, due to the "write_to_dump" method of | |
439 | recording::statement. This method can set a new location on a | |
440 | statement after the statement is created, and thus the location | |
441 | appears in the context's memento list *after* the statement that | |
442 | refers to it. | |
443 | ||
444 | In such circumstances, the statement is replayed *before* the location, | |
445 | when the latter doesn't yet have a playback object. | |
446 | ||
447 | Hence we need to ensure that locations have playback objects. */ | |
448 | if (!m_playback_obj) | |
449 | { | |
450 | replay_into (r); | |
451 | } | |
452 | gcc_assert (m_playback_obj); | |
453 | return static_cast <playback::location *> (m_playback_obj); | |
454 | } | |
455 | ||
c97b0d1d | 456 | location *dyn_cast_location () { return this; } |
457 | bool created_by_user () const { return m_created_by_user; } | |
458 | ||
863e76f9 | 459 | private: |
460 | string * make_debug_string (); | |
c97b0d1d | 461 | void write_reproducer (reproducer &r); |
863e76f9 | 462 | |
463 | private: | |
464 | string *m_filename; | |
465 | int m_line; | |
466 | int m_column; | |
c97b0d1d | 467 | bool m_created_by_user; |
863e76f9 | 468 | }; |
469 | ||
470 | class type : public memento | |
471 | { | |
472 | public: | |
473 | type *get_pointer (); | |
474 | type *get_const (); | |
475 | type *get_volatile (); | |
476 | ||
477 | /* Get the type obtained when dereferencing this type. | |
478 | ||
479 | This will return NULL if it's not valid to dereference this type. | |
480 | The caller is responsible for setting an error. */ | |
481 | virtual type *dereference () = 0; | |
482 | ||
483 | /* Dynamic casts. */ | |
484 | virtual function_type *dyn_cast_function_type () { return NULL; } | |
485 | virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; } | |
486 | virtual struct_ *dyn_cast_struct () { return NULL; } | |
487 | ||
488 | /* Is it typesafe to copy to this type from rtype? */ | |
489 | virtual bool accepts_writes_from (type *rtype) | |
490 | { | |
491 | gcc_assert (rtype); | |
492 | return this == rtype->unqualified (); | |
493 | } | |
494 | ||
495 | /* Strip off "const" etc */ | |
496 | virtual type *unqualified () | |
497 | { | |
498 | return this; | |
499 | } | |
500 | ||
501 | virtual bool is_int () const = 0; | |
502 | virtual bool is_float () const = 0; | |
503 | virtual bool is_bool () const = 0; | |
504 | virtual type *is_pointer () = 0; | |
505 | virtual type *is_array () = 0; | |
bde9c336 | 506 | virtual bool is_void () const { return false; } |
d0278351 | 507 | virtual bool has_known_size () const { return true; } |
863e76f9 | 508 | |
509 | bool is_numeric () const | |
510 | { | |
511 | return is_int () || is_float () || is_bool (); | |
512 | } | |
513 | ||
514 | playback::type * | |
515 | playback_type () | |
516 | { | |
517 | return static_cast <playback::type *> (m_playback_obj); | |
518 | } | |
519 | ||
c97b0d1d | 520 | virtual const char *access_as_type (reproducer &r); |
521 | ||
863e76f9 | 522 | protected: |
523 | type (context *ctxt) | |
524 | : memento (ctxt), | |
525 | m_pointer_to_this_type (NULL) | |
526 | {} | |
527 | ||
528 | private: | |
529 | type *m_pointer_to_this_type; | |
530 | }; | |
531 | ||
8a5a4b5e | 532 | /* Result of "gcc_jit_context_get_type". */ |
863e76f9 | 533 | class memento_of_get_type : public type |
534 | { | |
535 | public: | |
536 | memento_of_get_type (context *ctxt, | |
537 | enum gcc_jit_types kind) | |
538 | : type (ctxt), | |
539 | m_kind (kind) {} | |
540 | ||
541 | type *dereference (); | |
542 | ||
543 | bool accepts_writes_from (type *rtype) | |
544 | { | |
545 | if (m_kind == GCC_JIT_TYPE_VOID_PTR) | |
546 | if (rtype->is_pointer ()) | |
547 | { | |
548 | /* LHS (this) is type (void *), and the RHS is a pointer: | |
549 | accept it: */ | |
550 | return true; | |
551 | } | |
552 | ||
553 | return type::accepts_writes_from (rtype); | |
554 | } | |
555 | ||
556 | bool is_int () const; | |
557 | bool is_float () const; | |
558 | bool is_bool () const; | |
559 | type *is_pointer () { return dereference (); } | |
560 | type *is_array () { return NULL; } | |
bde9c336 | 561 | bool is_void () const { return m_kind == GCC_JIT_TYPE_VOID; } |
863e76f9 | 562 | |
563 | public: | |
564 | void replay_into (replayer *r); | |
565 | ||
566 | private: | |
567 | string * make_debug_string (); | |
c97b0d1d | 568 | void write_reproducer (reproducer &r); |
863e76f9 | 569 | |
570 | private: | |
571 | enum gcc_jit_types m_kind; | |
572 | }; | |
573 | ||
574 | /* Result of "gcc_jit_type_get_pointer". */ | |
575 | class memento_of_get_pointer : public type | |
576 | { | |
577 | public: | |
578 | memento_of_get_pointer (type *other_type) | |
579 | : type (other_type->m_ctxt), | |
580 | m_other_type (other_type) {} | |
581 | ||
582 | type *dereference () { return m_other_type; } | |
583 | ||
584 | bool accepts_writes_from (type *rtype); | |
585 | ||
586 | void replay_into (replayer *r); | |
587 | ||
588 | bool is_int () const { return false; } | |
589 | bool is_float () const { return false; } | |
590 | bool is_bool () const { return false; } | |
591 | type *is_pointer () { return m_other_type; } | |
592 | type *is_array () { return NULL; } | |
593 | ||
594 | private: | |
595 | string * make_debug_string (); | |
c97b0d1d | 596 | void write_reproducer (reproducer &r); |
863e76f9 | 597 | |
598 | private: | |
599 | type *m_other_type; | |
600 | }; | |
601 | ||
602 | /* Result of "gcc_jit_type_get_const". */ | |
603 | class memento_of_get_const : public type | |
604 | { | |
605 | public: | |
606 | memento_of_get_const (type *other_type) | |
607 | : type (other_type->m_ctxt), | |
608 | m_other_type (other_type) {} | |
609 | ||
610 | type *dereference () { return m_other_type->dereference (); } | |
611 | ||
612 | bool accepts_writes_from (type */*rtype*/) | |
613 | { | |
614 | /* Can't write to a "const". */ | |
615 | return false; | |
616 | } | |
617 | ||
618 | /* Strip off the "const", giving the underlying type. */ | |
619 | type *unqualified () { return m_other_type; } | |
620 | ||
621 | bool is_int () const { return m_other_type->is_int (); } | |
622 | bool is_float () const { return m_other_type->is_float (); } | |
623 | bool is_bool () const { return m_other_type->is_bool (); } | |
624 | type *is_pointer () { return m_other_type->is_pointer (); } | |
625 | type *is_array () { return m_other_type->is_array (); } | |
626 | ||
627 | void replay_into (replayer *); | |
628 | ||
629 | private: | |
630 | string * make_debug_string (); | |
c97b0d1d | 631 | void write_reproducer (reproducer &r); |
863e76f9 | 632 | |
633 | private: | |
634 | type *m_other_type; | |
635 | }; | |
636 | ||
637 | /* Result of "gcc_jit_type_get_volatile". */ | |
638 | class memento_of_get_volatile : public type | |
639 | { | |
640 | public: | |
641 | memento_of_get_volatile (type *other_type) | |
642 | : type (other_type->m_ctxt), | |
643 | m_other_type (other_type) {} | |
644 | ||
645 | type *dereference () { return m_other_type->dereference (); } | |
646 | ||
647 | /* Strip off the "volatile", giving the underlying type. */ | |
648 | type *unqualified () { return m_other_type; } | |
649 | ||
650 | bool is_int () const { return m_other_type->is_int (); } | |
651 | bool is_float () const { return m_other_type->is_float (); } | |
652 | bool is_bool () const { return m_other_type->is_bool (); } | |
653 | type *is_pointer () { return m_other_type->is_pointer (); } | |
654 | type *is_array () { return m_other_type->is_array (); } | |
655 | ||
656 | void replay_into (replayer *); | |
657 | ||
658 | private: | |
659 | string * make_debug_string (); | |
c97b0d1d | 660 | void write_reproducer (reproducer &r); |
863e76f9 | 661 | |
662 | private: | |
663 | type *m_other_type; | |
664 | }; | |
665 | ||
666 | class array_type : public type | |
667 | { | |
668 | public: | |
669 | array_type (context *ctxt, | |
670 | location *loc, | |
671 | type *element_type, | |
672 | int num_elements) | |
673 | : type (ctxt), | |
674 | m_loc (loc), | |
675 | m_element_type (element_type), | |
676 | m_num_elements (num_elements) | |
677 | {} | |
678 | ||
679 | type *dereference (); | |
680 | ||
681 | bool is_int () const { return false; } | |
682 | bool is_float () const { return false; } | |
683 | bool is_bool () const { return false; } | |
684 | type *is_pointer () { return NULL; } | |
685 | type *is_array () { return m_element_type; } | |
686 | ||
687 | void replay_into (replayer *); | |
688 | ||
689 | private: | |
690 | string * make_debug_string (); | |
c97b0d1d | 691 | void write_reproducer (reproducer &r); |
863e76f9 | 692 | |
693 | private: | |
694 | location *m_loc; | |
695 | type *m_element_type; | |
696 | int m_num_elements; | |
697 | }; | |
698 | ||
699 | class function_type : public type | |
700 | { | |
701 | public: | |
702 | function_type (context *ctxt, | |
703 | type *return_type, | |
704 | int num_params, | |
705 | type **param_types, | |
706 | int is_variadic); | |
707 | ||
708 | type *dereference (); | |
709 | function_type *dyn_cast_function_type () { return this; } | |
710 | function_type *as_a_function_type () { return this; } | |
711 | ||
712 | bool is_int () const { return false; } | |
713 | bool is_float () const { return false; } | |
714 | bool is_bool () const { return false; } | |
715 | type *is_pointer () { return NULL; } | |
716 | type *is_array () { return NULL; } | |
717 | ||
718 | void replay_into (replayer *); | |
719 | ||
720 | type * get_return_type () const { return m_return_type; } | |
b9a4cef3 | 721 | const vec<type *> &get_param_types () const { return m_param_types; } |
863e76f9 | 722 | int is_variadic () const { return m_is_variadic; } |
723 | ||
724 | string * make_debug_string_with_ptr (); | |
725 | ||
c97b0d1d | 726 | void |
727 | write_deferred_reproducer (reproducer &r, | |
728 | memento *ptr_type); | |
729 | ||
863e76f9 | 730 | private: |
731 | string * make_debug_string (); | |
732 | string * make_debug_string_with (const char *); | |
c97b0d1d | 733 | void write_reproducer (reproducer &r); |
863e76f9 | 734 | |
735 | private: | |
736 | type *m_return_type; | |
b9a4cef3 | 737 | auto_vec<type *> m_param_types; |
863e76f9 | 738 | int m_is_variadic; |
739 | }; | |
740 | ||
741 | class field : public memento | |
742 | { | |
743 | public: | |
744 | field (context *ctxt, | |
745 | location *loc, | |
746 | type *type, | |
747 | string *name) | |
748 | : memento (ctxt), | |
749 | m_loc (loc), | |
750 | m_type (type), | |
751 | m_name (name), | |
752 | m_container (NULL) | |
753 | {} | |
754 | ||
755 | type * get_type () const { return m_type; } | |
756 | ||
757 | compound_type * get_container () const { return m_container; } | |
758 | void set_container (compound_type *c) { m_container = c; } | |
759 | ||
760 | void replay_into (replayer *); | |
761 | ||
762 | void write_to_dump (dump &d); | |
763 | ||
764 | playback::field * | |
765 | playback_field () const | |
766 | { | |
767 | return static_cast <playback::field *> (m_playback_obj); | |
768 | } | |
769 | ||
770 | private: | |
771 | string * make_debug_string (); | |
c97b0d1d | 772 | void write_reproducer (reproducer &r); |
863e76f9 | 773 | |
774 | private: | |
775 | location *m_loc; | |
776 | type *m_type; | |
777 | string *m_name; | |
778 | compound_type *m_container; | |
779 | }; | |
780 | ||
781 | /* Base class for struct_ and union_ */ | |
782 | class compound_type : public type | |
783 | { | |
784 | public: | |
785 | compound_type (context *ctxt, | |
786 | location *loc, | |
787 | string *name); | |
788 | ||
789 | string *get_name () const { return m_name; } | |
790 | location *get_loc () const { return m_loc; } | |
791 | fields * get_fields () { return m_fields; } | |
792 | ||
793 | void | |
794 | set_fields (location *loc, | |
795 | int num_fields, | |
796 | field **fields); | |
797 | ||
798 | type *dereference (); | |
799 | ||
800 | bool is_int () const { return false; } | |
801 | bool is_float () const { return false; } | |
802 | bool is_bool () const { return false; } | |
803 | type *is_pointer () { return NULL; } | |
804 | type *is_array () { return NULL; } | |
805 | ||
d0278351 | 806 | bool has_known_size () const { return m_fields != NULL; } |
807 | ||
863e76f9 | 808 | playback::compound_type * |
809 | playback_compound_type () | |
810 | { | |
811 | return static_cast <playback::compound_type *> (m_playback_obj); | |
812 | } | |
813 | ||
814 | private: | |
815 | location *m_loc; | |
816 | string *m_name; | |
817 | fields *m_fields; | |
818 | }; | |
819 | ||
820 | class struct_ : public compound_type | |
821 | { | |
822 | public: | |
823 | struct_ (context *ctxt, | |
824 | location *loc, | |
825 | string *name); | |
826 | ||
827 | struct_ *dyn_cast_struct () { return this; } | |
828 | ||
829 | type * | |
830 | as_type () { return this; } | |
831 | ||
832 | void replay_into (replayer *r); | |
833 | ||
c97b0d1d | 834 | const char *access_as_type (reproducer &r); |
835 | ||
863e76f9 | 836 | private: |
837 | string * make_debug_string (); | |
c97b0d1d | 838 | void write_reproducer (reproducer &r); |
863e76f9 | 839 | }; |
840 | ||
841 | // memento of struct_::set_fields | |
842 | class fields : public memento | |
843 | { | |
844 | public: | |
845 | fields (compound_type *struct_or_union, | |
846 | int num_fields, | |
847 | field **fields); | |
848 | ||
849 | void replay_into (replayer *r); | |
850 | ||
851 | void write_to_dump (dump &d); | |
852 | ||
c97b0d1d | 853 | int length () const { return m_fields.length (); } |
854 | field *get_field (int i) const { return m_fields[i]; } | |
855 | ||
863e76f9 | 856 | private: |
857 | string * make_debug_string (); | |
c97b0d1d | 858 | void write_reproducer (reproducer &r); |
863e76f9 | 859 | |
860 | private: | |
861 | compound_type *m_struct_or_union; | |
b9a4cef3 | 862 | auto_vec<field *> m_fields; |
863e76f9 | 863 | }; |
864 | ||
865 | class union_ : public compound_type | |
866 | { | |
867 | public: | |
868 | union_ (context *ctxt, | |
869 | location *loc, | |
870 | string *name); | |
871 | ||
872 | void replay_into (replayer *r); | |
873 | ||
874 | private: | |
875 | string * make_debug_string (); | |
c97b0d1d | 876 | void write_reproducer (reproducer &r); |
863e76f9 | 877 | |
878 | private: | |
879 | location *m_loc; | |
880 | string *m_name; | |
863e76f9 | 881 | }; |
882 | ||
edee673f | 883 | /* An abstract base class for operations that visit all rvalues within an |
884 | expression tree. | |
885 | Currently the only implementation is class rvalue_usage_validator within | |
886 | jit-recording.c. */ | |
887 | ||
888 | class rvalue_visitor | |
889 | { | |
890 | public: | |
891 | virtual ~rvalue_visitor () {} | |
892 | virtual void visit (rvalue *rvalue) = 0; | |
893 | }; | |
894 | ||
8154a351 | 895 | /* When generating debug strings for rvalues we mimic C, so we need to |
896 | mimic C's precedence levels when handling compound expressions. | |
897 | These are in order from strongest precedence to weakest. */ | |
898 | enum precedence | |
899 | { | |
900 | PRECEDENCE_PRIMARY, | |
901 | PRECEDENCE_POSTFIX, | |
902 | PRECEDENCE_UNARY, | |
903 | PRECEDENCE_CAST, | |
904 | PRECEDENCE_MULTIPLICATIVE, | |
905 | PRECEDENCE_ADDITIVE, | |
906 | PRECEDENCE_SHIFT, | |
907 | PRECEDENCE_RELATIONAL, | |
908 | PRECEDENCE_EQUALITY, | |
909 | PRECEDENCE_BITWISE_AND, | |
910 | PRECEDENCE_BITWISE_XOR, | |
911 | PRECEDENCE_BITWISE_IOR, | |
912 | PRECEDENCE_LOGICAL_AND, | |
913 | PRECEDENCE_LOGICAL_OR | |
914 | }; | |
915 | ||
863e76f9 | 916 | class rvalue : public memento |
917 | { | |
918 | public: | |
919 | rvalue (context *ctxt, | |
920 | location *loc, | |
921 | type *type_) | |
922 | : memento (ctxt), | |
923 | m_loc (loc), | |
edee673f | 924 | m_type (type_), |
8154a351 | 925 | m_scope (NULL), |
926 | m_parenthesized_string (NULL) | |
863e76f9 | 927 | { |
928 | gcc_assert (type_); | |
929 | } | |
930 | ||
edee673f | 931 | location * get_loc () const { return m_loc; } |
932 | ||
863e76f9 | 933 | /* Get the recording::type of this rvalue. |
934 | ||
935 | Implements the post-error-checking part of | |
936 | gcc_jit_rvalue_get_type. */ | |
937 | type * get_type () const { return m_type; } | |
938 | ||
939 | playback::rvalue * | |
940 | playback_rvalue () const | |
941 | { | |
942 | return static_cast <playback::rvalue *> (m_playback_obj); | |
943 | } | |
944 | rvalue * | |
945 | access_field (location *loc, | |
946 | field *field); | |
947 | ||
948 | lvalue * | |
949 | dereference_field (location *loc, | |
950 | field *field); | |
951 | ||
952 | lvalue * | |
953 | dereference (location *loc); | |
954 | ||
edee673f | 955 | void |
956 | verify_valid_within_stmt (const char *api_funcname, statement *s); | |
957 | ||
958 | virtual void visit_children (rvalue_visitor *v) = 0; | |
959 | ||
960 | void set_scope (function *scope); | |
961 | function *get_scope () const { return m_scope; } | |
962 | ||
963 | /* Dynamic cast. */ | |
964 | virtual param *dyn_cast_param () { return NULL; } | |
965 | ||
c97b0d1d | 966 | virtual const char *access_as_rvalue (reproducer &r); |
967 | ||
8154a351 | 968 | /* Get the debug string, wrapped in parentheses. */ |
969 | const char * | |
970 | get_debug_string_parens (enum precedence outer_prec); | |
971 | ||
a24ef8d2 | 972 | virtual bool is_constant () const { return false; } |
973 | virtual bool get_wide_int (wide_int *) const { return false; } | |
974 | ||
8154a351 | 975 | private: |
976 | virtual enum precedence get_precedence () const = 0; | |
977 | ||
863e76f9 | 978 | protected: |
979 | location *m_loc; | |
980 | type *m_type; | |
edee673f | 981 | |
982 | private: | |
983 | function *m_scope; /* NULL for globals, non-NULL for locals/params */ | |
8154a351 | 984 | string *m_parenthesized_string; |
863e76f9 | 985 | }; |
986 | ||
987 | class lvalue : public rvalue | |
988 | { | |
989 | public: | |
990 | lvalue (context *ctxt, | |
991 | location *loc, | |
992 | type *type_) | |
993 | : rvalue (ctxt, loc, type_) | |
994 | {} | |
995 | ||
996 | playback::lvalue * | |
997 | playback_lvalue () const | |
998 | { | |
999 | return static_cast <playback::lvalue *> (m_playback_obj); | |
1000 | } | |
1001 | ||
1002 | lvalue * | |
1003 | access_field (location *loc, | |
1004 | field *field); | |
1005 | ||
1006 | rvalue * | |
1007 | get_address (location *loc); | |
1008 | ||
1009 | rvalue * | |
1010 | as_rvalue () { return this; } | |
c97b0d1d | 1011 | |
1012 | const char *access_as_rvalue (reproducer &r); | |
1013 | virtual const char *access_as_lvalue (reproducer &r); | |
863e76f9 | 1014 | }; |
1015 | ||
1016 | class param : public lvalue | |
1017 | { | |
1018 | public: | |
1019 | param (context *ctxt, | |
1020 | location *loc, | |
1021 | type *type, | |
1022 | string *name) | |
1023 | : lvalue (ctxt, loc, type), | |
1024 | m_name (name) {} | |
1025 | ||
1026 | lvalue * | |
1027 | as_lvalue () { return this; } | |
1028 | ||
1029 | void replay_into (replayer *r); | |
1030 | ||
edee673f | 1031 | void visit_children (rvalue_visitor *) {} |
1032 | ||
863e76f9 | 1033 | playback::param * |
1034 | playback_param () const | |
1035 | { | |
1036 | return static_cast <playback::param *> (m_playback_obj); | |
1037 | } | |
1038 | ||
edee673f | 1039 | param *dyn_cast_param () { return this; } |
1040 | ||
c97b0d1d | 1041 | const char *access_as_rvalue (reproducer &r); |
1042 | const char *access_as_lvalue (reproducer &r); | |
1043 | ||
863e76f9 | 1044 | private: |
1045 | string * make_debug_string () { return m_name; } | |
c97b0d1d | 1046 | void write_reproducer (reproducer &r); |
8154a351 | 1047 | enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; } |
863e76f9 | 1048 | |
1049 | private: | |
1050 | string *m_name; | |
1051 | }; | |
1052 | ||
1053 | class function : public memento | |
1054 | { | |
1055 | public: | |
1056 | function (context *ctxt, | |
1057 | location *loc, | |
1058 | enum gcc_jit_function_kind kind, | |
1059 | type *return_type, | |
1060 | string *name, | |
1061 | int num_params, | |
1062 | param **params, | |
1063 | int is_variadic, | |
1064 | enum built_in_function builtin_id); | |
1065 | ||
1066 | void replay_into (replayer *r); | |
1067 | ||
1068 | playback::function * | |
1069 | playback_function () const | |
1070 | { | |
1071 | return static_cast <playback::function *> (m_playback_obj); | |
1072 | } | |
1073 | ||
1074 | enum gcc_jit_function_kind get_kind () const { return m_kind; } | |
1075 | ||
1076 | lvalue * | |
1077 | new_local (location *loc, | |
1078 | type *type, | |
1079 | const char *name); | |
1080 | ||
1081 | block* | |
1082 | new_block (const char *name); | |
1083 | ||
edee673f | 1084 | location *get_loc () const { return m_loc; } |
863e76f9 | 1085 | type *get_return_type () const { return m_return_type; } |
1086 | string * get_name () const { return m_name; } | |
b9a4cef3 | 1087 | const vec<param *> &get_params () const { return m_params; } |
863e76f9 | 1088 | |
1089 | /* Get the given param by index. | |
1090 | Implements the post-error-checking part of | |
1091 | gcc_jit_function_get_param. */ | |
1092 | param *get_param (int i) const { return m_params[i]; } | |
1093 | ||
1094 | bool is_variadic () const { return m_is_variadic; } | |
1095 | ||
1096 | void write_to_dump (dump &d); | |
1097 | ||
1098 | void validate (); | |
1099 | ||
1100 | void dump_to_dot (const char *path); | |
1101 | ||
1102 | private: | |
1103 | string * make_debug_string (); | |
c97b0d1d | 1104 | void write_reproducer (reproducer &r); |
863e76f9 | 1105 | |
1106 | private: | |
1107 | location *m_loc; | |
1108 | enum gcc_jit_function_kind m_kind; | |
1109 | type *m_return_type; | |
1110 | string *m_name; | |
b9a4cef3 | 1111 | auto_vec<param *> m_params; |
863e76f9 | 1112 | int m_is_variadic; |
1113 | enum built_in_function m_builtin_id; | |
b9a4cef3 | 1114 | auto_vec<local *> m_locals; |
1115 | auto_vec<block *> m_blocks; | |
863e76f9 | 1116 | }; |
1117 | ||
1118 | class block : public memento | |
1119 | { | |
1120 | public: | |
1121 | block (function *func, int index, string *name) | |
1122 | : memento (func->m_ctxt), | |
1123 | m_func (func), | |
1124 | m_index (index), | |
1125 | m_name (name), | |
1126 | m_statements (), | |
1127 | m_has_been_terminated (false), | |
1128 | m_is_reachable (false) | |
1129 | { | |
1130 | } | |
1131 | ||
1132 | /* Get the recording::function containing this block. | |
1133 | Implements the post-error-checking part of | |
1134 | gcc_jit_block_get_function. */ | |
1135 | function *get_function () { return m_func; } | |
1136 | ||
1137 | bool has_been_terminated () { return m_has_been_terminated; } | |
1138 | bool is_reachable () { return m_is_reachable; } | |
1139 | ||
edee673f | 1140 | statement * |
863e76f9 | 1141 | add_eval (location *loc, |
1142 | rvalue *rvalue); | |
1143 | ||
edee673f | 1144 | statement * |
863e76f9 | 1145 | add_assignment (location *loc, |
1146 | lvalue *lvalue, | |
1147 | rvalue *rvalue); | |
1148 | ||
edee673f | 1149 | statement * |
863e76f9 | 1150 | add_assignment_op (location *loc, |
1151 | lvalue *lvalue, | |
1152 | enum gcc_jit_binary_op op, | |
1153 | rvalue *rvalue); | |
1154 | ||
edee673f | 1155 | statement * |
863e76f9 | 1156 | add_comment (location *loc, |
1157 | const char *text); | |
1158 | ||
edee673f | 1159 | statement * |
863e76f9 | 1160 | end_with_conditional (location *loc, |
1161 | rvalue *boolval, | |
1162 | block *on_true, | |
1163 | block *on_false); | |
1164 | ||
edee673f | 1165 | statement * |
863e76f9 | 1166 | end_with_jump (location *loc, |
1167 | block *target); | |
1168 | ||
edee673f | 1169 | statement * |
863e76f9 | 1170 | end_with_return (location *loc, |
1171 | rvalue *rvalue); | |
1172 | ||
a24ef8d2 | 1173 | statement * |
1174 | end_with_switch (location *loc, | |
1175 | rvalue *expr, | |
1176 | block *default_block, | |
1177 | int num_cases, | |
1178 | case_ **cases); | |
1179 | ||
863e76f9 | 1180 | playback::block * |
1181 | playback_block () const | |
1182 | { | |
1183 | return static_cast <playback::block *> (m_playback_obj); | |
1184 | } | |
1185 | ||
1186 | void write_to_dump (dump &d); | |
1187 | ||
1188 | bool validate (); | |
1189 | ||
1190 | location *get_loc () const; | |
1191 | ||
1192 | statement *get_first_statement () const; | |
1193 | statement *get_last_statement () const; | |
1194 | ||
a24ef8d2 | 1195 | vec <block *> get_successor_blocks () const; |
863e76f9 | 1196 | |
1197 | private: | |
1198 | string * make_debug_string (); | |
c97b0d1d | 1199 | void write_reproducer (reproducer &r); |
863e76f9 | 1200 | |
1201 | void replay_into (replayer *r); | |
1202 | ||
1203 | void dump_to_dot (pretty_printer *pp); | |
1204 | void dump_edges_to_dot (pretty_printer *pp); | |
1205 | ||
1206 | private: | |
1207 | function *m_func; | |
1208 | int m_index; | |
1209 | string *m_name; | |
b9a4cef3 | 1210 | auto_vec<statement *> m_statements; |
863e76f9 | 1211 | bool m_has_been_terminated; |
1212 | bool m_is_reachable; | |
1213 | ||
1214 | friend class function; | |
1215 | }; | |
1216 | ||
1217 | class global : public lvalue | |
1218 | { | |
1219 | public: | |
1220 | global (context *ctxt, | |
1221 | location *loc, | |
15b6c83e | 1222 | enum gcc_jit_global_kind kind, |
863e76f9 | 1223 | type *type, |
1224 | string *name) | |
1225 | : lvalue (ctxt, loc, type), | |
15b6c83e | 1226 | m_kind (kind), |
863e76f9 | 1227 | m_name (name) |
1228 | {} | |
1229 | ||
1230 | void replay_into (replayer *); | |
1231 | ||
edee673f | 1232 | void visit_children (rvalue_visitor *) {} |
1233 | ||
15b6c83e | 1234 | void write_to_dump (dump &d); |
1235 | ||
863e76f9 | 1236 | private: |
1237 | string * make_debug_string () { return m_name; } | |
c97b0d1d | 1238 | void write_reproducer (reproducer &r); |
8154a351 | 1239 | enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; } |
863e76f9 | 1240 | |
1241 | private: | |
15b6c83e | 1242 | enum gcc_jit_global_kind m_kind; |
863e76f9 | 1243 | string *m_name; |
1244 | }; | |
1245 | ||
feea5a1f | 1246 | template <typename HOST_TYPE> |
1247 | class memento_of_new_rvalue_from_const : public rvalue | |
863e76f9 | 1248 | { |
1249 | public: | |
feea5a1f | 1250 | memento_of_new_rvalue_from_const (context *ctxt, |
1251 | location *loc, | |
1252 | type *type, | |
1253 | HOST_TYPE value) | |
1254 | : rvalue (ctxt, loc, type), | |
863e76f9 | 1255 | m_value (value) {} |
1256 | ||
1257 | void replay_into (replayer *r); | |
1258 | ||
edee673f | 1259 | void visit_children (rvalue_visitor *) {} |
1260 | ||
a24ef8d2 | 1261 | bool is_constant () const { return true; } |
1262 | ||
1263 | bool get_wide_int (wide_int *out) const; | |
1264 | ||
863e76f9 | 1265 | private: |
1266 | string * make_debug_string (); | |
c97b0d1d | 1267 | void write_reproducer (reproducer &r); |
8154a351 | 1268 | enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; } |
863e76f9 | 1269 | |
1270 | private: | |
feea5a1f | 1271 | HOST_TYPE m_value; |
863e76f9 | 1272 | }; |
1273 | ||
1274 | class memento_of_new_string_literal : public rvalue | |
1275 | { | |
1276 | public: | |
1277 | memento_of_new_string_literal (context *ctxt, | |
1278 | location *loc, | |
1279 | string *value) | |
1280 | : rvalue (ctxt, loc, ctxt->get_type (GCC_JIT_TYPE_CONST_CHAR_PTR)), | |
1281 | m_value (value) {} | |
1282 | ||
1283 | void replay_into (replayer *r); | |
1284 | ||
edee673f | 1285 | void visit_children (rvalue_visitor *) {} |
1286 | ||
863e76f9 | 1287 | private: |
1288 | string * make_debug_string (); | |
c97b0d1d | 1289 | void write_reproducer (reproducer &r); |
8154a351 | 1290 | enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; } |
863e76f9 | 1291 | |
1292 | private: | |
1293 | string *m_value; | |
1294 | }; | |
1295 | ||
1296 | class unary_op : public rvalue | |
1297 | { | |
1298 | public: | |
1299 | unary_op (context *ctxt, | |
1300 | location *loc, | |
1301 | enum gcc_jit_unary_op op, | |
1302 | type *result_type, | |
1303 | rvalue *a) | |
1304 | : rvalue (ctxt, loc, result_type), | |
1305 | m_op (op), | |
1306 | m_a (a) | |
1307 | {} | |
1308 | ||
1309 | void replay_into (replayer *r); | |
1310 | ||
edee673f | 1311 | void visit_children (rvalue_visitor *v); |
1312 | ||
863e76f9 | 1313 | private: |
1314 | string * make_debug_string (); | |
c97b0d1d | 1315 | void write_reproducer (reproducer &r); |
8154a351 | 1316 | enum precedence get_precedence () const {return PRECEDENCE_UNARY;} |
863e76f9 | 1317 | |
1318 | private: | |
1319 | enum gcc_jit_unary_op m_op; | |
1320 | rvalue *m_a; | |
1321 | }; | |
1322 | ||
1323 | class binary_op : public rvalue | |
1324 | { | |
1325 | public: | |
1326 | binary_op (context *ctxt, | |
1327 | location *loc, | |
1328 | enum gcc_jit_binary_op op, | |
1329 | type *result_type, | |
1330 | rvalue *a, rvalue *b) | |
1331 | : rvalue (ctxt, loc, result_type), | |
1332 | m_op (op), | |
1333 | m_a (a), | |
1334 | m_b (b) {} | |
1335 | ||
1336 | void replay_into (replayer *r); | |
1337 | ||
edee673f | 1338 | void visit_children (rvalue_visitor *v); |
1339 | ||
863e76f9 | 1340 | private: |
1341 | string * make_debug_string (); | |
c97b0d1d | 1342 | void write_reproducer (reproducer &r); |
8154a351 | 1343 | enum precedence get_precedence () const; |
863e76f9 | 1344 | |
1345 | private: | |
1346 | enum gcc_jit_binary_op m_op; | |
1347 | rvalue *m_a; | |
1348 | rvalue *m_b; | |
1349 | }; | |
1350 | ||
1351 | class comparison : public rvalue | |
1352 | { | |
1353 | public: | |
1354 | comparison (context *ctxt, | |
1355 | location *loc, | |
1356 | enum gcc_jit_comparison op, | |
1357 | rvalue *a, rvalue *b) | |
1358 | : rvalue (ctxt, loc, ctxt->get_type (GCC_JIT_TYPE_BOOL)), | |
1359 | m_op (op), | |
1360 | m_a (a), | |
1361 | m_b (b) | |
1362 | {} | |
1363 | ||
1364 | void replay_into (replayer *r); | |
1365 | ||
edee673f | 1366 | void visit_children (rvalue_visitor *v); |
1367 | ||
863e76f9 | 1368 | private: |
1369 | string * make_debug_string (); | |
c97b0d1d | 1370 | void write_reproducer (reproducer &r); |
8154a351 | 1371 | enum precedence get_precedence () const; |
863e76f9 | 1372 | |
1373 | private: | |
1374 | enum gcc_jit_comparison m_op; | |
1375 | rvalue *m_a; | |
1376 | rvalue *m_b; | |
1377 | }; | |
1378 | ||
1379 | class cast : public rvalue | |
1380 | { | |
1381 | public: | |
1382 | cast (context *ctxt, | |
1383 | location *loc, | |
1384 | rvalue *a, | |
1385 | type *type_) | |
1386 | : rvalue (ctxt, loc, type_), | |
1387 | m_rvalue (a) | |
1388 | {} | |
1389 | ||
1390 | void replay_into (replayer *r); | |
1391 | ||
edee673f | 1392 | void visit_children (rvalue_visitor *v); |
1393 | ||
863e76f9 | 1394 | private: |
1395 | string * make_debug_string (); | |
c97b0d1d | 1396 | void write_reproducer (reproducer &r); |
8154a351 | 1397 | enum precedence get_precedence () const { return PRECEDENCE_CAST; } |
863e76f9 | 1398 | |
1399 | private: | |
1400 | rvalue *m_rvalue; | |
1401 | }; | |
1402 | ||
1403 | class call : public rvalue | |
1404 | { | |
1405 | public: | |
1406 | call (context *ctxt, | |
1407 | location *loc, | |
1408 | function *func, | |
1409 | int numargs, | |
1410 | rvalue **args); | |
1411 | ||
1412 | void replay_into (replayer *r); | |
1413 | ||
edee673f | 1414 | void visit_children (rvalue_visitor *v); |
1415 | ||
863e76f9 | 1416 | private: |
1417 | string * make_debug_string (); | |
c97b0d1d | 1418 | void write_reproducer (reproducer &r); |
8154a351 | 1419 | enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; } |
863e76f9 | 1420 | |
1421 | private: | |
1422 | function *m_func; | |
b9a4cef3 | 1423 | auto_vec<rvalue *> m_args; |
863e76f9 | 1424 | }; |
1425 | ||
1426 | class call_through_ptr : public rvalue | |
1427 | { | |
1428 | public: | |
1429 | call_through_ptr (context *ctxt, | |
1430 | location *loc, | |
1431 | rvalue *fn_ptr, | |
1432 | int numargs, | |
1433 | rvalue **args); | |
1434 | ||
1435 | void replay_into (replayer *r); | |
1436 | ||
edee673f | 1437 | void visit_children (rvalue_visitor *v); |
1438 | ||
863e76f9 | 1439 | private: |
1440 | string * make_debug_string (); | |
c97b0d1d | 1441 | void write_reproducer (reproducer &r); |
8154a351 | 1442 | enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; } |
863e76f9 | 1443 | |
1444 | private: | |
1445 | rvalue *m_fn_ptr; | |
b9a4cef3 | 1446 | auto_vec<rvalue *> m_args; |
863e76f9 | 1447 | }; |
1448 | ||
1449 | class array_access : public lvalue | |
1450 | { | |
1451 | public: | |
1452 | array_access (context *ctxt, | |
1453 | location *loc, | |
1454 | rvalue *ptr, | |
1455 | rvalue *index) | |
1456 | : lvalue (ctxt, loc, ptr->get_type ()->dereference ()), | |
1457 | m_ptr (ptr), | |
1458 | m_index (index) | |
1459 | {} | |
1460 | ||
1461 | void replay_into (replayer *r); | |
1462 | ||
edee673f | 1463 | void visit_children (rvalue_visitor *v); |
1464 | ||
863e76f9 | 1465 | private: |
1466 | string * make_debug_string (); | |
c97b0d1d | 1467 | void write_reproducer (reproducer &r); |
8154a351 | 1468 | enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; } |
863e76f9 | 1469 | |
1470 | private: | |
1471 | rvalue *m_ptr; | |
1472 | rvalue *m_index; | |
1473 | }; | |
1474 | ||
1475 | class access_field_of_lvalue : public lvalue | |
1476 | { | |
1477 | public: | |
1478 | access_field_of_lvalue (context *ctxt, | |
1479 | location *loc, | |
1480 | lvalue *val, | |
1481 | field *field) | |
1482 | : lvalue (ctxt, loc, field->get_type ()), | |
1483 | m_lvalue (val), | |
1484 | m_field (field) | |
1485 | {} | |
1486 | ||
1487 | void replay_into (replayer *r); | |
1488 | ||
edee673f | 1489 | void visit_children (rvalue_visitor *v); |
1490 | ||
863e76f9 | 1491 | private: |
1492 | string * make_debug_string (); | |
c97b0d1d | 1493 | void write_reproducer (reproducer &r); |
8154a351 | 1494 | enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; } |
863e76f9 | 1495 | |
1496 | private: | |
1497 | lvalue *m_lvalue; | |
1498 | field *m_field; | |
1499 | }; | |
1500 | ||
1501 | class access_field_rvalue : public rvalue | |
1502 | { | |
1503 | public: | |
1504 | access_field_rvalue (context *ctxt, | |
1505 | location *loc, | |
1506 | rvalue *val, | |
1507 | field *field) | |
1508 | : rvalue (ctxt, loc, field->get_type ()), | |
1509 | m_rvalue (val), | |
1510 | m_field (field) | |
1511 | {} | |
1512 | ||
1513 | void replay_into (replayer *r); | |
1514 | ||
edee673f | 1515 | void visit_children (rvalue_visitor *v); |
1516 | ||
863e76f9 | 1517 | private: |
1518 | string * make_debug_string (); | |
c97b0d1d | 1519 | void write_reproducer (reproducer &r); |
8154a351 | 1520 | enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; } |
863e76f9 | 1521 | |
1522 | private: | |
1523 | rvalue *m_rvalue; | |
1524 | field *m_field; | |
1525 | }; | |
1526 | ||
1527 | class dereference_field_rvalue : public lvalue | |
1528 | { | |
1529 | public: | |
1530 | dereference_field_rvalue (context *ctxt, | |
1531 | location *loc, | |
1532 | rvalue *val, | |
1533 | field *field) | |
1534 | : lvalue (ctxt, loc, field->get_type ()), | |
1535 | m_rvalue (val), | |
1536 | m_field (field) | |
1537 | {} | |
1538 | ||
1539 | void replay_into (replayer *r); | |
1540 | ||
edee673f | 1541 | void visit_children (rvalue_visitor *v); |
1542 | ||
863e76f9 | 1543 | private: |
1544 | string * make_debug_string (); | |
c97b0d1d | 1545 | void write_reproducer (reproducer &r); |
8154a351 | 1546 | enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; } |
863e76f9 | 1547 | |
1548 | private: | |
1549 | rvalue *m_rvalue; | |
1550 | field *m_field; | |
1551 | }; | |
1552 | ||
1553 | class dereference_rvalue : public lvalue | |
1554 | { | |
1555 | public: | |
1556 | dereference_rvalue (context *ctxt, | |
1557 | location *loc, | |
1558 | rvalue *val) | |
1559 | : lvalue (ctxt, loc, val->get_type ()->dereference ()), | |
1560 | m_rvalue (val) {} | |
1561 | ||
1562 | void replay_into (replayer *r); | |
1563 | ||
edee673f | 1564 | void visit_children (rvalue_visitor *v); |
1565 | ||
863e76f9 | 1566 | private: |
1567 | string * make_debug_string (); | |
c97b0d1d | 1568 | void write_reproducer (reproducer &r); |
8154a351 | 1569 | enum precedence get_precedence () const { return PRECEDENCE_UNARY; } |
863e76f9 | 1570 | |
1571 | private: | |
1572 | rvalue *m_rvalue; | |
1573 | }; | |
1574 | ||
1575 | class get_address_of_lvalue : public rvalue | |
1576 | { | |
1577 | public: | |
1578 | get_address_of_lvalue (context *ctxt, | |
1579 | location *loc, | |
1580 | lvalue *val) | |
1581 | : rvalue (ctxt, loc, val->get_type ()->get_pointer ()), | |
1582 | m_lvalue (val) | |
1583 | {} | |
1584 | ||
1585 | void replay_into (replayer *r); | |
1586 | ||
edee673f | 1587 | void visit_children (rvalue_visitor *v); |
1588 | ||
863e76f9 | 1589 | private: |
1590 | string * make_debug_string (); | |
c97b0d1d | 1591 | void write_reproducer (reproducer &r); |
8154a351 | 1592 | enum precedence get_precedence () const { return PRECEDENCE_UNARY; } |
863e76f9 | 1593 | |
1594 | private: | |
1595 | lvalue *m_lvalue; | |
1596 | }; | |
1597 | ||
1598 | class local : public lvalue | |
1599 | { | |
1600 | public: | |
1601 | local (function *func, location *loc, type *type_, string *name) | |
1602 | : lvalue (func->m_ctxt, loc, type_), | |
1603 | m_func (func), | |
edee673f | 1604 | m_name (name) |
1605 | { | |
1606 | set_scope (func); | |
1607 | } | |
863e76f9 | 1608 | |
1609 | void replay_into (replayer *r); | |
1610 | ||
edee673f | 1611 | void visit_children (rvalue_visitor *) {} |
1612 | ||
863e76f9 | 1613 | void write_to_dump (dump &d); |
1614 | ||
1615 | private: | |
1616 | string * make_debug_string () { return m_name; } | |
c97b0d1d | 1617 | void write_reproducer (reproducer &r); |
8154a351 | 1618 | enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; } |
863e76f9 | 1619 | |
1620 | private: | |
1621 | function *m_func; | |
1622 | string *m_name; | |
1623 | }; | |
1624 | ||
1625 | class statement : public memento | |
1626 | { | |
1627 | public: | |
a24ef8d2 | 1628 | virtual vec <block *> get_successor_blocks () const; |
863e76f9 | 1629 | |
1630 | void write_to_dump (dump &d); | |
1631 | ||
edee673f | 1632 | block *get_block () const { return m_block; } |
863e76f9 | 1633 | location *get_loc () const { return m_loc; } |
1634 | ||
1635 | protected: | |
1636 | statement (block *b, location *loc) | |
1637 | : memento (b->m_ctxt), | |
1638 | m_block (b), | |
1639 | m_loc (loc) {} | |
1640 | ||
863e76f9 | 1641 | playback::location * |
1642 | playback_location (replayer *r) const | |
1643 | { | |
1644 | return ::gcc::jit::recording::playback_location (r, m_loc); | |
1645 | } | |
1646 | ||
1647 | private: | |
1648 | block *m_block; | |
1649 | location *m_loc; | |
1650 | }; | |
1651 | ||
1652 | class eval : public statement | |
1653 | { | |
1654 | public: | |
1655 | eval (block *b, | |
1656 | location *loc, | |
1657 | rvalue *rvalue) | |
1658 | : statement (b, loc), | |
1659 | m_rvalue (rvalue) {} | |
1660 | ||
1661 | void replay_into (replayer *r); | |
1662 | ||
1663 | private: | |
1664 | string * make_debug_string (); | |
c97b0d1d | 1665 | void write_reproducer (reproducer &r); |
863e76f9 | 1666 | |
1667 | private: | |
1668 | rvalue *m_rvalue; | |
1669 | }; | |
1670 | ||
1671 | class assignment : public statement | |
1672 | { | |
1673 | public: | |
1674 | assignment (block *b, | |
1675 | location *loc, | |
1676 | lvalue *lvalue, | |
1677 | rvalue *rvalue) | |
1678 | : statement (b, loc), | |
1679 | m_lvalue (lvalue), | |
1680 | m_rvalue (rvalue) {} | |
1681 | ||
1682 | void replay_into (replayer *r); | |
1683 | ||
1684 | private: | |
1685 | string * make_debug_string (); | |
c97b0d1d | 1686 | void write_reproducer (reproducer &r); |
863e76f9 | 1687 | |
1688 | private: | |
1689 | lvalue *m_lvalue; | |
1690 | rvalue *m_rvalue; | |
1691 | }; | |
1692 | ||
1693 | class assignment_op : public statement | |
1694 | { | |
1695 | public: | |
1696 | assignment_op (block *b, | |
1697 | location *loc, | |
1698 | lvalue *lvalue, | |
1699 | enum gcc_jit_binary_op op, | |
1700 | rvalue *rvalue) | |
1701 | : statement (b, loc), | |
1702 | m_lvalue (lvalue), | |
1703 | m_op (op), | |
1704 | m_rvalue (rvalue) {} | |
1705 | ||
1706 | void replay_into (replayer *r); | |
1707 | ||
1708 | private: | |
1709 | string * make_debug_string (); | |
c97b0d1d | 1710 | void write_reproducer (reproducer &r); |
863e76f9 | 1711 | |
1712 | private: | |
1713 | lvalue *m_lvalue; | |
1714 | enum gcc_jit_binary_op m_op; | |
1715 | rvalue *m_rvalue; | |
1716 | }; | |
1717 | ||
1718 | class comment : public statement | |
1719 | { | |
1720 | public: | |
1721 | comment (block *b, | |
1722 | location *loc, | |
1723 | string *text) | |
1724 | : statement (b, loc), | |
1725 | m_text (text) {} | |
1726 | ||
1727 | void replay_into (replayer *r); | |
1728 | ||
1729 | private: | |
1730 | string * make_debug_string (); | |
c97b0d1d | 1731 | void write_reproducer (reproducer &r); |
863e76f9 | 1732 | |
1733 | private: | |
1734 | string *m_text; | |
1735 | }; | |
1736 | ||
1737 | class conditional : public statement | |
1738 | { | |
1739 | public: | |
1740 | conditional (block *b, | |
1741 | location *loc, | |
1742 | rvalue *boolval, | |
1743 | block *on_true, | |
1744 | block *on_false) | |
1745 | : statement (b, loc), | |
1746 | m_boolval (boolval), | |
1747 | m_on_true (on_true), | |
1748 | m_on_false (on_false) {} | |
1749 | ||
1750 | void replay_into (replayer *r); | |
1751 | ||
a24ef8d2 | 1752 | vec <block *> get_successor_blocks () const; |
863e76f9 | 1753 | |
1754 | private: | |
1755 | string * make_debug_string (); | |
c97b0d1d | 1756 | void write_reproducer (reproducer &r); |
863e76f9 | 1757 | |
1758 | private: | |
1759 | rvalue *m_boolval; | |
1760 | block *m_on_true; | |
1761 | block *m_on_false; | |
1762 | }; | |
1763 | ||
1764 | class jump : public statement | |
1765 | { | |
1766 | public: | |
1767 | jump (block *b, | |
1768 | location *loc, | |
1769 | block *target) | |
1770 | : statement (b, loc), | |
1771 | m_target (target) {} | |
1772 | ||
1773 | void replay_into (replayer *r); | |
1774 | ||
a24ef8d2 | 1775 | vec <block *> get_successor_blocks () const; |
863e76f9 | 1776 | |
1777 | private: | |
1778 | string * make_debug_string (); | |
c97b0d1d | 1779 | void write_reproducer (reproducer &r); |
863e76f9 | 1780 | |
1781 | private: | |
1782 | block *m_target; | |
1783 | }; | |
1784 | ||
1785 | class return_ : public statement | |
1786 | { | |
1787 | public: | |
1788 | return_ (block *b, | |
1789 | location *loc, | |
1790 | rvalue *rvalue) | |
1791 | : statement (b, loc), | |
1792 | m_rvalue (rvalue) {} | |
1793 | ||
1794 | void replay_into (replayer *r); | |
1795 | ||
a24ef8d2 | 1796 | vec <block *> get_successor_blocks () const; |
863e76f9 | 1797 | |
1798 | private: | |
1799 | string * make_debug_string (); | |
c97b0d1d | 1800 | void write_reproducer (reproducer &r); |
863e76f9 | 1801 | |
1802 | private: | |
1803 | rvalue *m_rvalue; | |
1804 | }; | |
1805 | ||
a24ef8d2 | 1806 | class case_ : public memento |
1807 | { | |
1808 | public: | |
1809 | case_ (context *ctxt, | |
1810 | rvalue *min_value, | |
1811 | rvalue *max_value, | |
1812 | block *dest_block) | |
1813 | : memento (ctxt), | |
1814 | m_min_value (min_value), | |
1815 | m_max_value (max_value), | |
1816 | m_dest_block (dest_block) | |
1817 | {} | |
1818 | ||
1819 | rvalue *get_min_value () const { return m_min_value; } | |
1820 | rvalue *get_max_value () const { return m_max_value; } | |
1821 | block *get_dest_block () const { return m_dest_block; } | |
1822 | ||
1823 | void replay_into (replayer *) { /* empty */ } | |
1824 | ||
1825 | void write_reproducer (reproducer &r); | |
1826 | ||
1827 | private: | |
1828 | string * make_debug_string (); | |
1829 | ||
1830 | private: | |
1831 | rvalue *m_min_value; | |
1832 | rvalue *m_max_value; | |
1833 | block *m_dest_block; | |
1834 | }; | |
1835 | ||
1836 | class switch_ : public statement | |
1837 | { | |
1838 | public: | |
1839 | switch_ (block *b, | |
1840 | location *loc, | |
1841 | rvalue *expr, | |
1842 | block *default_block, | |
1843 | int num_cases, | |
1844 | case_ **cases); | |
1845 | ||
1846 | void replay_into (replayer *r); | |
1847 | ||
1848 | vec <block *> get_successor_blocks () const; | |
1849 | ||
1850 | private: | |
1851 | string * make_debug_string (); | |
1852 | void write_reproducer (reproducer &r); | |
1853 | ||
1854 | private: | |
1855 | rvalue *m_expr; | |
1856 | block *m_default_block; | |
1857 | auto_vec <case_ *> m_cases; | |
1858 | }; | |
1859 | ||
863e76f9 | 1860 | } // namespace gcc::jit::recording |
1861 | ||
feea5a1f | 1862 | /* Create a recording::memento_of_new_rvalue_from_const instance and add |
1863 | it to this context's list of mementos. | |
1864 | ||
1865 | Implements the post-error-checking part of | |
1866 | gcc_jit_context_new_rvalue_from_{int|long|double|ptr}. */ | |
1867 | ||
1868 | template <typename HOST_TYPE> | |
1869 | recording::rvalue * | |
1870 | recording::context::new_rvalue_from_const (recording::type *type, | |
1871 | HOST_TYPE value) | |
1872 | { | |
1873 | recording::rvalue *result = | |
1874 | new memento_of_new_rvalue_from_const <HOST_TYPE> (this, NULL, type, value); | |
1875 | record (result); | |
1876 | return result; | |
1877 | } | |
1878 | ||
863e76f9 | 1879 | } // namespace gcc::jit |
1880 | ||
1881 | } // namespace gcc | |
1882 | ||
1883 | #endif /* JIT_RECORDING_H */ |