1 /* Internals of libgccjit: classes for playing back recorded API calls.
2 Copyright (C) 2013-2015 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/>. */
23 #include "coretypes.h"
26 #include "statistics.h"
35 #include "hard-reg-set.h"
44 #include "stringpool.h"
45 #include "stor-layout.h"
46 #include "print-tree.h"
48 #include "gcc-driver-name.h"
51 #include "fold-const.h"
55 #include "jit-common.h"
56 #include "jit-logging.h"
57 #include "jit-playback.h"
58 #include "jit-result.h"
59 #include "jit-builtins.h"
60 #include "jit-tempdir.h"
63 /* gcc::jit::playback::context::build_cast uses the convert.h API,
64 which in turn requires the frontend to provide a "convert"
65 function, apparently as a fallback.
67 Hence we provide this dummy one, with the requirement that any casts
68 are handled before reaching this. */
69 extern tree
convert (tree type
, tree expr
);
72 convert (tree dst_type
, tree expr
)
74 gcc_assert (gcc::jit::active_playback_ctxt
);
75 gcc::jit::active_playback_ctxt
->add_error (NULL
, "unhandled conversion");
76 fprintf (stderr
, "input expression:\n");
78 fprintf (stderr
, "requested type:\n");
79 debug_tree (dst_type
);
80 return error_mark_node
;
86 /**********************************************************************
88 **********************************************************************/
90 /* The constructor for gcc::jit::playback::context. */
92 playback::context::context (recording::context
*ctxt
)
93 : log_user (ctxt
->get_logger ()),
94 m_recording_ctxt (ctxt
),
96 m_char_array_type_node (NULL
),
97 m_const_char_ptr (NULL
)
99 JIT_LOG_SCOPE (get_logger ());
100 m_functions
.create (0);
101 m_globals
.create (0);
102 m_source_files
.create (0);
103 m_cached_locations
.create (0);
106 /* The destructor for gcc::jit::playback::context. */
108 playback::context::~context ()
110 JIT_LOG_SCOPE (get_logger ());
112 /* Normally the playback::context is responsible for cleaning up the
113 tempdir (including "fake.so" within the filesystem).
115 In the normal case, clean it up now.
117 However m_tempdir can be NULL if the context has handed over
118 responsibility for the tempdir cleanup to the jit::result object, so
119 that the cleanup can be delayed (see PR jit/64206). If that's the
120 case this "delete NULL;" is a no-op. */
123 m_functions
.release ();
126 /* A playback::context can reference GC-managed pointers. Mark them
127 ("by hand", rather than by gengtype).
129 This is called on the active playback context (if any) by the
130 my_ggc_walker hook in the jit_root_table in dummy-frontend.c. */
138 FOR_EACH_VEC_ELT (m_functions
, i
, func
)
140 if (ggc_test_and_set_mark (func
))
145 /* Given an enum gcc_jit_types value, get a "tree" type. */
148 get_tree_node_for_type (enum gcc_jit_types type_
)
152 case GCC_JIT_TYPE_VOID
:
153 return void_type_node
;
155 case GCC_JIT_TYPE_VOID_PTR
:
156 return ptr_type_node
;
158 case GCC_JIT_TYPE_BOOL
:
159 return boolean_type_node
;
161 case GCC_JIT_TYPE_CHAR
:
162 return char_type_node
;
163 case GCC_JIT_TYPE_SIGNED_CHAR
:
164 return signed_char_type_node
;
165 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
166 return unsigned_char_type_node
;
168 case GCC_JIT_TYPE_SHORT
:
169 return short_integer_type_node
;
170 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
171 return short_unsigned_type_node
;
173 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
175 tree const_char
= build_qualified_type (char_type_node
,
177 return build_pointer_type (const_char
);
180 case GCC_JIT_TYPE_INT
:
181 return integer_type_node
;
182 case GCC_JIT_TYPE_UNSIGNED_INT
:
183 return unsigned_type_node
;
185 case GCC_JIT_TYPE_LONG
:
186 return long_integer_type_node
;
187 case GCC_JIT_TYPE_UNSIGNED_LONG
:
188 return long_unsigned_type_node
;
190 case GCC_JIT_TYPE_LONG_LONG
:
191 return long_long_integer_type_node
;
192 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
193 return long_long_unsigned_type_node
;
195 case GCC_JIT_TYPE_FLOAT
:
196 return float_type_node
;
197 case GCC_JIT_TYPE_DOUBLE
:
198 return double_type_node
;
199 case GCC_JIT_TYPE_LONG_DOUBLE
:
200 return long_double_type_node
;
202 case GCC_JIT_TYPE_SIZE_T
:
203 return size_type_node
;
205 case GCC_JIT_TYPE_FILE_PTR
:
206 return fileptr_type_node
;
208 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
209 return complex_float_type_node
;
210 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
211 return complex_double_type_node
;
212 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
213 return complex_long_double_type_node
;
219 /* Construct a playback::type instance (wrapping a tree) for the given
224 get_type (enum gcc_jit_types type_
)
226 tree type_node
= get_tree_node_for_type (type_
);
227 if (NULL
== type_node
)
230 "unrecognized (enum gcc_jit_types) value: %i", type_
);
234 return new type (type_node
);
237 /* Construct a playback::type instance (wrapping a tree) for the given
242 new_array_type (playback::location
*loc
,
243 playback::type
*element_type
,
246 gcc_assert (element_type
);
248 tree t
= build_array_type_nelts (element_type
->as_tree (),
253 set_tree_location (t
, loc
);
258 /* Construct a playback::field instance (wrapping a tree). */
262 new_field (location
*loc
,
269 /* compare with c/c-decl.c:grokfield and grokdeclarator. */
270 tree decl
= build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
271 get_identifier (name
), type
->as_tree ());
274 set_tree_location (decl
, loc
);
276 return new field (decl
);
279 /* Construct a playback::compound_type instance (wrapping a tree). */
281 playback::compound_type
*
283 new_compound_type (location
*loc
,
285 bool is_struct
) /* else is union */
289 /* Compare with c/c-decl.c: start_struct. */
291 tree t
= make_node (is_struct
? RECORD_TYPE
: UNION_TYPE
);
292 TYPE_NAME (t
) = get_identifier (name
);
296 set_tree_location (t
, loc
);
298 return new compound_type (t
);
302 playback::compound_type::set_fields (const auto_vec
<playback::field
*> *fields
)
304 /* Compare with c/c-decl.c: finish_struct. */
307 tree fieldlist
= NULL
;
308 for (unsigned i
= 0; i
< fields
->length (); i
++)
310 field
*f
= (*fields
)[i
];
311 DECL_CONTEXT (f
->as_tree ()) = t
;
312 fieldlist
= chainon (f
->as_tree (), fieldlist
);
314 fieldlist
= nreverse (fieldlist
);
315 TYPE_FIELDS (t
) = fieldlist
;
320 /* Construct a playback::type instance (wrapping a tree) for a function
325 new_function_type (type
*return_type
,
326 const auto_vec
<type
*> *param_types
,
332 tree
*arg_types
= (tree
*)xcalloc(param_types
->length (), sizeof(tree
*));
334 FOR_EACH_VEC_ELT (*param_types
, i
, param_type
)
335 arg_types
[i
] = param_type
->as_tree ();
340 build_varargs_function_type_array (return_type
->as_tree (),
341 param_types
->length (),
344 fn_type
= build_function_type_array (return_type
->as_tree (),
345 param_types
->length (),
349 return new type (fn_type
);
352 /* Construct a playback::param instance (wrapping a tree). */
356 new_param (location
*loc
,
362 tree inner
= build_decl (UNKNOWN_LOCATION
, PARM_DECL
,
363 get_identifier (name
), type
->as_tree ());
365 set_tree_location (inner
, loc
);
367 return new param (this, inner
);
370 /* Construct a playback::function instance. */
374 new_function (location
*loc
,
375 enum gcc_jit_function_kind kind
,
378 const auto_vec
<param
*> *params
,
380 enum built_in_function builtin_id
)
385 //can return_type be NULL?
388 tree
*arg_types
= (tree
*)xcalloc(params
->length (), sizeof(tree
*));
389 FOR_EACH_VEC_ELT (*params
, i
, param
)
390 arg_types
[i
] = TREE_TYPE (param
->as_tree ());
394 fn_type
= build_varargs_function_type_array (return_type
->as_tree (),
395 params
->length (), arg_types
);
397 fn_type
= build_function_type_array (return_type
->as_tree (),
398 params
->length (), arg_types
);
401 /* FIXME: this uses input_location: */
402 tree fndecl
= build_fn_decl (name
, fn_type
);
405 set_tree_location (fndecl
, loc
);
407 tree resdecl
= build_decl (UNKNOWN_LOCATION
, RESULT_DECL
,
408 NULL_TREE
, return_type
->as_tree ());
409 DECL_ARTIFICIAL (resdecl
) = 1;
410 DECL_IGNORED_P (resdecl
) = 1;
411 DECL_RESULT (fndecl
) = resdecl
;
415 DECL_FUNCTION_CODE (fndecl
) = builtin_id
;
416 gcc_assert (loc
== NULL
);
417 DECL_SOURCE_LOCATION (fndecl
) = BUILTINS_LOCATION
;
419 DECL_BUILT_IN_CLASS (fndecl
) =
420 builtins_manager::get_class (builtin_id
);
421 set_builtin_decl (builtin_id
, fndecl
,
422 builtins_manager::implicit_p (builtin_id
));
424 builtins_manager
*bm
= get_builtins_manager ();
425 tree attrs
= bm
->get_attrs_tree (builtin_id
);
427 decl_attributes (&fndecl
, attrs
, ATTR_FLAG_BUILT_IN
);
429 decl_attributes (&fndecl
, NULL_TREE
, 0);
432 if (kind
!= GCC_JIT_FUNCTION_IMPORTED
)
434 tree param_decl_list
= NULL
;
435 FOR_EACH_VEC_ELT (*params
, i
, param
)
437 param_decl_list
= chainon (param
->as_tree (), param_decl_list
);
440 /* The param list was created in reverse order; fix it: */
441 param_decl_list
= nreverse (param_decl_list
);
444 for (t
= param_decl_list
; t
; t
= DECL_CHAIN (t
))
446 DECL_CONTEXT (t
) = fndecl
;
447 DECL_ARG_TYPE (t
) = TREE_TYPE (t
);
450 /* Set it up on DECL_ARGUMENTS */
451 DECL_ARGUMENTS(fndecl
) = param_decl_list
;
454 if (kind
== GCC_JIT_FUNCTION_ALWAYS_INLINE
)
456 DECL_DECLARED_INLINE_P (fndecl
) = 1;
458 /* Add attribute "always_inline": */
459 DECL_ATTRIBUTES (fndecl
) =
460 tree_cons (get_identifier ("always_inline"),
462 DECL_ATTRIBUTES (fndecl
));
465 function
*func
= new function (this, fndecl
, kind
);
466 m_functions
.safe_push (func
);
470 /* Construct a playback::lvalue instance (wrapping a tree). */
474 new_global (location
*loc
,
475 enum gcc_jit_global_kind kind
,
481 tree inner
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
482 get_identifier (name
),
484 TREE_PUBLIC (inner
) = (kind
!= GCC_JIT_GLOBAL_INTERNAL
);
485 DECL_COMMON (inner
) = 1;
491 case GCC_JIT_GLOBAL_EXPORTED
:
492 TREE_STATIC (inner
) = 1;
495 case GCC_JIT_GLOBAL_INTERNAL
:
496 TREE_STATIC (inner
) = 1;
499 case GCC_JIT_GLOBAL_IMPORTED
:
500 DECL_EXTERNAL (inner
) = 1;
505 set_tree_location (inner
, loc
);
507 varpool_node::get_create (inner
);
509 varpool_node::finalize_decl (inner
);
511 m_globals
.safe_push (inner
);
513 return new lvalue (this, inner
);
516 /* Implementation of the various
517 gcc::jit::playback::context::new_rvalue_from_const <HOST_TYPE>
519 Each of these constructs a playback::rvalue instance (wrapping a tree).
521 These specializations are required to be in the same namespace
522 as the template, hence we now have to enter the gcc::jit::playback
528 /* Specialization of making an rvalue from a const, for host <int>. */
533 new_rvalue_from_const
<int> (type
*type
,
536 // FIXME: type-checking, or coercion?
537 tree inner_type
= type
->as_tree ();
538 if (INTEGRAL_TYPE_P (inner_type
))
540 tree inner
= build_int_cst (inner_type
, value
);
541 return new rvalue (this, inner
);
545 REAL_VALUE_TYPE real_value
;
546 real_from_integer (&real_value
, VOIDmode
, value
, SIGNED
);
547 tree inner
= build_real (inner_type
, real_value
);
548 return new rvalue (this, inner
);
552 /* Specialization of making an rvalue from a const, for host <long>. */
557 new_rvalue_from_const
<long> (type
*type
,
560 // FIXME: type-checking, or coercion?
561 tree inner_type
= type
->as_tree ();
562 if (INTEGRAL_TYPE_P (inner_type
))
564 tree inner
= build_int_cst (inner_type
, value
);
565 return new rvalue (this, inner
);
569 REAL_VALUE_TYPE real_value
;
570 real_from_integer (&real_value
, VOIDmode
, value
, SIGNED
);
571 tree inner
= build_real (inner_type
, real_value
);
572 return new rvalue (this, inner
);
576 /* Specialization of making an rvalue from a const, for host <double>. */
581 new_rvalue_from_const
<double> (type
*type
,
584 // FIXME: type-checking, or coercion?
585 tree inner_type
= type
->as_tree ();
587 /* We have a "double", we want a REAL_VALUE_TYPE.
589 real.c:real_from_target appears to require the representation to be
590 split into 32-bit values, and then sent as an pair of host long
592 REAL_VALUE_TYPE real_value
;
596 uint32_t as_uint32s
[2];
599 long int as_long_ints
[2];
600 as_long_ints
[0] = u
.as_uint32s
[0];
601 as_long_ints
[1] = u
.as_uint32s
[1];
602 real_from_target (&real_value
, as_long_ints
, DFmode
);
603 tree inner
= build_real (inner_type
, real_value
);
604 return new rvalue (this, inner
);
607 /* Specialization of making an rvalue from a const, for host <void *>. */
612 new_rvalue_from_const
<void *> (type
*type
,
615 tree inner_type
= type
->as_tree ();
616 /* FIXME: how to ensure we have a wide enough type? */
617 tree inner
= build_int_cstu (inner_type
, (unsigned HOST_WIDE_INT
)value
);
618 return new rvalue (this, inner
);
621 /* We're done implementing the specializations of
622 gcc::jit::playback::context::new_rvalue_from_const <T>
623 so we can exit the gcc::jit::playback namespace. */
625 } // namespace playback
627 /* Construct a playback::rvalue instance (wrapping a tree). */
631 new_string_literal (const char *value
)
633 tree t_str
= build_string (strlen (value
), value
);
634 gcc_assert (m_char_array_type_node
);
635 TREE_TYPE (t_str
) = m_char_array_type_node
;
637 /* Convert to (const char*), loosely based on
638 c/c-typeck.c: array_to_pointer_conversion,
639 by taking address of start of string. */
640 tree t_addr
= build1 (ADDR_EXPR
, m_const_char_ptr
, t_str
);
642 return new rvalue (this, t_addr
);
645 /* Coerce a tree expression into a boolean tree expression. */
649 as_truth_value (tree expr
, location
*loc
)
651 /* Compare to c-typeck.c:c_objc_common_truthvalue_conversion */
652 tree typed_zero
= fold_build1 (CONVERT_EXPR
,
656 set_tree_location (typed_zero
, loc
);
658 expr
= build2 (NE_EXPR
, integer_type_node
, expr
, typed_zero
);
660 set_tree_location (expr
, loc
);
665 /* Construct a playback::rvalue instance (wrapping a tree) for a
670 new_unary_op (location
*loc
,
671 enum gcc_jit_unary_op op
,
675 // FIXME: type-checking, or coercion?
676 enum tree_code inner_op
;
678 gcc_assert (result_type
);
681 tree node
= a
->as_tree ();
682 tree inner_result
= NULL
;
687 add_error (loc
, "unrecognized (enum gcc_jit_unary_op) value: %i", op
);
690 case GCC_JIT_UNARY_OP_MINUS
:
691 inner_op
= NEGATE_EXPR
;
694 case GCC_JIT_UNARY_OP_BITWISE_NEGATE
:
695 inner_op
= BIT_NOT_EXPR
;
698 case GCC_JIT_UNARY_OP_LOGICAL_NEGATE
:
699 node
= as_truth_value (node
, loc
);
700 inner_result
= invert_truthvalue (node
);
702 set_tree_location (inner_result
, loc
);
703 return new rvalue (this, inner_result
);
705 case GCC_JIT_UNARY_OP_ABS
:
710 inner_result
= build1 (inner_op
,
711 result_type
->as_tree (),
714 set_tree_location (inner_result
, loc
);
716 return new rvalue (this, inner_result
);
719 /* Construct a playback::rvalue instance (wrapping a tree) for a
724 new_binary_op (location
*loc
,
725 enum gcc_jit_binary_op op
,
727 rvalue
*a
, rvalue
*b
)
729 // FIXME: type-checking, or coercion?
730 enum tree_code inner_op
;
732 gcc_assert (result_type
);
736 tree node_a
= a
->as_tree ();
737 tree node_b
= b
->as_tree ();
742 add_error (loc
, "unrecognized (enum gcc_jit_binary_op) value: %i", op
);
745 case GCC_JIT_BINARY_OP_PLUS
:
746 inner_op
= PLUS_EXPR
;
749 case GCC_JIT_BINARY_OP_MINUS
:
750 inner_op
= MINUS_EXPR
;
753 case GCC_JIT_BINARY_OP_MULT
:
754 inner_op
= MULT_EXPR
;
757 case GCC_JIT_BINARY_OP_DIVIDE
:
758 if (FLOAT_TYPE_P (result_type
->as_tree ()))
759 /* Floating-point division: */
760 inner_op
= RDIV_EXPR
;
762 /* Truncating to zero: */
763 inner_op
= TRUNC_DIV_EXPR
;
766 case GCC_JIT_BINARY_OP_MODULO
:
767 inner_op
= TRUNC_MOD_EXPR
;
770 case GCC_JIT_BINARY_OP_BITWISE_AND
:
771 inner_op
= BIT_AND_EXPR
;
774 case GCC_JIT_BINARY_OP_BITWISE_XOR
:
775 inner_op
= BIT_XOR_EXPR
;
778 case GCC_JIT_BINARY_OP_BITWISE_OR
:
779 inner_op
= BIT_IOR_EXPR
;
782 case GCC_JIT_BINARY_OP_LOGICAL_AND
:
783 node_a
= as_truth_value (node_a
, loc
);
784 node_b
= as_truth_value (node_b
, loc
);
785 inner_op
= TRUTH_ANDIF_EXPR
;
788 case GCC_JIT_BINARY_OP_LOGICAL_OR
:
789 node_a
= as_truth_value (node_a
, loc
);
790 node_b
= as_truth_value (node_b
, loc
);
791 inner_op
= TRUTH_ORIF_EXPR
;
794 case GCC_JIT_BINARY_OP_LSHIFT
:
795 inner_op
= LSHIFT_EXPR
;
798 case GCC_JIT_BINARY_OP_RSHIFT
:
799 inner_op
= RSHIFT_EXPR
;
803 tree inner_expr
= build2 (inner_op
,
804 result_type
->as_tree (),
808 set_tree_location (inner_expr
, loc
);
810 return new rvalue (this, inner_expr
);
813 /* Construct a playback::rvalue instance (wrapping a tree) for a
818 new_comparison (location
*loc
,
819 enum gcc_jit_comparison op
,
820 rvalue
*a
, rvalue
*b
)
822 // FIXME: type-checking, or coercion?
823 enum tree_code inner_op
;
831 add_error (loc
, "unrecognized (enum gcc_jit_comparison) value: %i", op
);
834 case GCC_JIT_COMPARISON_EQ
:
837 case GCC_JIT_COMPARISON_NE
:
840 case GCC_JIT_COMPARISON_LT
:
843 case GCC_JIT_COMPARISON_LE
:
846 case GCC_JIT_COMPARISON_GT
:
849 case GCC_JIT_COMPARISON_GE
:
854 tree inner_expr
= build2 (inner_op
,
859 set_tree_location (inner_expr
, loc
);
860 return new rvalue (this, inner_expr
);
863 /* Construct a playback::rvalue instance (wrapping a tree) for a
868 build_call (location
*loc
,
870 const auto_vec
<rvalue
*> *args
)
872 vec
<tree
, va_gc
> *tree_args
;
873 vec_alloc (tree_args
, args
->length ());
874 for (unsigned i
= 0; i
< args
->length (); i
++)
875 tree_args
->quick_push ((*args
)[i
]->as_tree ());
878 set_tree_location (fn_ptr
, loc
);
880 tree fn
= TREE_TYPE (fn_ptr
);
881 tree fn_type
= TREE_TYPE (fn
);
882 tree return_type
= TREE_TYPE (fn_type
);
884 return new rvalue (this,
885 build_call_vec (return_type
,
888 /* see c-typeck.c: build_function_call
889 which calls build_function_call_vec
891 which does lots of checking, then:
892 result = build_call_array_loc (loc, TREE_TYPE (fntype),
893 function, nargs, argarray);
895 (see also build_call_vec)
899 /* Construct a playback::rvalue instance (wrapping a tree) for a
900 call to a specific function. */
904 new_call (location
*loc
,
906 const auto_vec
<rvalue
*> *args
)
912 fndecl
= func
->as_fndecl ();
914 tree fntype
= TREE_TYPE (fndecl
);
916 tree fn
= build1 (ADDR_EXPR
, build_pointer_type (fntype
), fndecl
);
918 return build_call (loc
, fn
, args
);
921 /* Construct a playback::rvalue instance (wrapping a tree) for a
922 call through a function pointer. */
926 new_call_through_ptr (location
*loc
,
928 const auto_vec
<rvalue
*> *args
)
931 tree t_fn_ptr
= fn_ptr
->as_tree ();
933 return build_call (loc
, t_fn_ptr
, args
);
936 /* Construct a tree for a cast. */
939 playback::context::build_cast (playback::location
*loc
,
940 playback::rvalue
*expr
,
941 playback::type
*type_
)
943 /* For comparison, see:
944 - c/c-typeck.c:build_c_cast
945 - c/c-convert.c: convert
948 Only some kinds of cast are currently supported here. */
949 tree t_expr
= expr
->as_tree ();
950 tree t_dst_type
= type_
->as_tree ();
952 t_ret
= targetm
.convert_to_type (t_dst_type
, t_expr
);
955 enum tree_code dst_code
= TREE_CODE (t_dst_type
);
960 t_ret
= convert_to_integer (t_dst_type
, t_expr
);
964 /* Compare with c_objc_common_truthvalue_conversion and
965 c_common_truthvalue_conversion. */
966 /* For now, convert to: (t_expr != 0) */
967 t_ret
= build2 (NE_EXPR
, t_dst_type
,
969 build_int_cst (TREE_TYPE (t_expr
), 0));
973 t_ret
= convert_to_real (t_dst_type
, t_expr
);
977 t_ret
= build1 (NOP_EXPR
, t_dst_type
, t_expr
);
981 add_error (loc
, "couldn't handle cast during playback");
982 fprintf (stderr
, "input expression:\n");
984 fprintf (stderr
, "requested type:\n");
985 debug_tree (t_dst_type
);
986 return error_mark_node
;
989 if (TREE_CODE (t_ret
) != C_MAYBE_CONST_EXPR
)
990 t_ret
= fold (t_ret
);
995 /* Construct a playback::rvalue instance (wrapping a tree) for a
1000 new_cast (playback::location
*loc
,
1001 playback::rvalue
*expr
,
1002 playback::type
*type_
)
1005 tree t_cast
= build_cast (loc
, expr
, type_
);
1007 set_tree_location (t_cast
, loc
);
1008 return new rvalue (this, t_cast
);
1011 /* Construct a playback::lvalue instance (wrapping a tree) for an
1016 new_array_access (location
*loc
,
1023 /* For comparison, see:
1024 c/c-typeck.c: build_array_ref
1025 c-family/c-common.c: pointer_int_sum
1027 tree t_ptr
= ptr
->as_tree ();
1028 tree t_index
= index
->as_tree ();
1029 tree t_type_ptr
= TREE_TYPE (t_ptr
);
1030 tree t_type_star_ptr
= TREE_TYPE (t_type_ptr
);
1032 if (TREE_CODE (t_type_ptr
) == ARRAY_TYPE
)
1034 tree t_result
= build4 (ARRAY_REF
, t_type_star_ptr
, t_ptr
, t_index
,
1035 NULL_TREE
, NULL_TREE
);
1037 set_tree_location (t_result
, loc
);
1038 return new lvalue (this, t_result
);
1042 /* Convert index to an offset in bytes. */
1043 tree t_sizeof
= size_in_bytes (t_type_star_ptr
);
1044 t_index
= fold_build1 (CONVERT_EXPR
, sizetype
, t_index
);
1045 tree t_offset
= build2 (MULT_EXPR
, sizetype
, t_index
, t_sizeof
);
1047 /* Locate (ptr + offset). */
1048 tree t_address
= build2 (POINTER_PLUS_EXPR
, t_type_ptr
, t_ptr
, t_offset
);
1050 tree t_indirection
= build1 (INDIRECT_REF
, t_type_star_ptr
, t_address
);
1053 set_tree_location (t_sizeof
, loc
);
1054 set_tree_location (t_offset
, loc
);
1055 set_tree_location (t_address
, loc
);
1056 set_tree_location (t_indirection
, loc
);
1059 return new lvalue (this, t_indirection
);
1063 /* Construct a tree for a field access. */
1067 new_field_access (location
*loc
,
1074 /* Compare with c/c-typeck.c:lookup_field, build_indirect_ref, and
1075 build_component_ref. */
1076 tree type
= TREE_TYPE (datum
);
1078 gcc_assert (TREE_CODE (type
) != POINTER_TYPE
);
1080 tree t_field
= field
->as_tree ();
1081 tree ref
= build3 (COMPONENT_REF
, TREE_TYPE (t_field
), datum
,
1082 t_field
, NULL_TREE
);
1084 set_tree_location (ref
, loc
);
1088 /* Construct a tree for a dereference. */
1092 new_dereference (tree ptr
,
1097 tree type
= TREE_TYPE (TREE_TYPE(ptr
));
1098 tree datum
= build1 (INDIRECT_REF
, type
, ptr
);
1100 set_tree_location (datum
, loc
);
1104 /* Construct a playback::lvalue instance (wrapping a tree) for a
1109 access_field (location
*loc
,
1112 tree datum
= as_tree ();
1113 tree ref
= get_context ()->new_field_access (loc
, datum
, field
);
1116 return new lvalue (get_context (), ref
);
1119 /* Construct a playback::rvalue instance (wrapping a tree) for a
1124 access_field (location
*loc
,
1127 tree datum
= as_tree ();
1128 tree ref
= get_context ()->new_field_access (loc
, datum
, field
);
1131 return new rvalue (get_context (), ref
);
1134 /* Construct a playback::lvalue instance (wrapping a tree) for a
1135 dereferenced field access. */
1139 dereference_field (location
*loc
,
1142 tree ptr
= as_tree ();
1143 tree datum
= get_context ()->new_dereference (ptr
, loc
);
1146 tree ref
= get_context ()->new_field_access (loc
, datum
, field
);
1149 return new lvalue (get_context (), ref
);
1152 /* Construct a playback::lvalue instance (wrapping a tree) for a
1157 dereference (location
*loc
)
1159 tree ptr
= as_tree ();
1160 tree datum
= get_context ()->new_dereference (ptr
, loc
);
1161 return new lvalue (get_context (), datum
);
1164 /* Mark EXP saying that we need to be able to take the
1165 address of it; it should not be allocated in a register.
1166 Compare with e.g. c/c-typeck.c: c_mark_addressable. */
1169 jit_mark_addressable (tree exp
)
1174 switch (TREE_CODE (x
))
1177 /* (we don't yet support bitfields) */
1183 x
= TREE_OPERAND (x
, 0);
1186 case COMPOUND_LITERAL_EXPR
:
1188 TREE_ADDRESSABLE (x
) = 1;
1195 /* (we don't have a concept of a "register" declaration) */
1198 TREE_ADDRESSABLE (x
) = 1;
1205 /* Construct a playback::rvalue instance (wrapping a tree) for an
1210 get_address (location
*loc
)
1212 tree t_lvalue
= as_tree ();
1213 tree t_thistype
= TREE_TYPE (t_lvalue
);
1214 tree t_ptrtype
= build_pointer_type (t_thistype
);
1215 tree ptr
= build1 (ADDR_EXPR
, t_ptrtype
, t_lvalue
);
1217 get_context ()->set_tree_location (ptr
, loc
);
1218 jit_mark_addressable (t_lvalue
);
1219 return new rvalue (get_context (), ptr
);
1222 /* The wrapper subclasses are GC-managed, but can own non-GC memory.
1223 Provide this finalization hook for calling then they are collected,
1224 which calls the finalizer vfunc. This allows them to call "release"
1225 on any vec<> within them. */
1228 wrapper_finalizer (void *ptr
)
1230 playback::wrapper
*wrapper
= reinterpret_cast <playback::wrapper
*> (ptr
);
1231 wrapper
->finalizer ();
1234 /* gcc::jit::playback::wrapper subclasses are GC-managed:
1235 allocate them using ggc_internal_cleared_alloc. */
1239 operator new (size_t sz
)
1241 return ggc_internal_cleared_alloc (sz
, wrapper_finalizer
, 0, 1);
1245 /* Constructor for gcc:jit::playback::function. */
1247 playback::function::
1248 function (context
*ctxt
,
1250 enum gcc_jit_function_kind kind
)
1252 m_inner_fndecl (fndecl
),
1253 m_inner_bind_expr (NULL
),
1256 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
)
1258 /* Create a BIND_EXPR, and within it, a statement list. */
1259 m_stmt_list
= alloc_stmt_list ();
1260 m_stmt_iter
= tsi_start (m_stmt_list
);
1261 m_inner_block
= make_node (BLOCK
);
1263 build3 (BIND_EXPR
, void_type_node
, NULL
, m_stmt_list
, m_inner_block
);
1267 m_inner_block
= NULL
;
1272 /* Hand-written GC-marking hook for playback functions. */
1275 playback::function::
1278 gt_ggc_m_9tree_node (m_inner_fndecl
);
1279 gt_ggc_m_9tree_node (m_inner_bind_expr
);
1280 gt_ggc_m_9tree_node (m_stmt_list
);
1281 gt_ggc_m_9tree_node (m_inner_block
);
1284 /* Don't leak vec's internal buffer (in non-GC heap) when we are
1288 playback::function::finalizer ()
1290 m_blocks
.release ();
1293 /* Get the return type of a playback function, in tree form. */
1296 playback::function::
1297 get_return_type_as_tree () const
1299 return TREE_TYPE (TREE_TYPE(m_inner_fndecl
));
1302 /* Construct a new local within this playback::function. */
1305 playback::function::
1306 new_local (location
*loc
,
1312 tree inner
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
1313 get_identifier (name
),
1315 DECL_CONTEXT (inner
) = this->m_inner_fndecl
;
1317 /* Prepend to BIND_EXPR_VARS: */
1318 DECL_CHAIN (inner
) = BIND_EXPR_VARS (m_inner_bind_expr
);
1319 BIND_EXPR_VARS (m_inner_bind_expr
) = inner
;
1322 set_tree_location (inner
, loc
);
1323 return new lvalue (m_ctxt
, inner
);
1326 /* Construct a new block within this playback::function. */
1329 playback::function::
1330 new_block (const char *name
)
1332 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
1334 block
*result
= new playback::block (this, name
);
1335 m_blocks
.safe_push (result
);
1339 /* Build a statement list for the function as a whole out of the
1340 lists of statements for the individual blocks, building labels
1344 playback::function::
1350 JIT_LOG_SCOPE (m_ctxt
->get_logger ());
1352 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
1357 b
->m_label_expr
= build1 (LABEL_EXPR
,
1359 b
->as_label_decl ());
1360 tsi_link_after (&m_stmt_iter
, b
->m_label_expr
, TSI_CONTINUE_LINKING
);
1362 FOR_EACH_VEC_ELT (b
->m_stmts
, j
, stmt
)
1363 tsi_link_after (&m_stmt_iter
, stmt
, TSI_CONTINUE_LINKING
);
1367 /* Finish compiling the given function, potentially running the
1369 The function will have a statement list by now.
1370 Amongst other things, this gimplifies the statement list,
1371 and calls cgraph_node::finalize_function on the function. */
1374 playback::function::
1377 JIT_LOG_SCOPE (m_ctxt
->get_logger ());
1379 if (m_ctxt
->get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE
))
1380 debug_tree (m_stmt_list
);
1382 /* Do we need this to force cgraphunit.c to output the function? */
1383 if (m_kind
== GCC_JIT_FUNCTION_EXPORTED
)
1385 DECL_EXTERNAL (m_inner_fndecl
) = 0;
1386 DECL_PRESERVE_P (m_inner_fndecl
) = 1;
1389 if (m_kind
== GCC_JIT_FUNCTION_INTERNAL
1390 ||m_kind
== GCC_JIT_FUNCTION_ALWAYS_INLINE
)
1392 DECL_EXTERNAL (m_inner_fndecl
) = 0;
1393 TREE_PUBLIC (m_inner_fndecl
) = 0;
1396 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
)
1398 /* Seem to need this in gimple-low.c: */
1399 gcc_assert (m_inner_block
);
1400 DECL_INITIAL (m_inner_fndecl
) = m_inner_block
;
1402 /* how to add to function? the following appears to be how to
1403 set the body of a m_inner_fndecl: */
1404 DECL_SAVED_TREE(m_inner_fndecl
) = m_inner_bind_expr
;
1406 /* Ensure that locals appear in the debuginfo. */
1407 BLOCK_VARS (m_inner_block
) = BIND_EXPR_VARS (m_inner_bind_expr
);
1409 //debug_tree (m_inner_fndecl);
1411 /* Convert to gimple: */
1412 //printf("about to gimplify_function_tree\n");
1413 gimplify_function_tree (m_inner_fndecl
);
1414 //printf("finished gimplify_function_tree\n");
1416 current_function_decl
= m_inner_fndecl
;
1417 if (m_ctxt
->get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE
))
1418 dump_function_to_file (m_inner_fndecl
, stderr
, TDF_VOPS
|TDF_MEMSYMS
|TDF_LINENO
);
1419 //debug_tree (m_inner_fndecl);
1421 //printf("about to add to cgraph\n");
1422 /* Add to cgraph: */
1423 cgraph_node::finalize_function (m_inner_fndecl
, false);
1424 /* This can trigger a collection, so we need to have all of
1425 the funcs as roots. */
1427 current_function_decl
= NULL
;
1431 /* Don't leak vec's internal buffer (in non-GC heap) when we are
1435 playback::block::finalizer ()
1440 /* Add an eval of the rvalue to the function's statement list. */
1444 add_eval (location
*loc
,
1447 gcc_assert (rvalue
);
1450 set_tree_location (rvalue
->as_tree (), loc
);
1452 add_stmt (rvalue
->as_tree ());
1455 /* Add an assignment to the function's statement list. */
1459 add_assignment (location
*loc
,
1463 gcc_assert (lvalue
);
1464 gcc_assert (rvalue
);
1466 tree t_lvalue
= lvalue
->as_tree ();
1467 tree t_rvalue
= rvalue
->as_tree ();
1468 if (TREE_TYPE (t_rvalue
) != TREE_TYPE (t_lvalue
))
1470 t_rvalue
= build1 (CONVERT_EXPR
,
1471 TREE_TYPE (t_lvalue
),
1474 set_tree_location (t_rvalue
, loc
);
1478 build2 (MODIFY_EXPR
, TREE_TYPE (t_lvalue
),
1479 t_lvalue
, t_rvalue
);
1481 set_tree_location (stmt
, loc
);
1485 /* Add a comment to the function's statement list.
1486 For now this is done by adding a dummy label. */
1490 add_comment (location
*loc
,
1493 /* Wrap the text in C-style comment delimiters. */
1495 (3 /* opening delim */
1497 + 3 /* closing delim */
1498 + 1 /* terminator */);
1499 char *wrapped
= (char *)ggc_internal_alloc (sz
);
1500 snprintf (wrapped
, sz
, "/* %s */", text
);
1502 /* For now we simply implement this by adding a dummy label with a name
1503 containing the given text. */
1504 tree identifier
= get_identifier (wrapped
);
1505 tree label_decl
= build_decl (UNKNOWN_LOCATION
, LABEL_DECL
,
1506 identifier
, void_type_node
);
1507 DECL_CONTEXT (label_decl
) = m_func
->as_fndecl ();
1509 tree label_expr
= build1 (LABEL_EXPR
, void_type_node
, label_decl
);
1511 set_tree_location (label_expr
, loc
);
1512 add_stmt (label_expr
);
1515 /* Add a conditional jump statement to the function's statement list. */
1519 add_conditional (location
*loc
,
1524 gcc_assert (boolval
);
1525 gcc_assert (on_true
);
1526 gcc_assert (on_false
);
1528 /* COND_EXPR wants statement lists for the true/false operands, but we
1530 Shim it by creating jumps to the labels */
1531 tree true_jump
= build1 (GOTO_EXPR
, void_type_node
,
1532 on_true
->as_label_decl ());
1534 set_tree_location (true_jump
, loc
);
1536 tree false_jump
= build1 (GOTO_EXPR
, void_type_node
,
1537 on_false
->as_label_decl ());
1539 set_tree_location (false_jump
, loc
);
1542 build3 (COND_EXPR
, void_type_node
, boolval
->as_tree (),
1543 true_jump
, false_jump
);
1545 set_tree_location (stmt
, loc
);
1549 /* Add an unconditional jump statement to the function's statement list. */
1553 add_jump (location
*loc
,
1556 gcc_assert (target
);
1558 // see c_finish_loop
1559 //tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
1562 //tree stmt = build_and_jump (&LABEL_EXPR_LABEL (target->label_));
1563 TREE_USED (target
->as_label_decl ()) = 1;
1564 tree stmt
= build1 (GOTO_EXPR
, void_type_node
, target
->as_label_decl ());
1566 set_tree_location (stmt
, loc
);
1572 c_finish_goto_label (location_t loc, tree label)
1574 tree decl = lookup_label_for_goto (loc, label);
1577 TREE_USED (decl) = 1;
1579 tree t = build1 (GOTO_EXPR, void_type_node, decl);
1580 SET_EXPR_LOCATION (t, loc);
1581 return add_stmt (t);
1588 /* Add a return statement to the function's statement list. */
1592 add_return (location
*loc
,
1595 tree modify_retval
= NULL
;
1596 tree return_type
= m_func
->get_return_type_as_tree ();
1599 tree t_lvalue
= DECL_RESULT (m_func
->as_fndecl ());
1600 tree t_rvalue
= rvalue
->as_tree ();
1601 if (TREE_TYPE (t_rvalue
) != TREE_TYPE (t_lvalue
))
1602 t_rvalue
= build1 (CONVERT_EXPR
,
1603 TREE_TYPE (t_lvalue
),
1605 modify_retval
= build2 (MODIFY_EXPR
, return_type
,
1606 t_lvalue
, t_rvalue
);
1608 set_tree_location (modify_retval
, loc
);
1610 tree return_stmt
= build1 (RETURN_EXPR
, return_type
,
1613 set_tree_location (return_stmt
, loc
);
1615 add_stmt (return_stmt
);
1618 /* Helper function for playback::block::add_switch.
1619 Construct a case label for the given range, followed by a goto stmt
1620 to the given block, appending them to stmt list *ptr_t_switch_body. */
1623 add_case (tree
*ptr_t_switch_body
,
1626 playback::block
*dest_block
)
1628 tree t_label
= create_artificial_label (UNKNOWN_LOCATION
);
1629 DECL_CONTEXT (t_label
) = dest_block
->get_function ()->as_fndecl ();
1632 build_case_label (t_low_value
, t_high_value
, t_label
);
1633 append_to_statement_list (t_case_label
, ptr_t_switch_body
);
1636 build1 (GOTO_EXPR
, void_type_node
, dest_block
->as_label_decl ());
1637 append_to_statement_list (t_goto_stmt
, ptr_t_switch_body
);
1640 /* Add a switch statement to the function's statement list.
1642 My initial attempt at implementing this constructed a TREE_VEC
1643 of the cases and set it as SWITCH_LABELS (switch_expr). However,
1644 gimplify.c:gimplify_switch_expr is set up to deal with SWITCH_BODY, and
1645 doesn't have any logic for gimplifying SWITCH_LABELS.
1647 Hence we create a switch body, and populate it with case labels, each
1648 followed by a goto to the desired block. */
1652 add_switch (location
*loc
,
1654 block
*default_block
,
1655 const auto_vec
<case_
> *cases
)
1658 - c/c-typeck.c: c_start_case
1659 - c-family/c-common.c:c_add_case_label
1660 - java/expr.c:expand_java_switch and expand_java_add_case
1661 We've already rejected overlaps and duplicates in
1662 libgccjit.c:case_range_validator::validate. */
1664 tree t_expr
= expr
->as_tree ();
1665 tree t_type
= TREE_TYPE (t_expr
);
1667 tree t_switch_body
= alloc_stmt_list ();
1671 FOR_EACH_VEC_ELT (*cases
, i
, c
)
1673 tree t_low_value
= c
->m_min_value
->as_tree ();
1674 tree t_high_value
= c
->m_max_value
->as_tree ();
1675 add_case (&t_switch_body
,
1680 /* Default label. */
1681 add_case (&t_switch_body
,
1682 NULL_TREE
, NULL_TREE
,
1685 tree switch_stmt
= build3 (SWITCH_EXPR
, t_type
, t_expr
,
1686 t_switch_body
, NULL_TREE
);
1688 set_tree_location (switch_stmt
, loc
);
1689 add_stmt (switch_stmt
);
1692 /* Constructor for gcc::jit::playback::block. */
1695 block (function
*func
,
1705 identifier
= get_identifier (name
);
1708 m_label_decl
= build_decl (UNKNOWN_LOCATION
, LABEL_DECL
,
1709 identifier
, void_type_node
);
1710 DECL_CONTEXT (m_label_decl
) = func
->as_fndecl ();
1711 m_label_expr
= NULL
;
1714 /* A subclass of auto_vec <char *> that frees all of its elements on
1717 class auto_argvec
: public auto_vec
<char *>
1723 /* auto_argvec's dtor, freeing all contained strings, automatically
1724 chaining up to ~auto_vec <char *>, which frees the internal buffer. */
1726 auto_argvec::~auto_argvec ()
1730 FOR_EACH_VEC_ELT (*this, i
, str
)
1734 /* Compile a playback::context:
1736 - Use the context's options to cconstruct command-line options, and
1737 call into the rest of GCC (toplev::main).
1738 - Assuming it succeeds, we have a .s file.
1739 - We then run the "postprocess" vfunc:
1741 (A) In-memory compile ("gcc_jit_context_compile")
1743 For an in-memory compile we have the playback::compile_to_memory
1744 subclass; "postprocess" will convert the .s file to a .so DSO,
1745 and load it in memory (via dlopen), wrapping the result up as
1746 a jit::result and returning it.
1748 (B) Compile to file ("gcc_jit_context_compile_to_file")
1750 When compiling to a file, we have the playback::compile_to_file
1751 subclass; "postprocess" will either copy the .s file to the
1752 destination (for GCC_JIT_OUTPUT_KIND_ASSEMBLER), or invoke
1753 the driver to convert it as necessary, copying the result. */
1759 JIT_LOG_SCOPE (get_logger ());
1761 const char *ctxt_progname
;
1763 int keep_intermediates
=
1764 get_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES
);
1766 m_tempdir
= new tempdir (get_logger (), keep_intermediates
);
1767 if (!m_tempdir
->create ())
1770 /* Call into the rest of gcc.
1771 For now, we have to assemble command-line options to pass into
1772 toplev::main, so that they can be parsed. */
1774 /* Pass in user-provided program name as argv0, if any, so that it
1775 makes it into GCC's "progname" global, used in various diagnostics. */
1776 ctxt_progname
= get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1779 ctxt_progname
= "libgccjit.so";
1781 auto_vec
<recording::requested_dump
> requested_dumps
;
1782 m_recording_ctxt
->get_all_requested_dumps (&requested_dumps
);
1784 /* Acquire the JIT mutex and set "this" as the active playback ctxt. */
1787 auto_argvec fake_args
;
1788 make_fake_args (&fake_args
, ctxt_progname
, &requested_dumps
);
1789 if (errors_occurred ())
1795 /* This runs the compiler. */
1796 toplev
toplev (get_timer (), /* external_timer */
1797 false); /* init_signals */
1798 enter_scope ("toplev::main");
1800 for (unsigned i
= 0; i
< fake_args
.length (); i
++)
1801 get_logger ()->log ("argv[%i]: %s", i
, fake_args
[i
]);
1802 toplev
.main (fake_args
.length (),
1803 const_cast <char **> (fake_args
.address ()));
1804 exit_scope ("toplev::main");
1806 /* Extracting dumps makes use of the gcc::dump_manager, hence we
1807 need to do it between toplev::main (which creates the dump manager)
1808 and toplev::finalize (which deletes it). */
1809 extract_any_requested_dumps (&requested_dumps
);
1811 /* Clean up the compiler. */
1812 enter_scope ("toplev::finalize");
1814 exit_scope ("toplev::finalize");
1816 /* Ideally we would release the jit mutex here, but we can't yet since
1817 followup activities use timevars, which are global state. */
1819 if (errors_occurred ())
1825 if (get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE
))
1826 dump_generated_code ();
1828 /* We now have a .s file.
1830 Run any postprocessing steps. This will either convert the .s file to
1831 a .so DSO, and load it in memory (playback::compile_to_memory), or
1832 convert the .s file to the requested output format, and copy it to a
1833 given file (playback::compile_to_file). */
1834 postprocess (ctxt_progname
);
1839 /* Implementation of class gcc::jit::playback::compile_to_memory,
1840 a subclass of gcc::jit::playback::context. */
1842 /* playback::compile_to_memory's trivial constructor. */
1844 playback::compile_to_memory::compile_to_memory (recording::context
*ctxt
) :
1845 playback::context (ctxt
),
1848 JIT_LOG_SCOPE (get_logger ());
1851 /* Implementation of the playback::context::process vfunc for compiling
1854 Convert the .s file to a .so DSO, and load it in memory (via dlopen),
1855 wrapping the result up as a jit::result and returning it. */
1858 playback::compile_to_memory::postprocess (const char *ctxt_progname
)
1860 JIT_LOG_SCOPE (get_logger ());
1861 convert_to_dso (ctxt_progname
);
1862 if (errors_occurred ())
1864 m_result
= dlopen_built_dso ();
1867 /* Implementation of class gcc::jit::playback::compile_to_file,
1868 a subclass of gcc::jit::playback::context. */
1870 /* playback::compile_to_file's trivial constructor. */
1872 playback::compile_to_file::compile_to_file (recording::context
*ctxt
,
1873 enum gcc_jit_output_kind output_kind
,
1874 const char *output_path
) :
1875 playback::context (ctxt
),
1876 m_output_kind (output_kind
),
1877 m_output_path (output_path
)
1879 JIT_LOG_SCOPE (get_logger ());
1882 /* Implementation of the playback::context::process vfunc for compiling
1885 Either copy the .s file to the given destination (for
1886 GCC_JIT_OUTPUT_KIND_ASSEMBLER), or invoke the driver to convert it
1887 as necessary, copying the result. */
1890 playback::compile_to_file::postprocess (const char *ctxt_progname
)
1892 JIT_LOG_SCOPE (get_logger ());
1894 /* The driver takes different actions based on the filename, so
1895 we provide a filename with an appropriate suffix for the
1896 output kind, and then copy it up to the user-provided path,
1897 rather than directly compiling it to the requested output path. */
1899 switch (m_output_kind
)
1904 case GCC_JIT_OUTPUT_KIND_ASSEMBLER
:
1905 copy_file (get_tempdir ()->get_path_s_file (),
1909 case GCC_JIT_OUTPUT_KIND_OBJECT_FILE
:
1911 char *tmp_o_path
= ::concat (get_tempdir ()->get_path (),
1914 invoke_driver (ctxt_progname
,
1915 get_tempdir ()->get_path_s_file (),
1918 false, /* bool shared, */
1919 false);/* bool run_linker */
1920 if (!errors_occurred ())
1921 copy_file (tmp_o_path
,
1927 case GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY
:
1928 invoke_driver (ctxt_progname
,
1929 get_tempdir ()->get_path_s_file (),
1930 get_tempdir ()->get_path_so_file (),
1932 true, /* bool shared, */
1933 true);/* bool run_linker */
1934 if (!errors_occurred ())
1935 copy_file (get_tempdir ()->get_path_so_file (),
1939 case GCC_JIT_OUTPUT_KIND_EXECUTABLE
:
1941 char *tmp_exe_path
= ::concat (get_tempdir ()->get_path (),
1944 invoke_driver (ctxt_progname
,
1945 get_tempdir ()->get_path_s_file (),
1948 false, /* bool shared, */
1949 true);/* bool run_linker */
1950 if (!errors_occurred ())
1951 copy_file (tmp_exe_path
,
1953 free (tmp_exe_path
);
1961 /* Copy SRC_PATH to DST_PATH, preserving permission bits (in particular,
1962 the "executable" bits).
1964 Any errors that occur are reported on the context and hence count as
1965 a failure of the compile.
1967 We can't in general hardlink or use "rename" from the tempdir since
1968 it might be on a different filesystem to the destination. For example,
1969 I get EXDEV: "Invalid cross-device link". */
1972 playback::compile_to_file::copy_file (const char *src_path
,
1973 const char *dst_path
)
1975 JIT_LOG_SCOPE (get_logger ());
1978 get_logger ()->log ("src_path: %s", src_path
);
1979 get_logger ()->log ("dst_path: %s", dst_path
);
1984 size_t total_sz_in
= 0;
1985 size_t total_sz_out
= 0;
1988 struct stat stat_buf
;
1990 f_in
= fopen (src_path
, "rb");
1994 "unable to open %s for reading: %s",
2000 /* Use stat on the filedescriptor to get the mode,
2001 so that we can copy it over (in particular, the
2002 "executable" bits). */
2003 if (-1 == fstat (fileno (f_in
), &stat_buf
))
2006 "unable to fstat %s: %s",
2013 f_out
= fopen (dst_path
, "wb");
2017 "unable to open %s for writing: %s",
2024 while ( (sz_in
= fread (buf
, 1, sizeof (buf
), f_in
)) )
2026 total_sz_in
+= sz_in
;
2027 size_t sz_out_remaining
= sz_in
;
2028 size_t sz_out_so_far
= 0;
2029 while (sz_out_remaining
)
2031 size_t sz_out
= fwrite (buf
+ sz_out_so_far
,
2035 gcc_assert (sz_out
<= sz_out_remaining
);
2039 "error writing to %s: %s",
2046 total_sz_out
+= sz_out
;
2047 sz_out_so_far
+= sz_out
;
2048 sz_out_remaining
-= sz_out
;
2050 gcc_assert (sz_out_so_far
== sz_in
);
2055 "error reading from %s: %s",
2061 gcc_assert (total_sz_in
== total_sz_out
);
2063 get_logger ()->log ("total bytes copied: %ld", total_sz_out
);
2065 /* Set the permissions of the copy to those of the original file,
2066 in particular the "executable" bits. */
2067 if (-1 == fchmod (fileno (f_out
), stat_buf
.st_mode
))
2069 "error setting mode of %s: %s",
2076 /* Helper functions for gcc::jit::playback::context::compile. */
2078 /* This mutex guards gcc::jit::recording::context::compile, so that only
2079 one thread can be accessing the bulk of GCC's state at once. */
2081 static pthread_mutex_t jit_mutex
= PTHREAD_MUTEX_INITIALIZER
;
2083 /* Acquire jit_mutex and set "this" as the active playback ctxt. */
2086 playback::context::acquire_mutex ()
2088 auto_timevar
tv (get_timer (), TV_JIT_ACQUIRING_MUTEX
);
2090 /* Acquire the big GCC mutex. */
2091 JIT_LOG_SCOPE (get_logger ());
2092 pthread_mutex_lock (&jit_mutex
);
2093 gcc_assert (NULL
== active_playback_ctxt
);
2094 active_playback_ctxt
= this;
2097 /* Release jit_mutex and clear the active playback ctxt. */
2100 playback::context::release_mutex ()
2102 /* Release the big GCC mutex. */
2103 JIT_LOG_SCOPE (get_logger ());
2104 gcc_assert (active_playback_ctxt
== this);
2105 active_playback_ctxt
= NULL
;
2106 pthread_mutex_unlock (&jit_mutex
);
2109 /* Callback used by gcc::jit::playback::context::make_fake_args when
2110 invoking driver_get_configure_time_options.
2111 Populate a vec <char * > with the configure-time options. */
2114 append_arg_from_driver (const char *option
, void *user_data
)
2116 gcc_assert (option
);
2117 gcc_assert (user_data
);
2118 vec
<char *> *argvec
= static_cast <vec
<char *> *> (user_data
);
2119 argvec
->safe_push (concat ("-", option
, NULL
));
2122 /* Build a fake argv for toplev::main from the options set
2123 by the user on the context . */
2127 make_fake_args (vec
<char *> *argvec
,
2128 const char *ctxt_progname
,
2129 vec
<recording::requested_dump
> *requested_dumps
)
2131 JIT_LOG_SCOPE (get_logger ());
2133 #define ADD_ARG(arg) argvec->safe_push (xstrdup (arg))
2134 #define ADD_ARG_TAKE_OWNERSHIP(arg) argvec->safe_push (arg)
2136 ADD_ARG (ctxt_progname
);
2137 ADD_ARG (get_path_c_file ());
2140 /* Handle int options: */
2141 switch (get_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL
))
2145 "unrecognized optimization level: %i",
2146 get_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL
));
2165 /* What about -Os? */
2167 /* Handle bool options: */
2168 if (get_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO
))
2171 /* Suppress timing (and other) info. */
2172 if (!get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_SUMMARY
))
2178 /* Aggressively garbage-collect, to shake out bugs: */
2179 if (get_bool_option (GCC_JIT_BOOL_OPTION_SELFCHECK_GC
))
2181 ADD_ARG ("--param");
2182 ADD_ARG ("ggc-min-expand=0");
2183 ADD_ARG ("--param");
2184 ADD_ARG ("ggc-min-heapsize=0");
2187 if (get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING
))
2189 ADD_ARG ("-fdump-tree-all");
2190 ADD_ARG ("-fdump-rtl-all");
2191 ADD_ARG ("-fdump-ipa-all");
2194 /* Add "-fdump-" options for any calls to
2195 gcc_jit_context_enable_dump. */
2198 recording::requested_dump
*d
;
2199 FOR_EACH_VEC_ELT (*requested_dumps
, i
, d
)
2201 char *arg
= concat ("-fdump-", d
->m_dumpname
, NULL
);
2202 ADD_ARG_TAKE_OWNERSHIP (arg
);
2206 /* PR jit/64810: Add any target-specific default options
2207 from OPTION_DEFAULT_SPECS, normally provided by the driver
2208 in the non-jit case.
2210 The target-specific code can define OPTION_DEFAULT_SPECS:
2211 default command options in the form of spec macros for the
2212 driver to expand ().
2214 For cc1 etc, the driver processes OPTION_DEFAULT_SPECS and,
2215 if not overriden, injects the defaults as extra arguments to
2217 For the jit case, we need to add these arguments here. The
2218 input format (using the specs language) means that we have to run
2219 part of the driver code here (driver_get_configure_time_options).
2221 To avoid running the spec-expansion code every time, we just do
2222 it the first time (via a function-static flag), saving the result
2223 into a function-static vec.
2224 This flag and vec are global state (i.e. per-process).
2225 They are guarded by the jit mutex. */
2227 static bool have_configure_time_options
= false;
2228 static vec
<char *> configure_time_options
;
2230 if (have_configure_time_options
)
2231 log ("reusing cached configure-time options");
2234 have_configure_time_options
= true;
2235 log ("getting configure-time options from driver");
2236 driver_get_configure_time_options (append_arg_from_driver
,
2237 &configure_time_options
);
2244 FOR_EACH_VEC_ELT (configure_time_options
, i
, opt
)
2245 log ("configure_time_options[%i]: %s", i
, opt
);
2247 /* configure_time_options should now contain the expanded options
2248 from OPTION_DEFAULT_SPECS (if any). */
2249 FOR_EACH_VEC_ELT (configure_time_options
, i
, opt
)
2252 gcc_assert (opt
[0] == '-');
2258 ADD_ARG ("-ftime-report");
2260 /* Add any user-provided extra options, starting with any from
2262 m_recording_ctxt
->append_command_line_options (argvec
);
2265 #undef ADD_ARG_TAKE_OWNERSHIP
2268 /* The second half of the implementation of gcc_jit_context_enable_dump.
2269 Iterate through the requested dumps, reading the underlying files
2270 into heap-allocated buffers, writing pointers to the buffers into
2271 the char ** pointers provided by client code.
2272 Client code is responsible for calling free on the results. */
2276 extract_any_requested_dumps (vec
<recording::requested_dump
> *requested_dumps
)
2278 JIT_LOG_SCOPE (get_logger ());
2281 recording::requested_dump
*d
;
2282 FOR_EACH_VEC_ELT (*requested_dumps
, i
, d
)
2284 dump_file_info
*dfi
;
2288 dfi
= g
->get_dumps ()->get_dump_file_info_by_switch (d
->m_dumpname
);
2291 add_error (NULL
, "unrecognized dump: %s", d
->m_dumpname
);
2295 filename
= g
->get_dumps ()->get_dump_file_name (dfi
);
2296 content
= read_dump_file (filename
);
2297 *(d
->m_out_ptr
) = content
;
2302 /* Helper function for playback::context::extract_any_requested_dumps
2303 (itself for use in implementation of gcc_jit_context_enable_dump).
2305 Attempt to read the complete file at the given path, returning the
2306 bytes found there as a buffer.
2307 The caller is responsible for calling free on the result.
2308 Errors will be reported on the context, and lead to NULL being
2309 returned; an out-of-memory error will terminate the process. */
2312 playback::context::read_dump_file (const char *path
)
2314 char *result
= NULL
;
2315 size_t total_sz
= 0;
2320 f_in
= fopen (path
, "r");
2323 add_error (NULL
, "unable to open %s for reading", path
);
2327 while ( (sz
= fread (buf
, 1, sizeof (buf
), f_in
)) )
2329 size_t old_total_sz
= total_sz
;
2331 result
= reinterpret_cast <char *> (xrealloc (result
, total_sz
+ 1));
2332 memcpy (result
+ old_total_sz
, buf
, sz
);
2337 add_error (NULL
, "error reading from %s", path
);
2347 result
[total_sz
] = '\0';
2351 return xstrdup ("");
2354 /* Part of playback::context::compile ().
2356 We have a .s file; we want a .so file.
2357 We could reuse parts of gcc/gcc.c to do this.
2358 For now, just use the driver binary from the install, as
2359 named in gcc-driver-name.h
2360 e.g. "x86_64-unknown-linux-gnu-gcc-5.0.0". */
2364 convert_to_dso (const char *ctxt_progname
)
2366 JIT_LOG_SCOPE (get_logger ());
2368 invoke_driver (ctxt_progname
,
2369 m_tempdir
->get_path_s_file (),
2370 m_tempdir
->get_path_so_file (),
2372 true, /* bool shared, */
2373 true);/* bool run_linker */
2376 static const char * const gcc_driver_name
= GCC_DRIVER_NAME
;
2380 invoke_driver (const char *ctxt_progname
,
2381 const char *input_file
,
2382 const char *output_file
,
2387 JIT_LOG_SCOPE (get_logger ());
2389 bool embedded_driver
2390 = !get_inner_bool_option (INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER
);
2392 /* Currently this lumps together both assembling and linking into
2394 auto_timevar
assemble_timevar (get_timer (), tv_id
);
2396 #define ADD_ARG(arg) argvec.safe_push (xstrdup (arg))
2398 ADD_ARG (gcc_driver_name
);
2400 add_multilib_driver_arguments (&argvec
);
2403 ADD_ARG ("-shared");
2408 ADD_ARG (input_file
);
2410 ADD_ARG (output_file
);
2412 /* Don't use the linker plugin.
2413 If running with just a "make" and not a "make install", then we'd
2415 "fatal error: -fuse-linker-plugin, but liblto_plugin.so not found"
2416 libto_plugin is a .la at build time, with it becoming installed with
2417 ".so" suffix: i.e. it doesn't exist with a .so suffix until install
2419 ADD_ARG ("-fno-use-linker-plugin");
2421 #if defined (DARWIN_X86) || defined (DARWIN_PPC)
2422 /* OS X's linker defaults to treating undefined symbols as errors.
2423 If the context has any imported functions or globals they will be
2424 undefined until the .so is dynamically-linked into the process.
2425 Ensure that the driver passes in "-undefined dynamic_lookup" to the
2427 ADD_ARG ("-Wl,-undefined,dynamic_lookup");
2435 /* pex_one's error-handling requires pname to be non-NULL. */
2436 gcc_assert (ctxt_progname
);
2439 for (unsigned i
= 0; i
< argvec
.length (); i
++)
2440 get_logger ()->log ("argv[%i]: %s", i
, argvec
[i
]);
2442 if (embedded_driver
)
2443 invoke_embedded_driver (&argvec
);
2445 invoke_external_driver (ctxt_progname
, &argvec
);
2450 invoke_embedded_driver (const vec
<char *> *argvec
)
2452 JIT_LOG_SCOPE (get_logger ());
2453 driver
d (true, /* can_finalize */
2455 int result
= d
.main (argvec
->length (),
2456 const_cast <char **> (argvec
->address ()));
2459 add_error (NULL
, "error invoking gcc driver");
2464 invoke_external_driver (const char *ctxt_progname
,
2465 vec
<char *> *argvec
)
2467 JIT_LOG_SCOPE (get_logger ());
2469 int exit_status
= 0;
2472 /* pex argv arrays are NULL-terminated. */
2473 argvec
->safe_push (NULL
);
2475 errmsg
= pex_one (PEX_SEARCH
, /* int flags, */
2477 const_cast <char *const *> (argvec
->address ()),
2478 ctxt_progname
, /* const char *pname */
2479 NULL
, /* const char *outname */
2480 NULL
, /* const char *errname */
2481 &exit_status
, /* int *status */
2482 &err
); /* int *err*/
2485 add_error (NULL
, "error invoking gcc driver: %s", errmsg
);
2489 /* pex_one can return a NULL errmsg when the executable wasn't
2490 found (or doesn't exist), so trap these cases also. */
2491 if (exit_status
|| err
)
2494 "error invoking gcc driver: exit_status: %i err: %i",
2497 "whilst attempting to run a driver named: %s",
2506 /* Extract the target-specific MULTILIB_DEFAULTS to
2507 multilib_defaults_raw for use by
2508 playback::context::add_multilib_driver_arguments (). */
2510 #ifndef MULTILIB_DEFAULTS
2511 #define MULTILIB_DEFAULTS { "" }
2514 static const char *const multilib_defaults_raw
[] = MULTILIB_DEFAULTS
;
2516 /* Helper function for playback::context::invoke_driver ().
2518 32-bit and 64-bit multilib peer builds of libgccjit.so may share
2519 a driver binary. We need to pass in options to the shared driver
2520 to get the appropriate assembler/linker options for this multilib
2525 add_multilib_driver_arguments (vec
<char *> *argvec
)
2527 JIT_LOG_SCOPE (get_logger ());
2529 /* Add copies of the arguments in multilib_defaults_raw to argvec,
2530 prepending each with a "-". */
2531 for (size_t i
= 0; i
< ARRAY_SIZE (multilib_defaults_raw
); i
++)
2532 if (multilib_defaults_raw
[i
][0])
2533 argvec
->safe_push (concat ("-", multilib_defaults_raw
[i
], NULL
));
2536 /* Dynamically-link the built DSO file into this process, using dlopen.
2537 Wrap it up within a jit::result *, and return that.
2538 Return NULL if any errors occur, reporting them on this context. */
2544 JIT_LOG_SCOPE (get_logger ());
2545 auto_timevar
load_timevar (get_timer (), TV_LOAD
);
2546 void *handle
= NULL
;
2547 const char *error
= NULL
;
2548 result
*result_obj
= NULL
;
2550 /* Clear any existing error. */
2553 handle
= dlopen (m_tempdir
->get_path_so_file (),
2554 RTLD_NOW
| RTLD_LOCAL
);
2555 if ((error
= dlerror()) != NULL
) {
2556 add_error (NULL
, "%s", error
);
2560 /* We've successfully dlopened the result; create a
2561 jit::result object to wrap it.
2563 We're done with the tempdir for now, but if the user
2564 has requested debugging, the user's debugger might not
2565 be capable of dealing with the .so file being unlinked
2566 immediately, so keep it around until after the result
2567 is released. We do this by handing over ownership of
2568 the jit::tempdir to the result. See PR jit/64206. */
2569 tempdir
*handover_tempdir
;
2570 if (get_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO
))
2572 handover_tempdir
= m_tempdir
;
2574 /* The tempdir will eventually be cleaned up in the
2575 jit::result's dtor. */
2576 log ("GCC_JIT_BOOL_OPTION_DEBUGINFO was set:"
2577 " handing over tempdir to jit::result");
2581 handover_tempdir
= NULL
;
2582 /* ... and retain ownership of m_tempdir so we clean it
2583 up it the playback::context's dtor. */
2584 log ("GCC_JIT_BOOL_OPTION_DEBUGINFO was not set:"
2585 " retaining ownership of tempdir");
2588 result_obj
= new result (get_logger (), handle
, handover_tempdir
);
2596 /* Top-level hook for playing back a recording context.
2598 This plays back m_recording_ctxt, and, if no errors
2599 occurred builds statement lists for and then postprocesses
2600 every function in the result. */
2606 JIT_LOG_SCOPE (get_logger ());
2607 /* Adapted from c-common.c:c_common_nodes_and_builtins. */
2608 tree array_domain_type
= build_index_type (size_int (200));
2609 m_char_array_type_node
2610 = build_array_type (char_type_node
, array_domain_type
);
2613 = build_pointer_type (build_qualified_type (char_type_node
,
2616 /* Replay the recorded events: */
2617 timevar_push (TV_JIT_REPLAY
);
2619 m_recording_ctxt
->replay_into (this);
2621 /* Clean away the temporary references from recording objects
2622 to playback objects. We have to do this now since the
2623 latter are GC-allocated, but the former don't mark these
2624 refs. Hence we must stop using them before the GC can run. */
2625 m_recording_ctxt
->disassociate_from_playback ();
2627 /* The builtins_manager, if any, is associated with the recording::context
2628 and might be reused for future compiles on other playback::contexts,
2629 but its m_attributes array is not GTY-labeled and hence will become
2630 nonsense if the GC runs. Purge this state. */
2631 builtins_manager
*bm
= get_builtins_manager ();
2633 bm
->finish_playback ();
2635 timevar_pop (TV_JIT_REPLAY
);
2637 if (!errors_occurred ())
2642 /* No GC can happen yet; process the cached source locations. */
2643 handle_locations ();
2645 /* We've now created tree nodes for the stmts in the various blocks
2646 in each function, but we haven't built each function's single stmt
2647 list yet. Do so now. */
2648 FOR_EACH_VEC_ELT (m_functions
, i
, func
)
2649 func
->build_stmt_list ();
2651 /* No GC can have happened yet. */
2653 /* Postprocess the functions. This could trigger GC. */
2654 FOR_EACH_VEC_ELT (m_functions
, i
, func
)
2657 func
->postprocess ();
2662 /* Dump the generated .s file to stderr. */
2666 dump_generated_code ()
2668 JIT_LOG_SCOPE (get_logger ());
2671 FILE *f_in
= fopen (get_path_s_file (), "r");
2675 while ( (sz
= fread (buf
, 1, sizeof (buf
), f_in
)) )
2676 fwrite (buf
, 1, sz
, stderr
);
2681 /* Get the supposed path of the notional "fake.c" file within the
2682 tempdir. This file doesn't exist, but the rest of the compiler
2687 get_path_c_file () const
2689 return m_tempdir
->get_path_c_file ();
2692 /* Get the path of the assembler output file "fake.s" file within the
2697 get_path_s_file () const
2699 return m_tempdir
->get_path_s_file ();
2702 /* Get the path of the DSO object file "fake.so" file within the
2707 get_path_so_file () const
2709 return m_tempdir
->get_path_so_file ();
2712 /* qsort comparator for comparing pairs of playback::source_line *,
2713 ordering them by line number. */
2716 line_comparator (const void *lhs
, const void *rhs
)
2718 const playback::source_line
*line_lhs
= \
2719 *static_cast<const playback::source_line
* const*> (lhs
);
2720 const playback::source_line
*line_rhs
= \
2721 *static_cast<const playback::source_line
* const*> (rhs
);
2722 return line_lhs
->get_line_num () - line_rhs
->get_line_num ();
2725 /* qsort comparator for comparing pairs of playback::location *,
2726 ordering them by column number. */
2729 location_comparator (const void *lhs
, const void *rhs
)
2731 const playback::location
*loc_lhs
= \
2732 *static_cast<const playback::location
* const *> (lhs
);
2733 const playback::location
*loc_rhs
= \
2734 *static_cast<const playback::location
* const *> (rhs
);
2735 return loc_lhs
->get_column_num () - loc_rhs
->get_column_num ();
2738 /* Our API allows locations to be created in arbitrary orders, but the
2739 linemap API requires locations to be created in ascending order
2740 as if we were tokenizing files.
2742 This hook sorts all of the locations that have been created, and
2743 calls into the linemap API, creating linemap entries in sorted order
2744 for our locations. */
2750 /* Create the source code locations, following the ordering rules
2751 imposed by the linemap API.
2753 line_table is a global. */
2754 JIT_LOG_SCOPE (get_logger ());
2758 FOR_EACH_VEC_ELT (m_source_files
, i
, file
)
2760 linemap_add (line_table
, LC_ENTER
, false, file
->get_filename (), 0);
2762 /* Sort lines by ascending line numbers. */
2763 file
->m_source_lines
.qsort (&line_comparator
);
2767 FOR_EACH_VEC_ELT (file
->m_source_lines
, j
, line
)
2772 /* Sort locations in line by ascending column numbers. */
2773 line
->m_locations
.qsort (&location_comparator
);
2775 /* Determine maximum column within this line. */
2776 gcc_assert (line
->m_locations
.length () > 0);
2777 location
*final_column
=
2778 line
->m_locations
[line
->m_locations
.length () - 1];
2779 int max_col
= final_column
->get_column_num ();
2781 linemap_line_start (line_table
, line
->get_line_num (), max_col
);
2782 FOR_EACH_VEC_ELT (line
->m_locations
, k
, loc
)
2785 linemap_position_for_column (line_table
, loc
->get_column_num ());
2789 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2792 /* line_table should now be populated; every playback::location should
2793 now have an m_srcloc. */
2795 /* Now assign them to tree nodes as appropriate. */
2796 std::pair
<tree
, location
*> *cached_location
;
2798 FOR_EACH_VEC_ELT (m_cached_locations
, i
, cached_location
)
2800 tree t
= cached_location
->first
;
2801 source_location srcloc
= cached_location
->second
->m_srcloc
;
2803 /* This covers expressions: */
2804 if (CAN_HAVE_LOCATION_P (t
))
2805 SET_EXPR_LOCATION (t
, srcloc
);
2806 else if (CODE_CONTAINS_STRUCT(TREE_CODE(t
), TS_DECL_MINIMAL
))
2807 DECL_SOURCE_LOCATION (t
) = srcloc
;
2810 /* Don't know how to set location on this node. */
2815 /* We handle errors on a playback::context by adding them to the
2816 corresponding recording::context. */
2820 add_error (location
*loc
, const char *fmt
, ...)
2824 m_recording_ctxt
->add_error_va (loc
? loc
->get_recording_loc () : NULL
,
2829 /* We handle errors on a playback::context by adding them to the
2830 corresponding recording::context. */
2834 add_error_va (location
*loc
, const char *fmt
, va_list ap
)
2836 m_recording_ctxt
->add_error_va (loc
? loc
->get_recording_loc () : NULL
,
2840 /* Dealing with the linemap API. */
2842 /* Construct a playback::location for a recording::location, if it
2843 doesn't exist already. */
2845 playback::location
*
2847 new_location (recording::location
*rloc
,
2848 const char *filename
,
2852 /* Get the source_file for filename, creating if necessary. */
2853 source_file
*src_file
= get_source_file (filename
);
2854 /* Likewise for the line within the file. */
2855 source_line
*src_line
= src_file
->get_source_line (line
);
2856 /* Likewise for the column within the line. */
2857 location
*loc
= src_line
->get_location (rloc
, column
);
2861 /* Deferred setting of the location for a given tree, by adding the
2862 (tree, playback::location) pair to a list of deferred associations.
2863 We will actually set the location on the tree later on once
2864 the source_location for the playback::location exists. */
2868 set_tree_location (tree t
, location
*loc
)
2871 m_cached_locations
.safe_push (std::make_pair (t
, loc
));
2875 /* Construct a playback::source_file for the given source
2876 filename, if it doesn't exist already. */
2878 playback::source_file
*
2880 get_source_file (const char *filename
)
2883 For simplicitly, this is currently a linear search.
2884 Replace with a hash if this shows up in the profile. */
2887 tree ident_filename
= get_identifier (filename
);
2889 FOR_EACH_VEC_ELT (m_source_files
, i
, file
)
2890 if (file
->filename_as_tree () == ident_filename
)
2894 file
= new source_file (ident_filename
);
2895 m_source_files
.safe_push (file
);
2899 /* Constructor for gcc::jit::playback::source_file. */
2901 playback::source_file::source_file (tree filename
) :
2903 m_filename (filename
)
2907 /* Don't leak vec's internal buffer (in non-GC heap) when we are
2911 playback::source_file::finalizer ()
2913 m_source_lines
.release ();
2916 /* Construct a playback::source_line for the given line
2917 within this source file, if one doesn't exist already. */
2919 playback::source_line
*
2920 playback::source_file::
2921 get_source_line (int line_num
)
2924 For simplicitly, this is currently a linear search.
2925 Replace with a hash if this shows up in the profile. */
2929 FOR_EACH_VEC_ELT (m_source_lines
, i
, line
)
2930 if (line
->get_line_num () == line_num
)
2934 line
= new source_line (this, line_num
);
2935 m_source_lines
.safe_push (line
);
2939 /* Constructor for gcc::jit::playback::source_line. */
2941 playback::source_line::source_line (source_file
*file
, int line_num
) :
2943 m_source_file (file
),
2944 m_line_num (line_num
)
2948 /* Don't leak vec's internal buffer (in non-GC heap) when we are
2952 playback::source_line::finalizer ()
2954 m_locations
.release ();
2957 /* Construct a playback::location for the given column
2958 within this line of a specific source file, if one doesn't exist
2961 playback::location
*
2962 playback::source_line::
2963 get_location (recording::location
*rloc
, int column_num
)
2968 /* Another linear search that probably should be a hash table. */
2969 FOR_EACH_VEC_ELT (m_locations
, i
, loc
)
2970 if (loc
->get_column_num () == column_num
)
2974 loc
= new location (rloc
, this, column_num
);
2975 m_locations
.safe_push (loc
);
2979 /* Constructor for gcc::jit::playback::location. */
2981 playback::location::location (recording::location
*loc
,
2984 m_srcloc (UNKNOWN_LOCATION
),
2985 m_recording_loc (loc
),
2987 m_column_num(column_num
)
2991 /* The active gcc::jit::playback::context instance. This is a singleton,
2992 guarded by jit_mutex. */
2994 playback::context
*active_playback_ctxt
;
2996 } // namespace gcc::jit