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