1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2023 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 class timer;
28
29 namespace gcc {
30
31 namespace jit {
32
33 extern const char * const unary_op_reproducer_strings[];
34 extern const char * const binary_op_reproducer_strings[];
35
36 class result;
37 class dump;
38 class reproducer;
39
40 /**********************************************************************
41 Recording.
42 **********************************************************************/
43
44 namespace recording {
45
46 playback::location *
47 playback_location (replayer *r, location *loc);
48
49 const char *
50 playback_string (string *str);
51
52 playback::block *
53 playback_block (block *b);
54
55 /* A recording of a call to gcc_jit_context_enable_dump. */
56 struct requested_dump
57 {
58 const char *m_dumpname;
59 char **m_out_ptr;
60 };
61
62 /* A JIT-compilation context. */
63 class context : public log_user
64 {
65 public:
66 context (context *parent_ctxt);
67 ~context ();
68
69 builtins_manager *
70 get_builtins_manager ();
71
72 void record (memento *m);
73 void replay_into (replayer *r);
74 void disassociate_from_playback ();
75
76 string *
77 new_string (const char *text, bool escaped = false);
78
79 location *
80 new_location (const char *filename,
81 int line,
82 int column,
83 bool created_by_user);
84
85 type *
86 get_type (enum gcc_jit_types type);
87
88 type *
89 get_int_type (int num_bytes, int is_signed);
90
91 type *
92 new_array_type (location *loc,
93 type *element_type,
94 int num_elements);
95
96 field *
97 new_field (location *loc,
98 type *type,
99 const char *name);
100
101 field *
102 new_bitfield (location *loc,
103 type *type,
104 int width,
105 const char *name);
106
107 struct_ *
108 new_struct_type (location *loc,
109 const char *name);
110
111 union_ *
112 new_union_type (location *loc,
113 const char *name);
114
115 function_type *
116 new_function_type (type *return_type,
117 int num_params,
118 type **param_types,
119 int is_variadic);
120
121 type *
122 new_function_ptr_type (location *loc,
123 type *return_type,
124 int num_params,
125 type **param_types,
126 int is_variadic);
127
128 param *
129 new_param (location *loc,
130 type *type,
131 const char *name);
132
133 function *
134 new_function (location *loc,
135 enum gcc_jit_function_kind kind,
136 type *return_type,
137 const char *name,
138 int num_params,
139 param **params,
140 int is_variadic,
141 enum built_in_function builtin_id);
142
143 function *
144 get_builtin_function (const char *name);
145
146 lvalue *
147 new_global (location *loc,
148 enum gcc_jit_global_kind kind,
149 type *type,
150 const char *name);
151
152 rvalue *
153 new_ctor (location *loc,
154 type *type,
155 size_t num_values,
156 field **fields,
157 rvalue **values);
158
159 void
160 new_global_init_rvalue (lvalue *variable,
161 rvalue *init);
162
163 template <typename HOST_TYPE>
164 rvalue *
165 new_rvalue_from_const (type *type,
166 HOST_TYPE value);
167
168 rvalue *
169 new_string_literal (const char *value);
170
171 rvalue *
172 new_rvalue_from_vector (location *loc,
173 vector_type *type,
174 rvalue **elements);
175
176 rvalue *
177 new_unary_op (location *loc,
178 enum gcc_jit_unary_op op,
179 type *result_type,
180 rvalue *a);
181
182 rvalue *
183 new_binary_op (location *loc,
184 enum gcc_jit_binary_op op,
185 type *result_type,
186 rvalue *a, rvalue *b);
187
188 rvalue *
189 new_comparison (location *loc,
190 enum gcc_jit_comparison op,
191 rvalue *a, rvalue *b);
192
193 rvalue *
194 new_call (location *loc,
195 function *func,
196 int numargs, rvalue **args);
197
198 rvalue *
199 new_call_through_ptr (location *loc,
200 rvalue *fn_ptr,
201 int numargs, rvalue **args);
202
203 rvalue *
204 new_cast (location *loc,
205 rvalue *expr,
206 type *type_);
207
208 rvalue *
209 new_bitcast (location *loc,
210 rvalue *expr,
211 type *type_);
212
213 lvalue *
214 new_array_access (location *loc,
215 rvalue *ptr,
216 rvalue *index);
217
218 case_ *
219 new_case (rvalue *min_value,
220 rvalue *max_value,
221 block *block);
222
223 void
224 set_str_option (enum gcc_jit_str_option opt,
225 const char *value);
226
227 void
228 set_int_option (enum gcc_jit_int_option opt,
229 int value);
230
231 void
232 set_bool_option (enum gcc_jit_bool_option opt,
233 int value);
234
235 void
236 set_inner_bool_option (enum inner_bool_option inner_opt,
237 int value);
238
239 void
240 add_command_line_option (const char *optname);
241
242 void
243 append_command_line_options (vec <char *> *argvec);
244
245 void
246 add_driver_option (const char *optname);
247
248 void
249 append_driver_options (auto_string_vec *argvec);
250
251 void
252 enable_dump (const char *dumpname,
253 char **out_ptr);
254
255 const char *
256 get_str_option (enum gcc_jit_str_option opt) const
257 {
258 return m_str_options[opt];
259 }
260
261 int
262 get_int_option (enum gcc_jit_int_option opt) const
263 {
264 return m_int_options[opt];
265 }
266
267 int
268 get_bool_option (enum gcc_jit_bool_option opt) const
269 {
270 return m_bool_options[opt];
271 }
272
273 int
274 get_inner_bool_option (enum inner_bool_option opt) const
275 {
276 return m_inner_bool_options[opt];
277 }
278
279 result *
280 compile ();
281
282 void
283 compile_to_file (enum gcc_jit_output_kind output_kind,
284 const char *output_path);
285
286 void
287 add_error (location *loc, const char *fmt, ...)
288 GNU_PRINTF(3, 4);
289
290 void
291 add_error_va (location *loc, const char *fmt, va_list ap)
292 GNU_PRINTF(3, 0);
293
294 const char *
295 get_first_error () const;
296
297 const char *
298 get_last_error () const;
299
300 bool errors_occurred () const
301 {
302 if (m_parent_ctxt)
303 if (m_parent_ctxt->errors_occurred ())
304 return true;
305 return m_error_count;
306 }
307
308 type *get_opaque_FILE_type ();
309
310 void dump_to_file (const char *path, bool update_locations);
311
312 void dump_reproducer_to_file (const char *path);
313
314 void
315 get_all_requested_dumps (vec <recording::requested_dump> *out);
316
317 void set_timer (timer *t) { m_timer = t; }
318 timer *get_timer () const { return m_timer; }
319
320 void add_top_level_asm (location *loc, const char *asm_stmts);
321
322 private:
323 void log_all_options () const;
324 void log_str_option (enum gcc_jit_str_option opt) const;
325 void log_int_option (enum gcc_jit_int_option opt) const;
326 void log_bool_option (enum gcc_jit_bool_option opt) const;
327 void log_inner_bool_option (enum inner_bool_option opt) const;
328
329 void validate ();
330
331 private:
332 context *m_parent_ctxt;
333
334 /* The ultimate ancestor of the contexts within a family tree of
335 contexts. This has itself as its own m_toplevel_ctxt. */
336 context *m_toplevel_ctxt;
337
338 timer *m_timer;
339
340 int m_error_count;
341
342 char *m_first_error_str;
343 bool m_owns_first_error_str;
344
345 char *m_last_error_str;
346 bool m_owns_last_error_str;
347
348 char *m_str_options[GCC_JIT_NUM_STR_OPTIONS];
349 int m_int_options[GCC_JIT_NUM_INT_OPTIONS];
350 bool m_bool_options[GCC_JIT_NUM_BOOL_OPTIONS];
351 bool m_inner_bool_options[NUM_INNER_BOOL_OPTIONS];
352 auto_vec <char *> m_command_line_options;
353 auto_vec <char *> m_driver_options;
354
355 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
356 auto_vec<requested_dump> m_requested_dumps;
357
358 /* Recorded API usage. */
359 auto_vec<memento *> m_mementos;
360
361 /* Specific recordings, for use by dump_to_file. */
362 auto_vec<compound_type *> m_compound_types;
363 auto_vec<global *> m_globals;
364 auto_vec<function *> m_functions;
365 auto_vec<top_level_asm *> m_top_level_asms;
366
367 type *m_basic_types[NUM_GCC_JIT_TYPES];
368 type *m_FILE_type;
369
370 builtins_manager *m_builtins_manager; // lazily created
371 };
372
373
374 /* An object with lifetime managed by the context i.e.
375 it lives until the context is released, at which
376 point it itself is cleaned up. */
377
378 class memento
379 {
380 public:
381 virtual ~memento () {}
382
383 /* Hook for replaying this. */
384 virtual void replay_into (replayer *r) = 0;
385
386 void set_playback_obj (void *obj) { m_playback_obj = obj; }
387
388
389 /* Get the context that owns this object.
390
391 Implements the post-error-checking part of
392 gcc_jit_object_get_context. */
393 context *get_context () { return m_ctxt; }
394
395 memento *
396 as_object () { return this; }
397
398 /* Debugging hook, for use in generating error messages etc.
399 Implements the post-error-checking part of
400 gcc_jit_object_get_debug_string. */
401 const char *
402 get_debug_string ();
403
404 virtual void write_to_dump (dump &d);
405 virtual void write_reproducer (reproducer &r) = 0;
406 virtual location *dyn_cast_location () { return NULL; }
407
408 memento (const memento&) = delete;
409 memento& operator= (const memento&) = delete;
410
411 protected:
412 memento (context *ctxt)
413 : m_ctxt (ctxt),
414 m_playback_obj (NULL),
415 m_debug_string (NULL)
416 {
417 gcc_assert (ctxt);
418 }
419
420 string *new_string (const char *text) { return m_ctxt->new_string (text); }
421
422 private:
423 virtual string * make_debug_string () = 0;
424
425 public:
426 context *m_ctxt;
427
428 protected:
429 void *m_playback_obj;
430
431 private:
432 string *m_debug_string;
433 };
434
435 /* or just use std::string? */
436 class string : public memento
437 {
438 public:
439 string (context *ctxt, const char *text, bool escaped);
440 ~string ();
441
442 const char *c_str () const { return m_buffer; }
443
444 static string * from_printf (context *ctxt, const char *fmt, ...)
445 GNU_PRINTF(2, 3);
446
447 void replay_into (replayer *) final override {}
448
449 string (const string&) = delete;
450 string& operator= (const string&) = delete;
451
452 private:
453 string * make_debug_string () final override;
454 void write_reproducer (reproducer &r) final override;
455
456 private:
457 size_t m_len;
458 char *m_buffer;
459
460 /* Flag to track if this string is the result of string::make_debug_string,
461 to avoid infinite recursion when logging all mementos: don't re-escape
462 such strings. */
463 bool m_escaped;
464 };
465
466 class location : public memento
467 {
468 public:
469 location (context *ctxt, string *filename, int line, int column,
470 bool created_by_user)
471 : memento (ctxt),
472 m_filename (filename),
473 m_line (line),
474 m_column (column),
475 m_created_by_user (created_by_user)
476 {}
477
478 void replay_into (replayer *r) final override;
479
480 playback::location *
481 playback_location (replayer *r)
482 {
483 /* Normally during playback, we can walk forwards through the list of
484 recording objects, playing them back. The ordering of recording
485 ensures that everything that a recording object refers to has
486 already been played back, so we can simply look up the relevant
487 m_playback_obj.
488
489 Locations are an exception, due to the "write_to_dump" method of
490 recording::statement. This method can set a new location on a
491 statement after the statement is created, and thus the location
492 appears in the context's memento list *after* the statement that
493 refers to it.
494
495 In such circumstances, the statement is replayed *before* the location,
496 when the latter doesn't yet have a playback object.
497
498 Hence we need to ensure that locations have playback objects. */
499 if (!m_playback_obj)
500 {
501 replay_into (r);
502 }
503 gcc_assert (m_playback_obj);
504 return static_cast <playback::location *> (m_playback_obj);
505 }
506
507 location *dyn_cast_location () final override { return this; }
508 bool created_by_user () const { return m_created_by_user; }
509
510 private:
511 string * make_debug_string () final override;
512 void write_reproducer (reproducer &r) final override;
513
514 private:
515 string *m_filename;
516 int m_line;
517 int m_column;
518 bool m_created_by_user;
519 };
520
521 class type : public memento
522 {
523 public:
524 type *get_pointer ();
525 type *get_const ();
526 type *get_volatile ();
527 type *get_aligned (size_t alignment_in_bytes);
528 type *get_vector (size_t num_units);
529
530 /* Get the type obtained when dereferencing this type.
531
532 This will return NULL if it's not valid to dereference this type.
533 The caller is responsible for setting an error. */
534 virtual type *dereference () = 0;
535 /* Get the type size in bytes.
536
537 This is implemented only for memento_of_get_type and
538 memento_of_get_pointer as it is used for initializing globals of
539 these types. */
540 virtual size_t get_size () { gcc_unreachable (); }
541
542 /* Dynamic casts. */
543 virtual function_type *dyn_cast_function_type () { return NULL; }
544 virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; }
545 virtual struct_ *dyn_cast_struct () { return NULL; }
546 virtual vector_type *dyn_cast_vector_type () { return NULL; }
547
548 /* Is it typesafe to copy to this type from rtype? */
549 virtual bool accepts_writes_from (type *rtype)
550 {
551 gcc_assert (rtype);
552 return this->unqualified ()->is_same_type_as (rtype->unqualified ());
553 }
554
555 virtual bool is_same_type_as (type *other)
556 {
557 return this == other;
558 }
559
560 /* Strip off "const" etc */
561 virtual type *unqualified ()
562 {
563 return this;
564 }
565
566 virtual bool is_int () const = 0;
567 virtual bool is_float () const = 0;
568 virtual bool is_bool () const = 0;
569 virtual type *is_pointer () = 0;
570 virtual type *is_volatile () { return NULL; }
571 virtual type *is_const () { return NULL; }
572 virtual type *is_array () = 0;
573 virtual struct_ *is_struct () { return NULL; }
574 virtual bool is_union () const { return false; }
575 virtual bool is_void () const { return false; }
576 virtual vector_type *is_vector () { return NULL; }
577 virtual bool has_known_size () const { return true; }
578 virtual bool is_signed () const = 0;
579
580 bool is_numeric () const
581 {
582 return is_int () || is_float () || is_bool ();
583 }
584
585 playback::type *
586 playback_type ()
587 {
588 return static_cast <playback::type *> (m_playback_obj);
589 }
590
591 virtual const char *access_as_type (reproducer &r);
592
593 protected:
594 type (context *ctxt)
595 : memento (ctxt),
596 m_pointer_to_this_type (NULL)
597 {}
598
599 private:
600 type *m_pointer_to_this_type;
601 };
602
603 /* Result of "gcc_jit_context_get_type". */
604 class memento_of_get_type : public type
605 {
606 public:
607 memento_of_get_type (context *ctxt,
608 enum gcc_jit_types kind)
609 : type (ctxt),
610 m_kind (kind) {}
611
612 type *dereference () final override;
613
614 size_t get_size () final override;
615
616 bool accepts_writes_from (type *rtype) final override
617 {
618 if (m_kind == GCC_JIT_TYPE_VOID_PTR)
619 {
620 if (rtype->is_pointer ())
621 {
622 /* LHS (this) is type (void *), and the RHS is a pointer:
623 accept it: */
624 return true;
625 }
626 } else if (is_int ()
627 && rtype->is_int ()
628 && get_size () == rtype->get_size ()
629 && is_signed () == rtype->is_signed ())
630 {
631 /* LHS (this) is an integer of the same size and sign as rtype. */
632 return true;
633 }
634
635 return type::accepts_writes_from (rtype);
636 }
637
638 bool is_int () const final override;
639 bool is_float () const final override;
640 bool is_bool () const final override;
641 type *is_pointer () final override { return dereference (); }
642 type *is_array () final override { return NULL; }
643 bool is_void () const final override { return m_kind == GCC_JIT_TYPE_VOID; }
644 bool is_signed () const final override;
645
646 public:
647 void replay_into (replayer *r) final override;
648
649 private:
650 string * make_debug_string () final override;
651 void write_reproducer (reproducer &r) final override;
652
653 private:
654 enum gcc_jit_types m_kind;
655 };
656
657 /* Result of "gcc_jit_type_get_pointer". */
658 class memento_of_get_pointer : public type
659 {
660 public:
661 memento_of_get_pointer (type *other_type)
662 : type (other_type->m_ctxt),
663 m_other_type (other_type) {}
664
665 type *dereference () final override { return m_other_type; }
666
667 size_t get_size () final override;
668
669 bool accepts_writes_from (type *rtype) final override;
670
671 void replay_into (replayer *r) final override;
672
673 bool is_int () const final override { return false; }
674 bool is_float () const final override { return false; }
675 bool is_bool () const final override { return false; }
676 type *is_pointer () final override { return m_other_type; }
677 type *is_array () final override { return NULL; }
678 bool is_signed () const final override { return false; }
679
680 private:
681 string * make_debug_string () final override;
682 void write_reproducer (reproducer &r) final override;
683
684 private:
685 type *m_other_type;
686 };
687
688 /* A decorated version of a type, for get_const, get_volatile,
689 get_aligned, and get_vector. */
690
691 class decorated_type : public type
692 {
693 public:
694 decorated_type (type *other_type)
695 : type (other_type->m_ctxt),
696 m_other_type (other_type) {}
697
698 type *dereference () final override { return m_other_type->dereference (); }
699
700 size_t get_size () final override { return m_other_type->get_size (); };
701
702 bool is_int () const final override { return m_other_type->is_int (); }
703 bool is_float () const final override { return m_other_type->is_float (); }
704 bool is_bool () const final override { return m_other_type->is_bool (); }
705 type *is_pointer () final override { return m_other_type->is_pointer (); }
706 type *is_array () final override { return m_other_type->is_array (); }
707 struct_ *is_struct () final override { return m_other_type->is_struct (); }
708 bool is_signed () const final override { return m_other_type->is_signed (); }
709
710 protected:
711 type *m_other_type;
712 };
713
714 /* Result of "gcc_jit_type_get_const". */
715 class memento_of_get_const : public decorated_type
716 {
717 public:
718 memento_of_get_const (type *other_type)
719 : decorated_type (other_type) {}
720
721 bool accepts_writes_from (type */*rtype*/) final override
722 {
723 /* Can't write to a "const". */
724 return false;
725 }
726
727 /* Strip off the "const", giving the underlying type. */
728 type *unqualified () final override { return m_other_type; }
729
730 bool is_same_type_as (type *other) final override
731 {
732 if (!other->is_const ())
733 return false;
734 return m_other_type->is_same_type_as (other->is_const ());
735 }
736
737 type *is_const () final override { return m_other_type; }
738
739 void replay_into (replayer *) final override;
740
741 private:
742 string * make_debug_string () final override;
743 void write_reproducer (reproducer &r) final override;
744 };
745
746 /* Result of "gcc_jit_type_get_volatile". */
747 class memento_of_get_volatile : public decorated_type
748 {
749 public:
750 memento_of_get_volatile (type *other_type)
751 : decorated_type (other_type) {}
752
753 bool is_same_type_as (type *other) final override
754 {
755 if (!other->is_volatile ())
756 return false;
757 return m_other_type->is_same_type_as (other->is_volatile ());
758 }
759
760 /* Strip off the "volatile", giving the underlying type. */
761 type *unqualified () final override { return m_other_type; }
762
763 type *is_volatile () final override { return m_other_type; }
764
765 void replay_into (replayer *) final override;
766
767 private:
768 string * make_debug_string () final override;
769 void write_reproducer (reproducer &r) final override;
770 };
771
772 /* Result of "gcc_jit_type_get_aligned". */
773 class memento_of_get_aligned : public decorated_type
774 {
775 public:
776 memento_of_get_aligned (type *other_type, size_t alignment_in_bytes)
777 : decorated_type (other_type),
778 m_alignment_in_bytes (alignment_in_bytes) {}
779
780 /* Strip off the alignment, giving the underlying type. */
781 type *unqualified () final override { return m_other_type; }
782
783 void replay_into (replayer *) final override;
784
785 private:
786 string * make_debug_string () final override;
787 void write_reproducer (reproducer &r) final override;
788
789 private:
790 size_t m_alignment_in_bytes;
791 };
792
793 /* Result of "gcc_jit_type_get_vector". */
794 class vector_type : public decorated_type
795 {
796 public:
797 vector_type (type *other_type, size_t num_units)
798 : decorated_type (other_type),
799 m_num_units (num_units) {}
800
801 size_t get_num_units () const { return m_num_units; }
802
803 vector_type *dyn_cast_vector_type () final override { return this; }
804
805 type *get_element_type () { return m_other_type; }
806
807 void replay_into (replayer *) final override;
808
809 bool is_same_type_as (type *other) final override
810 {
811 vector_type *other_vec_type = other->dyn_cast_vector_type ();
812 if (other_vec_type == NULL)
813 return false;
814 return get_num_units () == other_vec_type->get_num_units ()
815 && get_element_type () == other_vec_type->get_element_type ();
816 }
817
818 vector_type *is_vector () final override { return this; }
819
820 private:
821 string * make_debug_string () final override;
822 void write_reproducer (reproducer &r) final override;
823
824 private:
825 size_t m_num_units;
826 };
827
828 class array_type : public type
829 {
830 public:
831 array_type (context *ctxt,
832 location *loc,
833 type *element_type,
834 int num_elements)
835 : type (ctxt),
836 m_loc (loc),
837 m_element_type (element_type),
838 m_num_elements (num_elements)
839 {}
840
841 type *dereference () final override;
842
843 bool is_int () const final override { return false; }
844 bool is_float () const final override { return false; }
845 bool is_bool () const final override { return false; }
846 type *is_pointer () final override { return NULL; }
847 type *is_array () final override { return m_element_type; }
848 int num_elements () { return m_num_elements; }
849 bool is_signed () const final override { return false; }
850
851 void replay_into (replayer *) final override;
852
853 private:
854 string * make_debug_string () final override;
855 void write_reproducer (reproducer &r) final override;
856
857 private:
858 location *m_loc;
859 type *m_element_type;
860 int m_num_elements;
861 };
862
863 class function_type : public type
864 {
865 public:
866 function_type (context *ctxt,
867 type *return_type,
868 int num_params,
869 type **param_types,
870 int is_variadic);
871
872 type *dereference () final override;
873 function_type *dyn_cast_function_type () final override { return this; }
874 function_type *as_a_function_type () final override { return this; }
875
876 bool is_same_type_as (type *other) final override;
877
878 bool is_int () const final override { return false; }
879 bool is_float () const final override { return false; }
880 bool is_bool () const final override { return false; }
881 type *is_pointer () final override { return NULL; }
882 type *is_array () final override { return NULL; }
883 bool is_signed () const final override { return false; }
884
885 void replay_into (replayer *) final override;
886
887 type * get_return_type () const { return m_return_type; }
888 const vec<type *> &get_param_types () const { return m_param_types; }
889 int is_variadic () const { return m_is_variadic; }
890
891 string * make_debug_string_with_ptr ();
892
893 void
894 write_deferred_reproducer (reproducer &r,
895 memento *ptr_type);
896
897 private:
898 string * make_debug_string () final override;
899 string * make_debug_string_with (const char *);
900 void write_reproducer (reproducer &r) final override;
901
902 private:
903 type *m_return_type;
904 auto_vec<type *> m_param_types;
905 int m_is_variadic;
906 };
907
908 class field : public memento
909 {
910 public:
911 field (context *ctxt,
912 location *loc,
913 type *type,
914 string *name)
915 : memento (ctxt),
916 m_loc (loc),
917 m_type (type),
918 m_name (name),
919 m_container (NULL)
920 {}
921
922 type * get_type () const { return m_type; }
923
924 compound_type * get_container () const { return m_container; }
925 void set_container (compound_type *c) { m_container = c; }
926
927 void replay_into (replayer *) override;
928
929 void write_to_dump (dump &d) override;
930
931 playback::field *
932 playback_field () const
933 {
934 return static_cast <playback::field *> (m_playback_obj);
935 }
936
937 private:
938 string * make_debug_string () override;
939 void write_reproducer (reproducer &r) override;
940
941 protected:
942 location *m_loc;
943 type *m_type;
944 string *m_name;
945 compound_type *m_container;
946 };
947
948
949 class bitfield : public field
950 {
951 public:
952 bitfield (context *ctxt,
953 location *loc,
954 type *type,
955 int width,
956 string *name)
957 : field (ctxt, loc, type, name),
958 m_width (width)
959 {}
960
961 void replay_into (replayer *) final override;
962
963 void write_to_dump (dump &d) final override;
964
965 private:
966 string * make_debug_string () final override;
967 void write_reproducer (reproducer &r) final override;
968
969 private:
970 int m_width;
971 };
972
973 /* Base class for struct_ and union_ */
974 class compound_type : public type
975 {
976 public:
977 compound_type (context *ctxt,
978 location *loc,
979 string *name);
980
981 string *get_name () const { return m_name; }
982 location *get_loc () const { return m_loc; }
983 fields * get_fields () { return m_fields; }
984
985 void
986 set_fields (location *loc,
987 int num_fields,
988 field **fields);
989
990 type *dereference () final override;
991
992 bool is_int () const final override { return false; }
993 bool is_float () const final override { return false; }
994 bool is_bool () const final override { return false; }
995 type *is_pointer () final override { return NULL; }
996 type *is_array () final override { return NULL; }
997 bool is_signed () const final override { return false; }
998
999 bool has_known_size () const final override { return m_fields != NULL; }
1000
1001 playback::compound_type *
1002 playback_compound_type ()
1003 {
1004 return static_cast <playback::compound_type *> (m_playback_obj);
1005 }
1006
1007 private:
1008 location *m_loc;
1009 string *m_name;
1010 fields *m_fields;
1011 };
1012
1013 class struct_ : public compound_type
1014 {
1015 public:
1016 struct_ (context *ctxt,
1017 location *loc,
1018 string *name);
1019
1020 struct_ *dyn_cast_struct () final override { return this; }
1021
1022 type *
1023 as_type () { return this; }
1024
1025 void replay_into (replayer *r) final override;
1026
1027 const char *access_as_type (reproducer &r) final override;
1028
1029 struct_ *is_struct () final override { return this; }
1030
1031 private:
1032 string * make_debug_string () final override;
1033 void write_reproducer (reproducer &r) final override;
1034 };
1035
1036 // memento of struct_::set_fields
1037 class fields : public memento
1038 {
1039 public:
1040 fields (compound_type *struct_or_union,
1041 int num_fields,
1042 field **fields);
1043
1044 void replay_into (replayer *r) final override;
1045
1046 void write_to_dump (dump &d) final override;
1047
1048 int length () const { return m_fields.length (); }
1049 field *get_field (int i) const { return m_fields[i]; }
1050
1051 private:
1052 string * make_debug_string () final override;
1053 void write_reproducer (reproducer &r) final override;
1054
1055 private:
1056 compound_type *m_struct_or_union;
1057 auto_vec<field *> m_fields;
1058 };
1059
1060 class union_ : public compound_type
1061 {
1062 public:
1063 union_ (context *ctxt,
1064 location *loc,
1065 string *name);
1066
1067 void replay_into (replayer *r) final override;
1068
1069 bool is_union () const final override { return true; }
1070
1071 private:
1072 string * make_debug_string () final override;
1073 void write_reproducer (reproducer &r) final override;
1074 };
1075
1076 /* An abstract base class for operations that visit all rvalues within an
1077 expression tree.
1078 Currently the only implementation is class rvalue_usage_validator within
1079 jit-recording.cc. */
1080
1081 class rvalue_visitor
1082 {
1083 public:
1084 virtual ~rvalue_visitor () {}
1085 virtual void visit (rvalue *rvalue) = 0;
1086 };
1087
1088 /* When generating debug strings for rvalues we mimic C, so we need to
1089 mimic C's precedence levels when handling compound expressions.
1090 These are in order from strongest precedence to weakest. */
1091 enum precedence
1092 {
1093 PRECEDENCE_PRIMARY,
1094 PRECEDENCE_POSTFIX,
1095 PRECEDENCE_UNARY,
1096 PRECEDENCE_CAST,
1097 PRECEDENCE_MULTIPLICATIVE,
1098 PRECEDENCE_ADDITIVE,
1099 PRECEDENCE_SHIFT,
1100 PRECEDENCE_RELATIONAL,
1101 PRECEDENCE_EQUALITY,
1102 PRECEDENCE_BITWISE_AND,
1103 PRECEDENCE_BITWISE_XOR,
1104 PRECEDENCE_BITWISE_IOR,
1105 PRECEDENCE_LOGICAL_AND,
1106 PRECEDENCE_LOGICAL_OR
1107 };
1108
1109 class rvalue : public memento
1110 {
1111 public:
1112 rvalue (context *ctxt,
1113 location *loc,
1114 type *type_)
1115 : memento (ctxt),
1116 m_loc (loc),
1117 m_type (type_),
1118 m_scope (NULL),
1119 m_parenthesized_string (NULL)
1120 {
1121 gcc_assert (type_);
1122 }
1123
1124 location * get_loc () const { return m_loc; }
1125
1126 /* Get the recording::type of this rvalue.
1127
1128 Implements the post-error-checking part of
1129 gcc_jit_rvalue_get_type. */
1130 type * get_type () const { return m_type; }
1131
1132 playback::rvalue *
1133 playback_rvalue () const
1134 {
1135 return static_cast <playback::rvalue *> (m_playback_obj);
1136 }
1137 rvalue *
1138 access_field (location *loc,
1139 field *field);
1140
1141 lvalue *
1142 dereference_field (location *loc,
1143 field *field);
1144
1145 lvalue *
1146 dereference (location *loc);
1147
1148 void
1149 verify_valid_within_stmt (const char *api_funcname, statement *s);
1150
1151 virtual void visit_children (rvalue_visitor *v) = 0;
1152
1153 void set_scope (function *scope);
1154 function *get_scope () const { return m_scope; }
1155
1156 /* Dynamic casts. */
1157 virtual param *dyn_cast_param () { return NULL; }
1158 virtual base_call *dyn_cast_base_call () { return NULL; }
1159
1160 virtual const char *access_as_rvalue (reproducer &r);
1161
1162 /* Get the debug string, wrapped in parentheses. */
1163 const char *
1164 get_debug_string_parens (enum precedence outer_prec);
1165
1166 virtual bool is_constant () const { return false; }
1167 virtual bool get_wide_int (wide_int *) const { return false; }
1168
1169 private:
1170 virtual enum precedence get_precedence () const = 0;
1171
1172 protected:
1173 location *m_loc;
1174 type *m_type;
1175
1176 private:
1177 function *m_scope; /* NULL for globals, non-NULL for locals/params */
1178 string *m_parenthesized_string;
1179 };
1180
1181 class lvalue : public rvalue
1182 {
1183 public:
1184 lvalue (context *ctxt,
1185 location *loc,
1186 type *type_)
1187 : rvalue (ctxt, loc, type_),
1188 m_link_section (NULL),
1189 m_reg_name (NULL),
1190 m_tls_model (GCC_JIT_TLS_MODEL_NONE),
1191 m_alignment (0)
1192 {}
1193
1194 playback::lvalue *
1195 playback_lvalue () const
1196 {
1197 return static_cast <playback::lvalue *> (m_playback_obj);
1198 }
1199
1200 lvalue *
1201 access_field (location *loc,
1202 field *field);
1203
1204 rvalue *
1205 get_address (location *loc);
1206
1207 rvalue *
1208 as_rvalue () { return this; }
1209
1210 const char *access_as_rvalue (reproducer &r) override;
1211 virtual const char *access_as_lvalue (reproducer &r);
1212 virtual bool is_global () const { return false; }
1213 void set_tls_model (enum gcc_jit_tls_model model);
1214 void set_link_section (const char *name);
1215 void set_register_name (const char *reg_name);
1216 void set_alignment (unsigned bytes);
1217 unsigned get_alignment () const { return m_alignment; }
1218
1219 protected:
1220 string *m_link_section;
1221 string *m_reg_name;
1222 enum gcc_jit_tls_model m_tls_model;
1223 unsigned m_alignment;
1224 };
1225
1226 class param : public lvalue
1227 {
1228 public:
1229 param (context *ctxt,
1230 location *loc,
1231 type *type,
1232 string *name)
1233 : lvalue (ctxt, loc, type),
1234 m_name (name) {}
1235
1236 lvalue *
1237 as_lvalue () { return this; }
1238
1239 void replay_into (replayer *r) final override;
1240
1241 void visit_children (rvalue_visitor *) final override {}
1242
1243 playback::param *
1244 playback_param () const
1245 {
1246 return static_cast <playback::param *> (m_playback_obj);
1247 }
1248
1249 param *dyn_cast_param () final override { return this; }
1250
1251 const char *access_as_rvalue (reproducer &r) final override;
1252 const char *access_as_lvalue (reproducer &r) final override;
1253
1254 private:
1255 string * make_debug_string () final override { return m_name; }
1256 void write_reproducer (reproducer &r) final override;
1257 enum precedence get_precedence () const final override
1258 {
1259 return PRECEDENCE_PRIMARY;
1260 }
1261
1262 private:
1263 string *m_name;
1264 };
1265
1266 class function : public memento
1267 {
1268 public:
1269 function (context *ctxt,
1270 location *loc,
1271 enum gcc_jit_function_kind kind,
1272 type *return_type,
1273 string *name,
1274 int num_params,
1275 param **params,
1276 int is_variadic,
1277 enum built_in_function builtin_id);
1278
1279 void replay_into (replayer *r) final override;
1280
1281 playback::function *
1282 playback_function () const
1283 {
1284 return static_cast <playback::function *> (m_playback_obj);
1285 }
1286
1287 enum gcc_jit_function_kind get_kind () const { return m_kind; }
1288
1289 lvalue *
1290 new_local (location *loc,
1291 type *type,
1292 const char *name);
1293
1294 block*
1295 new_block (const char *name);
1296
1297 location *get_loc () const { return m_loc; }
1298 type *get_return_type () const { return m_return_type; }
1299 string * get_name () const { return m_name; }
1300 const vec<param *> &get_params () const { return m_params; }
1301
1302 /* Get the given param by index.
1303 Implements the post-error-checking part of
1304 gcc_jit_function_get_param. */
1305 param *get_param (int i) const { return m_params[i]; }
1306
1307 bool is_variadic () const { return m_is_variadic; }
1308
1309 void write_to_dump (dump &d) final override;
1310
1311 void validate ();
1312
1313 void dump_to_dot (const char *path);
1314
1315 rvalue *get_address (location *loc);
1316
1317 private:
1318 string * make_debug_string () final override;
1319 void write_reproducer (reproducer &r) final override;
1320
1321 private:
1322 location *m_loc;
1323 enum gcc_jit_function_kind m_kind;
1324 type *m_return_type;
1325 string *m_name;
1326 auto_vec<param *> m_params;
1327 int m_is_variadic;
1328 enum built_in_function m_builtin_id;
1329 auto_vec<local *> m_locals;
1330 auto_vec<block *> m_blocks;
1331 type *m_fn_ptr_type;
1332 };
1333
1334 class block : public memento
1335 {
1336 public:
1337 block (function *func, int index, string *name)
1338 : memento (func->m_ctxt),
1339 m_func (func),
1340 m_index (index),
1341 m_name (name),
1342 m_statements (),
1343 m_has_been_terminated (false),
1344 m_is_reachable (false)
1345 {
1346 }
1347
1348 /* Get the recording::function containing this block.
1349 Implements the post-error-checking part of
1350 gcc_jit_block_get_function. */
1351 function *get_function () { return m_func; }
1352
1353 bool has_been_terminated () { return m_has_been_terminated; }
1354 bool is_reachable () { return m_is_reachable; }
1355
1356 statement *
1357 add_eval (location *loc,
1358 rvalue *rvalue);
1359
1360 statement *
1361 add_assignment (location *loc,
1362 lvalue *lvalue,
1363 rvalue *rvalue);
1364
1365 statement *
1366 add_assignment_op (location *loc,
1367 lvalue *lvalue,
1368 enum gcc_jit_binary_op op,
1369 rvalue *rvalue);
1370
1371 statement *
1372 add_comment (location *loc,
1373 const char *text);
1374
1375 extended_asm *
1376 add_extended_asm (location *loc,
1377 const char *asm_template);
1378
1379 statement *
1380 end_with_conditional (location *loc,
1381 rvalue *boolval,
1382 block *on_true,
1383 block *on_false);
1384
1385 statement *
1386 end_with_jump (location *loc,
1387 block *target);
1388
1389 statement *
1390 end_with_return (location *loc,
1391 rvalue *rvalue);
1392
1393 statement *
1394 end_with_switch (location *loc,
1395 rvalue *expr,
1396 block *default_block,
1397 int num_cases,
1398 case_ **cases);
1399
1400 extended_asm *
1401 end_with_extended_asm_goto (location *loc,
1402 const char *asm_template,
1403 int num_goto_blocks,
1404 block **goto_blocks,
1405 block *fallthrough_block);
1406
1407 playback::block *
1408 playback_block () const
1409 {
1410 return static_cast <playback::block *> (m_playback_obj);
1411 }
1412
1413 void write_to_dump (dump &d) final override;
1414
1415 bool validate ();
1416
1417 location *get_loc () const;
1418
1419 statement *get_first_statement () const;
1420 statement *get_last_statement () const;
1421
1422 vec <block *> get_successor_blocks () const;
1423
1424 private:
1425 string * make_debug_string () final override;
1426 void write_reproducer (reproducer &r) final override;
1427
1428 void replay_into (replayer *r) final override;
1429
1430 void dump_to_dot (pretty_printer *pp);
1431 void dump_edges_to_dot (pretty_printer *pp);
1432
1433 private:
1434 function *m_func;
1435 int m_index;
1436 string *m_name;
1437 auto_vec<statement *> m_statements;
1438 bool m_has_been_terminated;
1439 bool m_is_reachable;
1440
1441 friend class function;
1442 };
1443
1444 class global : public lvalue
1445 {
1446 public:
1447 global (context *ctxt,
1448 location *loc,
1449 enum gcc_jit_global_kind kind,
1450 type *type,
1451 string *name)
1452 : lvalue (ctxt, loc, type),
1453 m_kind (kind),
1454 m_name (name)
1455 {
1456 m_initializer = NULL;
1457 m_initializer_num_bytes = 0;
1458 }
1459 ~global ()
1460 {
1461 free (m_initializer);
1462 }
1463
1464 void replay_into (replayer *) final override;
1465
1466 void visit_children (rvalue_visitor *) final override {}
1467
1468 void write_to_dump (dump &d) final override;
1469
1470 bool is_global () const final override { return true; }
1471
1472 void
1473 set_initializer (const void *initializer,
1474 size_t num_bytes)
1475 {
1476 if (m_initializer)
1477 free (m_initializer);
1478 m_initializer = xmalloc (num_bytes);
1479 memcpy (m_initializer, initializer, num_bytes);
1480 m_initializer_num_bytes = num_bytes;
1481 }
1482
1483 void set_flags (int flag_fields)
1484 {
1485 m_flags = (enum global_var_flags)(m_flags | flag_fields);
1486 }
1487 /* Returns true if any of the flags in the argument is set. */
1488 bool test_flags_anyof (int flag_fields) const
1489 {
1490 return m_flags & flag_fields;
1491 }
1492
1493 enum gcc_jit_global_kind get_kind () const
1494 {
1495 return m_kind;
1496 }
1497
1498 void set_rvalue_init (rvalue *val) { m_rvalue_init = val; }
1499
1500 private:
1501 string * make_debug_string () final override { return m_name; }
1502 template <typename T>
1503 void write_initializer_reproducer (const char *id, reproducer &r);
1504 void write_reproducer (reproducer &r) final override;
1505 enum precedence get_precedence () const final override
1506 {
1507 return PRECEDENCE_PRIMARY;
1508 }
1509
1510 private:
1511 enum gcc_jit_global_kind m_kind;
1512 enum global_var_flags m_flags = GLOBAL_VAR_FLAGS_NONE;
1513 string *m_name;
1514 void *m_initializer;
1515 rvalue *m_rvalue_init = nullptr; /* Only needed for write_dump. */
1516 size_t m_initializer_num_bytes;
1517 };
1518
1519 template <typename HOST_TYPE>
1520 class memento_of_new_rvalue_from_const : public rvalue
1521 {
1522 public:
1523 memento_of_new_rvalue_from_const (context *ctxt,
1524 location *loc,
1525 type *type,
1526 HOST_TYPE value)
1527 : rvalue (ctxt, loc, type),
1528 m_value (value) {}
1529
1530 void replay_into (replayer *r) final override;
1531
1532 void visit_children (rvalue_visitor *) final override {}
1533
1534 bool is_constant () const final override { return true; }
1535
1536 bool get_wide_int (wide_int *out) const final override;
1537
1538 private:
1539 string * make_debug_string () final override;
1540 void write_reproducer (reproducer &r) final override;
1541 enum precedence get_precedence () const final override
1542 {
1543 return PRECEDENCE_PRIMARY;
1544 }
1545
1546 private:
1547 HOST_TYPE m_value;
1548 };
1549
1550 class memento_of_new_string_literal : public rvalue
1551 {
1552 public:
1553 memento_of_new_string_literal (context *ctxt,
1554 location *loc,
1555 string *value)
1556 : rvalue (ctxt, loc, ctxt->get_type (GCC_JIT_TYPE_CONST_CHAR_PTR)),
1557 m_value (value) {}
1558
1559 void replay_into (replayer *r) final override;
1560
1561 void visit_children (rvalue_visitor *) final override {}
1562
1563 private:
1564 string * make_debug_string () final override;
1565 void write_reproducer (reproducer &r) final override;
1566 enum precedence get_precedence () const final override
1567 {
1568 return PRECEDENCE_PRIMARY;
1569 }
1570
1571 private:
1572 string *m_value;
1573 };
1574
1575 class memento_of_new_rvalue_from_vector : public rvalue
1576 {
1577 public:
1578 memento_of_new_rvalue_from_vector (context *ctxt,
1579 location *loc,
1580 vector_type *type,
1581 rvalue **elements);
1582
1583 void replay_into (replayer *r) final override;
1584
1585 void visit_children (rvalue_visitor *) final override;
1586
1587 private:
1588 string * make_debug_string () final override;
1589 void write_reproducer (reproducer &r) final override;
1590 enum precedence get_precedence () const final override
1591 {
1592 return PRECEDENCE_PRIMARY;
1593 }
1594
1595 private:
1596 vector_type *m_vector_type;
1597 auto_vec<rvalue *> m_elements;
1598 };
1599
1600 class ctor : public rvalue
1601 {
1602 public:
1603 ctor (context *ctxt,
1604 location *loc,
1605 type *type)
1606 : rvalue (ctxt, loc, type)
1607 { }
1608
1609 void replay_into (replayer *r) final override;
1610
1611 void visit_children (rvalue_visitor *) final override;
1612
1613 private:
1614 string * make_debug_string () final override;
1615 void write_reproducer (reproducer &r) final override;
1616 enum precedence get_precedence () const final override
1617 {
1618 return PRECEDENCE_PRIMARY;
1619 }
1620
1621 public:
1622 auto_vec<field *> m_fields;
1623 auto_vec<rvalue *> m_values;
1624 };
1625
1626 class unary_op : public rvalue
1627 {
1628 public:
1629 unary_op (context *ctxt,
1630 location *loc,
1631 enum gcc_jit_unary_op op,
1632 type *result_type,
1633 rvalue *a)
1634 : rvalue (ctxt, loc, result_type),
1635 m_op (op),
1636 m_a (a)
1637 {}
1638
1639 void replay_into (replayer *r) final override;
1640
1641 void visit_children (rvalue_visitor *v) final override;
1642
1643 private:
1644 string * make_debug_string () final override;
1645 void write_reproducer (reproducer &r) final override;
1646 enum precedence get_precedence () const final override
1647 {
1648 return PRECEDENCE_UNARY;
1649 }
1650
1651 private:
1652 enum gcc_jit_unary_op m_op;
1653 rvalue *m_a;
1654 };
1655
1656 class binary_op : public rvalue
1657 {
1658 public:
1659 binary_op (context *ctxt,
1660 location *loc,
1661 enum gcc_jit_binary_op op,
1662 type *result_type,
1663 rvalue *a, rvalue *b)
1664 : rvalue (ctxt, loc, result_type),
1665 m_op (op),
1666 m_a (a),
1667 m_b (b) {}
1668
1669 void replay_into (replayer *r) final override;
1670
1671 void visit_children (rvalue_visitor *v) final override;
1672
1673 private:
1674 string * make_debug_string () final override;
1675 void write_reproducer (reproducer &r) final override;
1676 enum precedence get_precedence () const final override;
1677
1678 private:
1679 enum gcc_jit_binary_op m_op;
1680 rvalue *m_a;
1681 rvalue *m_b;
1682 };
1683
1684 class comparison : public rvalue
1685 {
1686 public:
1687 comparison (context *ctxt,
1688 location *loc,
1689 enum gcc_jit_comparison op,
1690 rvalue *a, rvalue *b)
1691 : rvalue (ctxt, loc, ctxt->get_type (GCC_JIT_TYPE_BOOL)),
1692 m_op (op),
1693 m_a (a),
1694 m_b (b)
1695 {
1696 type *a_type = a->get_type ();
1697 vector_type *vec_type = a_type->dyn_cast_vector_type ();
1698 if (vec_type != NULL)
1699 {
1700 type *element_type = vec_type->get_element_type ();
1701 type *inner_type;
1702 /* Vectors of floating-point values return a vector of integers of the
1703 same size. */
1704 if (element_type->is_float ())
1705 inner_type = ctxt->get_int_type (element_type->get_size (), false);
1706 else
1707 inner_type = element_type;
1708 m_type = new vector_type (inner_type, vec_type->get_num_units ());
1709 ctxt->record (m_type);
1710 }
1711 }
1712
1713 void replay_into (replayer *r) final override;
1714
1715 void visit_children (rvalue_visitor *v) final override;
1716
1717 private:
1718 string * make_debug_string () final override;
1719 void write_reproducer (reproducer &r) final override;
1720 enum precedence get_precedence () const final override;
1721
1722 private:
1723 enum gcc_jit_comparison m_op;
1724 rvalue *m_a;
1725 rvalue *m_b;
1726 };
1727
1728 class cast : public rvalue
1729 {
1730 public:
1731 cast (context *ctxt,
1732 location *loc,
1733 rvalue *a,
1734 type *type_)
1735 : rvalue (ctxt, loc, type_),
1736 m_rvalue (a)
1737 {}
1738
1739 void replay_into (replayer *r) final override;
1740
1741 void visit_children (rvalue_visitor *v) final override;
1742
1743 private:
1744 string * make_debug_string () final override;
1745 void write_reproducer (reproducer &r) final override;
1746 enum precedence get_precedence () const final override
1747 {
1748 return PRECEDENCE_CAST;
1749 }
1750
1751 private:
1752 rvalue *m_rvalue;
1753 };
1754
1755 class bitcast : public rvalue
1756 {
1757 public:
1758 bitcast (context *ctxt,
1759 location *loc,
1760 rvalue *a,
1761 type *type_)
1762 : rvalue (ctxt, loc, type_),
1763 m_rvalue (a)
1764 {}
1765
1766 void replay_into (replayer *r) final override;
1767
1768 void visit_children (rvalue_visitor *v) final override;
1769
1770 private:
1771 string * make_debug_string () final override;
1772 void write_reproducer (reproducer &r) final override;
1773 enum precedence get_precedence () const final override
1774 {
1775 return PRECEDENCE_CAST;
1776 }
1777
1778 private:
1779 rvalue *m_rvalue;
1780 };
1781
1782 class base_call : public rvalue
1783 {
1784 public:
1785 base_call (context *ctxt,
1786 location *loc,
1787 type *type_,
1788 int numargs,
1789 rvalue **args);
1790
1791 enum precedence get_precedence () const final override
1792 {
1793 return PRECEDENCE_POSTFIX;
1794 }
1795
1796 base_call *dyn_cast_base_call () final override { return this; }
1797
1798 void set_require_tail_call (bool require_tail_call)
1799 {
1800 m_require_tail_call = require_tail_call;
1801 }
1802
1803 protected:
1804 void write_reproducer_tail_call (reproducer &r, const char *id);
1805
1806 protected:
1807 auto_vec<rvalue *> m_args;
1808 bool m_require_tail_call;
1809 };
1810
1811 class call : public base_call
1812 {
1813 public:
1814 call (context *ctxt,
1815 location *loc,
1816 function *func,
1817 int numargs,
1818 rvalue **args);
1819
1820 void replay_into (replayer *r) final override;
1821
1822 void visit_children (rvalue_visitor *v) final override;
1823
1824 private:
1825 string * make_debug_string () final override;
1826 void write_reproducer (reproducer &r) final override;
1827
1828 private:
1829 function *m_func;
1830 };
1831
1832 class call_through_ptr : public base_call
1833 {
1834 public:
1835 call_through_ptr (context *ctxt,
1836 location *loc,
1837 rvalue *fn_ptr,
1838 int numargs,
1839 rvalue **args);
1840
1841 void replay_into (replayer *r) final override;
1842
1843 void visit_children (rvalue_visitor *v) final override;
1844
1845 private:
1846 string * make_debug_string () final override;
1847 void write_reproducer (reproducer &r) final override;
1848
1849 private:
1850 rvalue *m_fn_ptr;
1851 };
1852
1853 class array_access : public lvalue
1854 {
1855 public:
1856 array_access (context *ctxt,
1857 location *loc,
1858 rvalue *ptr,
1859 rvalue *index)
1860 : lvalue (ctxt, loc, ptr->get_type ()->dereference ()),
1861 m_ptr (ptr),
1862 m_index (index)
1863 {}
1864
1865 void replay_into (replayer *r) final override;
1866
1867 void visit_children (rvalue_visitor *v) final override;
1868
1869 private:
1870 string * make_debug_string () final override;
1871 void write_reproducer (reproducer &r) final override;
1872 enum precedence get_precedence () const final override
1873 {
1874 return PRECEDENCE_POSTFIX;
1875 }
1876
1877 private:
1878 rvalue *m_ptr;
1879 rvalue *m_index;
1880 };
1881
1882 class access_field_of_lvalue : public lvalue
1883 {
1884 public:
1885 access_field_of_lvalue (context *ctxt,
1886 location *loc,
1887 lvalue *val,
1888 field *field)
1889 : lvalue (ctxt, loc, field->get_type ()),
1890 m_lvalue (val),
1891 m_field (field)
1892 {}
1893
1894 void replay_into (replayer *r) final override;
1895
1896 void visit_children (rvalue_visitor *v) final override;
1897
1898 private:
1899 string * make_debug_string () final override;
1900 void write_reproducer (reproducer &r) final override;
1901 enum precedence get_precedence () const final override
1902 {
1903 return PRECEDENCE_POSTFIX;
1904 }
1905
1906 private:
1907 lvalue *m_lvalue;
1908 field *m_field;
1909 };
1910
1911 class access_field_rvalue : public rvalue
1912 {
1913 public:
1914 access_field_rvalue (context *ctxt,
1915 location *loc,
1916 rvalue *val,
1917 field *field)
1918 : rvalue (ctxt, loc, field->get_type ()),
1919 m_rvalue (val),
1920 m_field (field)
1921 {}
1922
1923 void replay_into (replayer *r) final override;
1924
1925 void visit_children (rvalue_visitor *v) final override;
1926
1927 private:
1928 string * make_debug_string () final override;
1929 void write_reproducer (reproducer &r) final override;
1930 enum precedence get_precedence () const final override
1931 {
1932 return PRECEDENCE_POSTFIX;
1933 }
1934
1935 private:
1936 rvalue *m_rvalue;
1937 field *m_field;
1938 };
1939
1940 class dereference_field_rvalue : public lvalue
1941 {
1942 public:
1943 dereference_field_rvalue (context *ctxt,
1944 location *loc,
1945 rvalue *val,
1946 field *field)
1947 : lvalue (ctxt, loc, field->get_type ()),
1948 m_rvalue (val),
1949 m_field (field)
1950 {}
1951
1952 void replay_into (replayer *r) final override;
1953
1954 void visit_children (rvalue_visitor *v) final override;
1955
1956 private:
1957 string * make_debug_string () final override;
1958 void write_reproducer (reproducer &r) final override;
1959 enum precedence get_precedence () const final override
1960 {
1961 return PRECEDENCE_POSTFIX;
1962 }
1963
1964 private:
1965 rvalue *m_rvalue;
1966 field *m_field;
1967 };
1968
1969 class dereference_rvalue : public lvalue
1970 {
1971 public:
1972 dereference_rvalue (context *ctxt,
1973 location *loc,
1974 rvalue *val)
1975 : lvalue (ctxt, loc, val->get_type ()->dereference ()),
1976 m_rvalue (val) {}
1977
1978 void replay_into (replayer *r) final override;
1979
1980 void visit_children (rvalue_visitor *v) final override;
1981
1982 private:
1983 string * make_debug_string () final override;
1984 void write_reproducer (reproducer &r) final override;
1985 enum precedence get_precedence () const final override
1986 {
1987 return PRECEDENCE_UNARY;
1988 }
1989
1990 private:
1991 rvalue *m_rvalue;
1992 };
1993
1994 class get_address_of_lvalue : public rvalue
1995 {
1996 public:
1997 get_address_of_lvalue (context *ctxt,
1998 location *loc,
1999 lvalue *val)
2000 : rvalue (ctxt, loc, val->get_type ()->get_pointer ()),
2001 m_lvalue (val)
2002 {}
2003
2004 void replay_into (replayer *r) final override;
2005
2006 void visit_children (rvalue_visitor *v) final override;
2007
2008 private:
2009 string * make_debug_string () final override;
2010 void write_reproducer (reproducer &r) final override;
2011 enum precedence get_precedence () const final override
2012 {
2013 return PRECEDENCE_UNARY;
2014 }
2015
2016 private:
2017 lvalue *m_lvalue;
2018 };
2019
2020 class function_pointer : public rvalue
2021 {
2022 public:
2023 function_pointer (context *ctxt,
2024 location *loc,
2025 function *fn,
2026 type *type)
2027 : rvalue (ctxt, loc, type),
2028 m_fn (fn) {}
2029
2030 void replay_into (replayer *r) final override;
2031
2032 void visit_children (rvalue_visitor *v) final override;
2033
2034 private:
2035 string * make_debug_string () final override;
2036 void write_reproducer (reproducer &r) final override;
2037 enum precedence get_precedence () const final override
2038 {
2039 return PRECEDENCE_UNARY;
2040 }
2041
2042 private:
2043 function *m_fn;
2044 };
2045
2046 class local : public lvalue
2047 {
2048 public:
2049 local (function *func, location *loc, type *type_, string *name)
2050 : lvalue (func->m_ctxt, loc, type_),
2051 m_func (func),
2052 m_name (name)
2053 {
2054 set_scope (func);
2055 }
2056
2057 void replay_into (replayer *r) final override;
2058
2059 void visit_children (rvalue_visitor *) final override {}
2060
2061 void write_to_dump (dump &d) final override;
2062
2063 private:
2064 string * make_debug_string () final override { return m_name; }
2065 void write_reproducer (reproducer &r) final override;
2066 enum precedence get_precedence () const final override
2067 {
2068 return PRECEDENCE_PRIMARY;
2069 }
2070
2071 private:
2072 function *m_func;
2073 string *m_name;
2074 };
2075
2076 class statement : public memento
2077 {
2078 public:
2079 virtual vec <block *> get_successor_blocks () const;
2080
2081 void write_to_dump (dump &d) final override;
2082
2083 block *get_block () const { return m_block; }
2084 location *get_loc () const { return m_loc; }
2085
2086 protected:
2087 statement (block *b, location *loc)
2088 : memento (b->m_ctxt),
2089 m_block (b),
2090 m_loc (loc) {}
2091
2092 playback::location *
2093 playback_location (replayer *r) const
2094 {
2095 return ::gcc::jit::recording::playback_location (r, m_loc);
2096 }
2097
2098 private:
2099 block *m_block;
2100 location *m_loc;
2101 };
2102
2103 class eval : public statement
2104 {
2105 public:
2106 eval (block *b,
2107 location *loc,
2108 rvalue *rvalue)
2109 : statement (b, loc),
2110 m_rvalue (rvalue) {}
2111
2112 void replay_into (replayer *r) final override;
2113
2114 private:
2115 string * make_debug_string () final override;
2116 void write_reproducer (reproducer &r) final override;
2117
2118 private:
2119 rvalue *m_rvalue;
2120 };
2121
2122 class assignment : public statement
2123 {
2124 public:
2125 assignment (block *b,
2126 location *loc,
2127 lvalue *lvalue,
2128 rvalue *rvalue)
2129 : statement (b, loc),
2130 m_lvalue (lvalue),
2131 m_rvalue (rvalue) {}
2132
2133 void replay_into (replayer *r) final override;
2134
2135 private:
2136 string * make_debug_string () final override;
2137 void write_reproducer (reproducer &r) final override;
2138
2139 private:
2140 lvalue *m_lvalue;
2141 rvalue *m_rvalue;
2142 };
2143
2144 class assignment_op : public statement
2145 {
2146 public:
2147 assignment_op (block *b,
2148 location *loc,
2149 lvalue *lvalue,
2150 enum gcc_jit_binary_op op,
2151 rvalue *rvalue)
2152 : statement (b, loc),
2153 m_lvalue (lvalue),
2154 m_op (op),
2155 m_rvalue (rvalue) {}
2156
2157 void replay_into (replayer *r) final override;
2158
2159 private:
2160 string * make_debug_string () final override;
2161 void write_reproducer (reproducer &r) final override;
2162
2163 private:
2164 lvalue *m_lvalue;
2165 enum gcc_jit_binary_op m_op;
2166 rvalue *m_rvalue;
2167 };
2168
2169 class comment : public statement
2170 {
2171 public:
2172 comment (block *b,
2173 location *loc,
2174 string *text)
2175 : statement (b, loc),
2176 m_text (text) {}
2177
2178 void replay_into (replayer *r) final override;
2179
2180 private:
2181 string * make_debug_string () final override;
2182 void write_reproducer (reproducer &r) final override;
2183
2184 private:
2185 string *m_text;
2186 };
2187
2188 class conditional : public statement
2189 {
2190 public:
2191 conditional (block *b,
2192 location *loc,
2193 rvalue *boolval,
2194 block *on_true,
2195 block *on_false)
2196 : statement (b, loc),
2197 m_boolval (boolval),
2198 m_on_true (on_true),
2199 m_on_false (on_false) {}
2200
2201 void replay_into (replayer *r) final override;
2202
2203 vec <block *> get_successor_blocks () const final override;
2204
2205 private:
2206 string * make_debug_string () final override;
2207 void write_reproducer (reproducer &r) final override;
2208
2209 private:
2210 rvalue *m_boolval;
2211 block *m_on_true;
2212 block *m_on_false;
2213 };
2214
2215 class jump : public statement
2216 {
2217 public:
2218 jump (block *b,
2219 location *loc,
2220 block *target)
2221 : statement (b, loc),
2222 m_target (target) {}
2223
2224 void replay_into (replayer *r) final override;
2225
2226 vec <block *> get_successor_blocks () const final override;
2227
2228 private:
2229 string * make_debug_string () final override;
2230 void write_reproducer (reproducer &r) final override;
2231
2232 private:
2233 block *m_target;
2234 };
2235
2236 class return_ : public statement
2237 {
2238 public:
2239 return_ (block *b,
2240 location *loc,
2241 rvalue *rvalue)
2242 : statement (b, loc),
2243 m_rvalue (rvalue) {}
2244
2245 void replay_into (replayer *r) final override;
2246
2247 vec <block *> get_successor_blocks () const final override;
2248
2249 private:
2250 string * make_debug_string () final override;
2251 void write_reproducer (reproducer &r) final override;
2252
2253 private:
2254 rvalue *m_rvalue;
2255 };
2256
2257 class case_ : public memento
2258 {
2259 public:
2260 case_ (context *ctxt,
2261 rvalue *min_value,
2262 rvalue *max_value,
2263 block *dest_block)
2264 : memento (ctxt),
2265 m_min_value (min_value),
2266 m_max_value (max_value),
2267 m_dest_block (dest_block)
2268 {}
2269
2270 rvalue *get_min_value () const { return m_min_value; }
2271 rvalue *get_max_value () const { return m_max_value; }
2272 block *get_dest_block () const { return m_dest_block; }
2273
2274 void replay_into (replayer *) final override { /* empty */ }
2275
2276 void write_reproducer (reproducer &r) final override;
2277
2278 private:
2279 string * make_debug_string () final override;
2280
2281 private:
2282 rvalue *m_min_value;
2283 rvalue *m_max_value;
2284 block *m_dest_block;
2285 };
2286
2287 class switch_ : public statement
2288 {
2289 public:
2290 switch_ (block *b,
2291 location *loc,
2292 rvalue *expr,
2293 block *default_block,
2294 int num_cases,
2295 case_ **cases);
2296
2297 void replay_into (replayer *r) final override;
2298
2299 vec <block *> get_successor_blocks () const final override;
2300
2301 private:
2302 string * make_debug_string () final override;
2303 void write_reproducer (reproducer &r) final override;
2304
2305 private:
2306 rvalue *m_expr;
2307 block *m_default_block;
2308 auto_vec <case_ *> m_cases;
2309 };
2310
2311 class asm_operand : public memento
2312 {
2313 public:
2314 asm_operand (extended_asm *ext_asm,
2315 string *asm_symbolic_name,
2316 string *constraint);
2317
2318 const char *get_symbolic_name () const
2319 {
2320 if (m_asm_symbolic_name)
2321 return m_asm_symbolic_name->c_str ();
2322 else
2323 return NULL;
2324 }
2325
2326 const char *get_constraint () const
2327 {
2328 return m_constraint->c_str ();
2329 }
2330
2331 virtual void print (pretty_printer *pp) const;
2332
2333 private:
2334 string * make_debug_string () final override;
2335
2336 protected:
2337 extended_asm *m_ext_asm;
2338 string *m_asm_symbolic_name;
2339 string *m_constraint;
2340 };
2341
2342 class output_asm_operand : public asm_operand
2343 {
2344 public:
2345 output_asm_operand (extended_asm *ext_asm,
2346 string *asm_symbolic_name,
2347 string *constraint,
2348 lvalue *dest)
2349 : asm_operand (ext_asm, asm_symbolic_name, constraint),
2350 m_dest (dest)
2351 {}
2352
2353 lvalue *get_lvalue () const { return m_dest; }
2354
2355 void replay_into (replayer *) final override {}
2356
2357 void print (pretty_printer *pp) const final override;
2358
2359 private:
2360 void write_reproducer (reproducer &r) final override;
2361
2362 private:
2363 lvalue *m_dest;
2364 };
2365
2366 class input_asm_operand : public asm_operand
2367 {
2368 public:
2369 input_asm_operand (extended_asm *ext_asm,
2370 string *asm_symbolic_name,
2371 string *constraint,
2372 rvalue *src)
2373 : asm_operand (ext_asm, asm_symbolic_name, constraint),
2374 m_src (src)
2375 {}
2376
2377 rvalue *get_rvalue () const { return m_src; }
2378
2379 void replay_into (replayer *) final override {}
2380
2381 void print (pretty_printer *pp) const final override;
2382
2383 private:
2384 void write_reproducer (reproducer &r) final override;
2385
2386 private:
2387 rvalue *m_src;
2388 };
2389
2390 /* Abstract base class for extended_asm statements. */
2391
2392 class extended_asm : public statement
2393 {
2394 public:
2395 extended_asm (block *b,
2396 location *loc,
2397 string *asm_template)
2398 : statement (b, loc),
2399 m_asm_template (asm_template),
2400 m_is_volatile (false),
2401 m_is_inline (false)
2402 {}
2403
2404 void set_volatile_flag (bool flag) { m_is_volatile = flag; }
2405 void set_inline_flag (bool flag) { m_is_inline = flag; }
2406
2407 void add_output_operand (const char *asm_symbolic_name,
2408 const char *constraint,
2409 lvalue *dest);
2410 void add_input_operand (const char *asm_symbolic_name,
2411 const char *constraint,
2412 rvalue *src);
2413 void add_clobber (const char *victim);
2414
2415 void replay_into (replayer *r) override;
2416
2417 string *get_asm_template () const { return m_asm_template; }
2418
2419 virtual bool is_goto () const = 0;
2420 virtual void maybe_print_gotos (pretty_printer *) const = 0;
2421
2422 protected:
2423 void write_flags (reproducer &r);
2424 void write_clobbers (reproducer &r);
2425
2426 private:
2427 string * make_debug_string () final override;
2428 virtual void maybe_populate_playback_blocks
2429 (auto_vec <playback::block *> *out) = 0;
2430
2431 protected:
2432 string *m_asm_template;
2433 bool m_is_volatile;
2434 bool m_is_inline;
2435 auto_vec<output_asm_operand *> m_output_ops;
2436 auto_vec<input_asm_operand *> m_input_ops;
2437 auto_vec<string *> m_clobbers;
2438 };
2439
2440 /* An extended_asm that's not a goto, as created by
2441 gcc_jit_block_add_extended_asm. */
2442
2443 class extended_asm_simple : public extended_asm
2444 {
2445 public:
2446 extended_asm_simple (block *b,
2447 location *loc,
2448 string *asm_template)
2449 : extended_asm (b, loc, asm_template)
2450 {}
2451
2452 void write_reproducer (reproducer &r) override;
2453 bool is_goto () const final override { return false; }
2454 void maybe_print_gotos (pretty_printer *) const final override {}
2455
2456 private:
2457 void maybe_populate_playback_blocks
2458 (auto_vec <playback::block *> *) final override
2459 {}
2460 };
2461
2462 /* An extended_asm that's a asm goto, as created by
2463 gcc_jit_block_end_with_extended_asm_goto. */
2464
2465 class extended_asm_goto : public extended_asm
2466 {
2467 public:
2468 extended_asm_goto (block *b,
2469 location *loc,
2470 string *asm_template,
2471 int num_goto_blocks,
2472 block **goto_blocks,
2473 block *fallthrough_block);
2474
2475 void replay_into (replayer *r) final override;
2476 void write_reproducer (reproducer &r) override;
2477
2478 vec <block *> get_successor_blocks () const final override;
2479
2480 bool is_goto () const final override { return true; }
2481 void maybe_print_gotos (pretty_printer *) const final override;
2482
2483 private:
2484 void maybe_populate_playback_blocks
2485 (auto_vec <playback::block *> *out) final override;
2486
2487 private:
2488 auto_vec <block *> m_goto_blocks;
2489 block *m_fallthrough_block;
2490 };
2491
2492 /* A group of top-level asm statements, as created by
2493 gcc_jit_context_add_top_level_asm. */
2494
2495 class top_level_asm : public memento
2496 {
2497 public:
2498 top_level_asm (context *ctxt, location *loc, string *asm_stmts);
2499
2500 void write_to_dump (dump &d) final override;
2501
2502 private:
2503 void replay_into (replayer *r) final override;
2504 string * make_debug_string () final override;
2505 void write_reproducer (reproducer &r) final override;
2506
2507 private:
2508 location *m_loc;
2509 string *m_asm_stmts;
2510 };
2511
2512 class global_init_rvalue : public memento
2513 {
2514 public:
2515 global_init_rvalue (context *ctxt, lvalue *variable, rvalue *init) :
2516 memento (ctxt), m_variable (variable), m_init (init) {};
2517
2518 void write_to_dump (dump &d) final override;
2519
2520 private:
2521 void replay_into (replayer *r) final override;
2522 string * make_debug_string () final override;
2523 void write_reproducer (reproducer &r) final override;
2524
2525 private:
2526 lvalue *m_variable;
2527 rvalue *m_init;
2528 };
2529
2530 } // namespace gcc::jit::recording
2531
2532 /* Create a recording::memento_of_new_rvalue_from_const instance and add
2533 it to this context's list of mementos.
2534
2535 Implements the post-error-checking part of
2536 gcc_jit_context_new_rvalue_from_{int|long|double|ptr}. */
2537
2538 template <typename HOST_TYPE>
2539 recording::rvalue *
2540 recording::context::new_rvalue_from_const (recording::type *type,
2541 HOST_TYPE value)
2542 {
2543 recording::rvalue *result =
2544 new memento_of_new_rvalue_from_const <HOST_TYPE> (this, NULL, type, value);
2545 record (result);
2546 return result;
2547 }
2548
2549 /* Don't call this directly. Call types_kinda_same. */
2550 bool
2551 types_kinda_same_internal (recording::type *a,
2552 recording::type *b);
2553
2554 /* Strip all qualifiers and count pointer depth, returning true
2555 if the types and pointer depth are the same, otherwise false.
2556
2557 For array and vector types the number of element also
2558 has to match, aswell as the element types themself. */
2559 inline bool
2560 types_kinda_same (recording::type *a, recording::type *b)
2561 {
2562 /* Handle trivial case here, to allow for inlining. */
2563 return a == b || types_kinda_same_internal (a, b);
2564 }
2565
2566 } // namespace gcc::jit
2567
2568 } // namespace gcc
2569
2570 #endif /* JIT_RECORDING_H */