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