1 /* Internals of libgccjit: classes for playing back recorded API calls.
2 Copyright (C) 2013-2024 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
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)
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.
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/>. */
21 #ifndef JIT_PLAYBACK_H
22 #define JIT_PLAYBACK_H
25 #include <utility> // for std::pair
31 #include "jit-recording.h"
33 class diagnostic_context
;
34 struct diagnostic_info
;
40 const char* fn_attribute_to_string (gcc_jit_fn_attribute attr
);
41 const char* variable_attribute_to_string (gcc_jit_variable_attribute attr
);
43 /**********************************************************************
45 **********************************************************************/
50 set_variable_string_attribute (
51 const std::vector
<std::pair
<gcc_jit_variable_attribute
,
52 std::string
>> &attributes
,
55 /* playback::context is an abstract base class.
57 The two concrete subclasses are:
58 - playback::compile_to_memory
59 - playback::compile_to_file. */
61 class context
: public log_user
64 context (::gcc::jit::recording::context
*ctxt
);
72 new_location (recording::location
*rloc
,
78 get_type (enum gcc_jit_types type
);
81 new_array_type (location
*loc
,
86 new_field (location
*loc
,
91 new_bitfield (location
*loc
,
97 new_compound_type (location
*loc
,
99 bool is_struct
); /* else is union */
102 new_function_type (type
*return_type
,
103 const auto_vec
<type
*> *param_types
,
107 new_param (location
*loc
,
112 new_function (location
*loc
,
113 enum gcc_jit_function_kind kind
,
116 const auto_vec
<param
*> *params
,
118 enum built_in_function builtin_id
,
119 const std::vector
<gcc_jit_fn_attribute
> &attributes
,
120 const std::vector
<std::pair
<gcc_jit_fn_attribute
,
121 std::string
>> &string_attributes
,
122 const std::vector
<std::pair
<gcc_jit_fn_attribute
,
124 &int_array_attributes
);
127 new_global (location
*loc
,
128 enum gcc_jit_global_kind kind
,
131 enum global_var_flags flags
,
132 const std::vector
<std::pair
<gcc_jit_variable_attribute
,
133 std::string
>> &attributes
);
136 new_global_initialized (location
*loc
,
137 enum gcc_jit_global_kind kind
,
140 size_t initializer_num_elem
,
141 const void *initializer
,
143 enum global_var_flags flags
,
144 const std::vector
<std::pair
<
145 gcc_jit_variable_attribute
,
150 new_ctor (location
*log
,
152 const auto_vec
<field
*> *fields
,
153 const auto_vec
<rvalue
*> *rvalues
);
157 global_set_init_rvalue (lvalue
* variable
,
160 template <typename HOST_TYPE
>
162 new_rvalue_from_const (type
*type
,
166 new_string_literal (const char *value
);
169 new_rvalue_from_vector (location
*loc
,
171 const auto_vec
<rvalue
*> &elements
);
174 new_unary_op (location
*loc
,
175 enum gcc_jit_unary_op op
,
180 new_binary_op (location
*loc
,
181 enum gcc_jit_binary_op op
,
183 rvalue
*a
, rvalue
*b
);
186 new_comparison (location
*loc
,
187 enum gcc_jit_comparison op
,
188 rvalue
*a
, rvalue
*b
, type
*vec_result_type
);
191 new_call (location
*loc
,
193 const auto_vec
<rvalue
*> *args
,
194 bool require_tail_call
);
197 new_call_through_ptr (location
*loc
,
199 const auto_vec
<rvalue
*> *args
,
200 bool require_tail_call
);
203 new_cast (location
*loc
,
208 new_bitcast (location
*loc
,
213 new_array_access (location
*loc
,
218 set_str_option (enum gcc_jit_str_option opt
,
222 set_int_option (enum gcc_jit_int_option opt
,
226 set_bool_option (enum gcc_jit_bool_option opt
,
230 get_str_option (enum gcc_jit_str_option opt
) const
232 return m_recording_ctxt
->get_str_option (opt
);
236 get_int_option (enum gcc_jit_int_option opt
) const
238 return m_recording_ctxt
->get_int_option (opt
);
242 get_bool_option (enum gcc_jit_bool_option opt
) const
244 return m_recording_ctxt
->get_bool_option (opt
);
248 get_inner_bool_option (enum inner_bool_option opt
) const
250 return m_recording_ctxt
->get_inner_bool_option (opt
);
253 builtins_manager
*get_builtins_manager () const
255 return m_recording_ctxt
->get_builtins_manager ();
262 add_error (location
*loc
, const char *fmt
, ...)
266 add_error_va (location
*loc
, const char *fmt
, va_list ap
)
270 get_first_error () const;
273 add_diagnostic (diagnostic_context
*context
,
274 const diagnostic_info
&diagnostic
);
277 set_tree_location (tree t
, location
*loc
);
280 new_field_access (location
*loc
,
285 new_dereference (tree ptr
, location
*loc
);
288 as_truth_value (tree expr
, location
*loc
);
290 bool errors_occurred () const
292 return m_recording_ctxt
->errors_occurred ();
295 timer
*get_timer () const { return m_recording_ctxt
->get_timer (); }
297 void add_top_level_asm (const char *asm_stmts
);
300 void dump_generated_code ();
303 build_call (location
*loc
,
305 const auto_vec
<rvalue
*> *args
,
306 bool require_tail_call
);
309 build_cast (location
*loc
,
314 get_source_file (const char *filename
);
317 get_tree_node_for_type (enum gcc_jit_types type_
);
319 void handle_locations ();
323 const char * get_path_c_file () const;
324 const char * get_path_s_file () const;
325 const char * get_path_so_file () const;
328 global_new_decl (location
*loc
,
329 enum gcc_jit_global_kind kind
,
332 enum global_var_flags flags
,
333 const std::vector
<std::pair
<gcc_jit_variable_attribute
,
334 std::string
>> &attributes
);
336 global_finalize_lvalue (tree inner
);
340 /* Functions for implementing "compile". */
347 make_fake_args (vec
<char *> *argvec
,
348 const char *ctxt_progname
,
349 vec
<recording::requested_dump
> *requested_dumps
);
352 extract_any_requested_dumps
353 (vec
<recording::requested_dump
> *requested_dumps
);
356 read_dump_file (const char *path
);
358 virtual void postprocess (const char *ctxt_progname
) = 0;
361 tempdir
*get_tempdir () { return m_tempdir
; }
364 convert_to_dso (const char *ctxt_progname
);
367 invoke_driver (const char *ctxt_progname
,
368 const char *input_file
,
369 const char *output_file
,
375 add_multilib_driver_arguments (vec
<char *> *argvec
);
382 invoke_embedded_driver (const vec
<char *> *argvec
);
385 invoke_external_driver (const char *ctxt_progname
,
386 vec
<char *> *argvec
);
389 ::gcc::jit::recording::context
*m_recording_ctxt
;
393 auto_vec
<function
*> m_functions
;
394 auto_vec
<tree
> m_globals
;
395 tree m_const_char_ptr
;
397 /* Source location handling. */
398 auto_vec
<source_file
*> m_source_files
;
400 auto_vec
<std::pair
<tree
, location
*> > m_cached_locations
;
403 class compile_to_memory
: public context
406 compile_to_memory (recording::context
*ctxt
);
407 void postprocess (const char *ctxt_progname
) final override
;
409 result
*get_result_obj () const { return m_result
; }
415 class compile_to_file
: public context
418 compile_to_file (recording::context
*ctxt
,
419 enum gcc_jit_output_kind output_kind
,
420 const char *output_path
);
421 void postprocess (const char *ctxt_progname
) final override
;
425 copy_file (const char *src_path
,
426 const char *dst_path
);
429 enum gcc_jit_output_kind m_output_kind
;
430 const char *m_output_path
;
434 /* A temporary wrapper object.
435 These objects are (mostly) only valid during replay.
436 We allocate them on the GC heap, so that they will be cleaned
437 the next time the GC collects.
438 The exception is the "function" class, which is tracked and marked by
439 the jit::context, since it needs to stay alive during post-processing
440 (when the GC could run). */
444 /* Allocate in the GC heap. */
445 void *operator new (size_t sz
);
447 /* Some wrapper subclasses contain vec<> and so need to
448 release them when they are GC-ed. */
449 virtual void finalizer () { }
453 class type
: public wrapper
460 tree
as_tree () const { return m_inner
; }
462 type
*get_pointer () const { return new type (build_pointer_type (m_inner
)); }
464 type
*get_const () const
466 return new type (build_qualified_type (m_inner
, TYPE_QUAL_CONST
));
469 type
*get_volatile () const
471 return new type (build_qualified_type (m_inner
, TYPE_QUAL_VOLATILE
));
474 type
*get_restrict () const
476 return new type (build_qualified_type (m_inner
, TYPE_QUAL_RESTRICT
));
479 type
*get_aligned (size_t alignment_in_bytes
) const;
480 type
*get_vector (size_t num_units
) const;
486 class compound_type
: public type
489 compound_type (tree inner
)
493 void set_fields (const auto_vec
<field
*> *fields
);
496 class field
: public wrapper
503 tree
as_tree () const { return m_inner
; }
509 class bitfield
: public field
{};
511 class function
: public wrapper
514 function(context
*ctxt
, tree fndecl
, enum gcc_jit_function_kind kind
);
517 void finalizer () final override
;
519 tree
get_return_type_as_tree () const;
521 tree
as_fndecl () const { return m_inner_fndecl
; }
523 enum gcc_jit_function_kind
get_kind () const { return m_kind
; }
526 new_local (location
*loc
,
529 const std::vector
<std::pair
<gcc_jit_variable_attribute
,
530 std::string
>> &attributes
);
533 new_block (const char *name
);
536 get_address (location
*loc
);
549 set_tree_location (tree t
, location
*loc
)
551 m_ctxt
->set_tree_location (t
, loc
);
557 tree m_inner_bind_expr
;
558 enum gcc_jit_function_kind m_kind
;
560 tree_stmt_iterator m_stmt_iter
;
561 vec
<block
*> m_blocks
;
566 case_ (rvalue
*min_value
, rvalue
*max_value
, block
*dest_block
)
567 : m_min_value (min_value
),
568 m_max_value (max_value
),
569 m_dest_block (dest_block
)
579 asm_operand (const char *asm_symbolic_name
,
580 const char *constraint
,
582 : m_asm_symbolic_name (asm_symbolic_name
),
583 m_constraint (constraint
),
587 const char *m_asm_symbolic_name
;
588 const char *m_constraint
;
592 class block
: public wrapper
595 block (function
*func
,
598 void finalizer () final override
;
600 tree
as_label_decl () const { return m_label_decl
; }
602 function
*get_function () const { return m_func
; }
605 add_eval (location
*loc
,
609 add_assignment (location
*loc
,
614 add_comment (location
*loc
,
618 add_conditional (location
*loc
,
624 add_block (location
*loc
,
628 add_jump (location
*loc
,
632 add_return (location
*loc
,
636 add_switch (location
*loc
,
638 block
*default_block
,
639 const auto_vec
<case_
> *cases
);
642 add_extended_asm (location
*loc
,
643 const char *asm_template
,
646 const auto_vec
<asm_operand
> *outputs
,
647 const auto_vec
<asm_operand
> *inputs
,
648 const auto_vec
<const char *> *clobbers
,
649 const auto_vec
<block
*> *goto_blocks
);
653 set_tree_location (tree t
, location
*loc
)
655 m_func
->set_tree_location (t
, loc
);
658 void add_stmt (tree stmt
)
660 /* TODO: use one stmt_list per block. */
661 m_stmts
.safe_push (stmt
);
672 friend class function
;
675 class rvalue
: public wrapper
678 rvalue (context
*ctxt
, tree inner
)
682 /* Pre-mark tree nodes with TREE_VISITED so that they can be
683 deeply unshared during gimplification (including across
684 functions); this requires LANG_HOOKS_DEEP_UNSHARING to be true. */
685 TREE_VISITED (inner
) = 1;
689 as_rvalue () { return this; }
691 tree
as_tree () const { return m_inner
; }
693 context
*get_context () const { return m_ctxt
; }
696 get_type () { return new type (TREE_TYPE (m_inner
)); }
699 access_field (location
*loc
,
703 dereference_field (location
*loc
,
707 dereference (location
*loc
);
714 class lvalue
: public rvalue
717 lvalue (context
*ctxt
, tree inner
)
718 : rvalue(ctxt
, inner
)
722 as_lvalue () { return this; }
725 access_field (location
*loc
,
729 get_address (location
*loc
);
732 set_tls_model (enum tls_model tls_model
)
734 set_decl_tls_model (as_tree (), tls_model
);
738 set_link_section (const char* name
)
740 set_decl_section_name (as_tree (), name
);
744 set_register_name (const char* reg_name
)
746 set_user_assembler_name (as_tree (), reg_name
);
747 DECL_REGISTER (as_tree ()) = 1;
748 DECL_HARD_REGISTER (as_tree ()) = 1;
752 set_alignment (int alignment
)
754 SET_DECL_ALIGN (as_tree (), alignment
* BITS_PER_UNIT
);
755 DECL_USER_ALIGN (as_tree ()) = 1;
759 bool mark_addressable (location
*loc
);
762 class param
: public lvalue
765 param (context
*ctxt
, tree inner
)
766 : lvalue(ctxt
, inner
)
770 /* Dealing with the linemap API.
772 It appears that libcpp requires locations to be created as if by
773 a tokenizer, creating them by filename, in ascending order of
774 line/column, whereas our API doesn't impose any such constraints:
775 we allow client code to create locations in arbitrary orders.
777 To square this circle, we need to cache all location creation,
778 grouping things up by filename/line, and then creating the linemap
779 entries in a post-processing phase. */
781 /* A set of locations, all sharing a filename */
782 class source_file
: public wrapper
785 source_file (tree filename
);
786 void finalizer () final override
;
789 get_source_line (int line_num
);
791 tree
filename_as_tree () const { return m_filename
; }
794 get_filename () const { return IDENTIFIER_POINTER (m_filename
); }
796 vec
<source_line
*> m_source_lines
;
802 /* A source line, with one or more locations of interest. */
803 class source_line
: public wrapper
806 source_line (source_file
*file
, int line_num
);
807 void finalizer () final override
;
810 get_location (recording::location
*rloc
, int column_num
);
812 int get_line_num () const { return m_line_num
; }
814 vec
<location
*> m_locations
;
817 source_file
*m_source_file ATTRIBUTE_UNUSED
;
821 /* A specific location on a source line. This is what we expose
822 to the client API. */
823 class location
: public wrapper
826 location (recording::location
*loc
, source_line
*line
, int column_num
);
828 int get_column_num () const { return m_column_num
; }
830 recording::location
*get_recording_loc () const { return m_recording_loc
; }
835 recording::location
*m_recording_loc
;
836 source_line
*m_line ATTRIBUTE_UNUSED
;
840 } // namespace gcc::jit::playback
842 extern playback::context
*active_playback_ctxt
;
844 } // namespace gcc::jit
848 #endif /* JIT_PLAYBACK_H */