1 /* Internals of libgccjit: classes for playing back recorded API calls.
2 Copyright (C) 2013-2019 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 "stringpool.h"
32 #include "stor-layout.h"
33 #include "print-tree.h"
35 #include "gcc-driver-name.h"
38 #include "fold-const.h"
39 #include "opt-suggestions.h"
41 #include "diagnostic.h"
45 #include "jit-playback.h"
46 #include "jit-result.h"
47 #include "jit-builtins.h"
48 #include "jit-tempdir.h"
50 /* Compare with gcc/c-family/c-common.h: DECL_C_BIT_FIELD,
52 These are redefined here to avoid depending from the C frontend. */
53 #define DECL_JIT_BIT_FIELD(NODE) \
54 (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) == 1)
55 #define SET_DECL_JIT_BIT_FIELD(NODE) \
56 (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) = 1)
58 /* gcc::jit::playback::context::build_cast uses the convert.h API,
59 which in turn requires the frontend to provide a "convert"
60 function, apparently as a fallback.
62 Hence we provide this dummy one, with the requirement that any casts
63 are handled before reaching this. */
64 extern tree
convert (tree type
, tree expr
);
67 convert (tree dst_type
, tree expr
)
69 gcc_assert (gcc::jit::active_playback_ctxt
);
70 gcc::jit::active_playback_ctxt
->add_error (NULL
, "unhandled conversion");
71 fprintf (stderr
, "input expression:\n");
73 fprintf (stderr
, "requested type:\n");
74 debug_tree (dst_type
);
75 return error_mark_node
;
81 /**********************************************************************
83 **********************************************************************/
85 /* The constructor for gcc::jit::playback::context. */
87 playback::context::context (recording::context
*ctxt
)
88 : log_user (ctxt
->get_logger ()),
89 m_recording_ctxt (ctxt
),
91 m_char_array_type_node (NULL
),
92 m_const_char_ptr (NULL
)
94 JIT_LOG_SCOPE (get_logger ());
95 m_functions
.create (0);
97 m_source_files
.create (0);
98 m_cached_locations
.create (0);
101 /* The destructor for gcc::jit::playback::context. */
103 playback::context::~context ()
105 JIT_LOG_SCOPE (get_logger ());
107 /* Normally the playback::context is responsible for cleaning up the
108 tempdir (including "fake.so" within the filesystem).
110 In the normal case, clean it up now.
112 However m_tempdir can be NULL if the context has handed over
113 responsibility for the tempdir cleanup to the jit::result object, so
114 that the cleanup can be delayed (see PR jit/64206). If that's the
115 case this "delete NULL;" is a no-op. */
118 m_functions
.release ();
121 /* A playback::context can reference GC-managed pointers. Mark them
122 ("by hand", rather than by gengtype).
124 This is called on the active playback context (if any) by the
125 my_ggc_walker hook in the jit_root_table in dummy-frontend.c. */
133 FOR_EACH_VEC_ELT (m_functions
, i
, func
)
135 if (ggc_test_and_set_mark (func
))
140 /* Given an enum gcc_jit_types value, get a "tree" type. */
143 get_tree_node_for_type (enum gcc_jit_types type_
)
147 case GCC_JIT_TYPE_VOID
:
148 return void_type_node
;
150 case GCC_JIT_TYPE_VOID_PTR
:
151 return ptr_type_node
;
153 case GCC_JIT_TYPE_BOOL
:
154 return boolean_type_node
;
156 case GCC_JIT_TYPE_CHAR
:
157 return char_type_node
;
158 case GCC_JIT_TYPE_SIGNED_CHAR
:
159 return signed_char_type_node
;
160 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
161 return unsigned_char_type_node
;
163 case GCC_JIT_TYPE_SHORT
:
164 return short_integer_type_node
;
165 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
166 return short_unsigned_type_node
;
168 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
170 tree const_char
= build_qualified_type (char_type_node
,
172 return build_pointer_type (const_char
);
175 case GCC_JIT_TYPE_INT
:
176 return integer_type_node
;
177 case GCC_JIT_TYPE_UNSIGNED_INT
:
178 return unsigned_type_node
;
180 case GCC_JIT_TYPE_LONG
:
181 return long_integer_type_node
;
182 case GCC_JIT_TYPE_UNSIGNED_LONG
:
183 return long_unsigned_type_node
;
185 case GCC_JIT_TYPE_LONG_LONG
:
186 return long_long_integer_type_node
;
187 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
188 return long_long_unsigned_type_node
;
190 case GCC_JIT_TYPE_FLOAT
:
191 return float_type_node
;
192 case GCC_JIT_TYPE_DOUBLE
:
193 return double_type_node
;
194 case GCC_JIT_TYPE_LONG_DOUBLE
:
195 return long_double_type_node
;
197 case GCC_JIT_TYPE_SIZE_T
:
198 return size_type_node
;
200 case GCC_JIT_TYPE_FILE_PTR
:
201 return fileptr_type_node
;
203 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
204 return complex_float_type_node
;
205 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
206 return complex_double_type_node
;
207 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
208 return complex_long_double_type_node
;
214 /* Construct a playback::type instance (wrapping a tree) for the given
219 get_type (enum gcc_jit_types type_
)
221 tree type_node
= get_tree_node_for_type (type_
);
222 if (type_node
== NULL
)
224 add_error (NULL
, "unrecognized (enum gcc_jit_types) value: %i", type_
);
228 return new type (type_node
);
231 /* Construct a playback::type instance (wrapping a tree) for the given
236 new_array_type (playback::location
*loc
,
237 playback::type
*element_type
,
240 gcc_assert (element_type
);
242 tree t
= build_array_type_nelts (element_type
->as_tree (),
247 set_tree_location (t
, loc
);
252 /* Construct a playback::field instance (wrapping a tree). */
256 new_field (location
*loc
,
263 /* compare with c/c-decl.c:grokfield and grokdeclarator. */
264 tree decl
= build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
265 get_identifier (name
), type
->as_tree ());
268 set_tree_location (decl
, loc
);
270 return new field (decl
);
273 /* Construct a playback::bitfield instance (wrapping a tree). */
277 new_bitfield (location
*loc
,
286 /* compare with c/c-decl.c:grokfield, grokdeclarator and
287 check_bitfield_type_and_width. */
289 tree tree_type
= type
->as_tree ();
290 gcc_assert (INTEGRAL_TYPE_P (tree_type
));
291 tree tree_width
= build_int_cst (integer_type_node
, width
);
292 if (compare_tree_int (tree_width
, TYPE_PRECISION (tree_type
)) > 0)
296 "width of bit-field %s (width: %i) is wider than its type (width: %i)",
297 name
, width
, TYPE_PRECISION (tree_type
));
301 tree decl
= build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
302 get_identifier (name
), type
->as_tree ());
303 DECL_NONADDRESSABLE_P (decl
) = true;
304 DECL_INITIAL (decl
) = tree_width
;
305 SET_DECL_JIT_BIT_FIELD (decl
);
308 set_tree_location (decl
, loc
);
310 return new field (decl
);
313 /* Construct a playback::compound_type instance (wrapping a tree). */
315 playback::compound_type
*
317 new_compound_type (location
*loc
,
319 bool is_struct
) /* else is union */
323 /* Compare with c/c-decl.c: start_struct. */
325 tree t
= make_node (is_struct
? RECORD_TYPE
: UNION_TYPE
);
326 TYPE_NAME (t
) = get_identifier (name
);
330 set_tree_location (t
, loc
);
332 return new compound_type (t
);
336 playback::compound_type::set_fields (const auto_vec
<playback::field
*> *fields
)
338 /* Compare with c/c-decl.c: finish_struct. */
341 tree fieldlist
= NULL
;
342 for (unsigned i
= 0; i
< fields
->length (); i
++)
344 field
*f
= (*fields
)[i
];
345 tree x
= f
->as_tree ();
346 DECL_CONTEXT (x
) = t
;
347 if (DECL_JIT_BIT_FIELD (x
))
349 unsigned HOST_WIDE_INT width
= tree_to_uhwi (DECL_INITIAL (x
));
350 DECL_SIZE (x
) = bitsize_int (width
);
351 DECL_BIT_FIELD (x
) = 1;
353 fieldlist
= chainon (x
, fieldlist
);
355 fieldlist
= nreverse (fieldlist
);
356 TYPE_FIELDS (t
) = fieldlist
;
361 /* Construct a playback::type instance (wrapping a tree) for a function
366 new_function_type (type
*return_type
,
367 const auto_vec
<type
*> *param_types
,
373 tree
*arg_types
= (tree
*)xcalloc(param_types
->length (), sizeof(tree
*));
375 FOR_EACH_VEC_ELT (*param_types
, i
, param_type
)
376 arg_types
[i
] = param_type
->as_tree ();
381 build_varargs_function_type_array (return_type
->as_tree (),
382 param_types
->length (),
385 fn_type
= build_function_type_array (return_type
->as_tree (),
386 param_types
->length (),
390 return new type (fn_type
);
393 /* Construct a playback::param instance (wrapping a tree). */
397 new_param (location
*loc
,
403 tree inner
= build_decl (UNKNOWN_LOCATION
, PARM_DECL
,
404 get_identifier (name
), type
->as_tree ());
406 set_tree_location (inner
, loc
);
408 return new param (this, inner
);
411 /* Construct a playback::function instance. */
415 new_function (location
*loc
,
416 enum gcc_jit_function_kind kind
,
419 const auto_vec
<param
*> *params
,
421 enum built_in_function builtin_id
)
426 //can return_type be NULL?
429 tree
*arg_types
= (tree
*)xcalloc(params
->length (), sizeof(tree
*));
430 FOR_EACH_VEC_ELT (*params
, i
, param
)
431 arg_types
[i
] = TREE_TYPE (param
->as_tree ());
435 fn_type
= build_varargs_function_type_array (return_type
->as_tree (),
436 params
->length (), arg_types
);
438 fn_type
= build_function_type_array (return_type
->as_tree (),
439 params
->length (), arg_types
);
442 /* FIXME: this uses input_location: */
443 tree fndecl
= build_fn_decl (name
, fn_type
);
446 set_tree_location (fndecl
, loc
);
448 tree resdecl
= build_decl (UNKNOWN_LOCATION
, RESULT_DECL
,
449 NULL_TREE
, return_type
->as_tree ());
450 DECL_ARTIFICIAL (resdecl
) = 1;
451 DECL_IGNORED_P (resdecl
) = 1;
452 DECL_RESULT (fndecl
) = resdecl
;
456 gcc_assert (loc
== NULL
);
457 DECL_SOURCE_LOCATION (fndecl
) = BUILTINS_LOCATION
;
459 built_in_class fclass
= builtins_manager::get_class (builtin_id
);
460 set_decl_built_in_function (fndecl
, fclass
, builtin_id
);
461 set_builtin_decl (builtin_id
, fndecl
,
462 builtins_manager::implicit_p (builtin_id
));
464 builtins_manager
*bm
= get_builtins_manager ();
465 tree attrs
= bm
->get_attrs_tree (builtin_id
);
467 decl_attributes (&fndecl
, attrs
, ATTR_FLAG_BUILT_IN
);
469 decl_attributes (&fndecl
, NULL_TREE
, 0);
472 if (kind
!= GCC_JIT_FUNCTION_IMPORTED
)
474 tree param_decl_list
= NULL
;
475 FOR_EACH_VEC_ELT (*params
, i
, param
)
477 param_decl_list
= chainon (param
->as_tree (), param_decl_list
);
480 /* The param list was created in reverse order; fix it: */
481 param_decl_list
= nreverse (param_decl_list
);
484 for (t
= param_decl_list
; t
; t
= DECL_CHAIN (t
))
486 DECL_CONTEXT (t
) = fndecl
;
487 DECL_ARG_TYPE (t
) = TREE_TYPE (t
);
490 /* Set it up on DECL_ARGUMENTS */
491 DECL_ARGUMENTS(fndecl
) = param_decl_list
;
494 if (kind
== GCC_JIT_FUNCTION_ALWAYS_INLINE
)
496 DECL_DECLARED_INLINE_P (fndecl
) = 1;
498 /* Add attribute "always_inline": */
499 DECL_ATTRIBUTES (fndecl
) =
500 tree_cons (get_identifier ("always_inline"),
502 DECL_ATTRIBUTES (fndecl
));
505 function
*func
= new function (this, fndecl
, kind
);
506 m_functions
.safe_push (func
);
510 /* Construct a playback::lvalue instance (wrapping a tree). */
514 new_global (location
*loc
,
515 enum gcc_jit_global_kind kind
,
521 tree inner
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
522 get_identifier (name
),
524 TREE_PUBLIC (inner
) = (kind
!= GCC_JIT_GLOBAL_INTERNAL
);
525 DECL_COMMON (inner
) = 1;
531 case GCC_JIT_GLOBAL_EXPORTED
:
532 TREE_STATIC (inner
) = 1;
535 case GCC_JIT_GLOBAL_INTERNAL
:
536 TREE_STATIC (inner
) = 1;
539 case GCC_JIT_GLOBAL_IMPORTED
:
540 DECL_EXTERNAL (inner
) = 1;
545 set_tree_location (inner
, loc
);
547 varpool_node::get_create (inner
);
549 varpool_node::finalize_decl (inner
);
551 m_globals
.safe_push (inner
);
553 return new lvalue (this, inner
);
556 /* Implementation of the various
557 gcc::jit::playback::context::new_rvalue_from_const <HOST_TYPE>
559 Each of these constructs a playback::rvalue instance (wrapping a tree).
561 These specializations are required to be in the same namespace
562 as the template, hence we now have to enter the gcc::jit::playback
568 /* Specialization of making an rvalue from a const, for host <int>. */
573 new_rvalue_from_const
<int> (type
*type
,
576 // FIXME: type-checking, or coercion?
577 tree inner_type
= type
->as_tree ();
578 if (INTEGRAL_TYPE_P (inner_type
))
580 tree inner
= build_int_cst (inner_type
, value
);
581 return new rvalue (this, inner
);
585 REAL_VALUE_TYPE real_value
;
586 real_from_integer (&real_value
, VOIDmode
, value
, SIGNED
);
587 tree inner
= build_real (inner_type
, real_value
);
588 return new rvalue (this, inner
);
592 /* Specialization of making an rvalue from a const, for host <long>. */
597 new_rvalue_from_const
<long> (type
*type
,
600 // FIXME: type-checking, or coercion?
601 tree inner_type
= type
->as_tree ();
602 if (INTEGRAL_TYPE_P (inner_type
))
604 tree inner
= build_int_cst (inner_type
, value
);
605 return new rvalue (this, inner
);
609 REAL_VALUE_TYPE real_value
;
610 real_from_integer (&real_value
, VOIDmode
, value
, SIGNED
);
611 tree inner
= build_real (inner_type
, real_value
);
612 return new rvalue (this, inner
);
616 /* Specialization of making an rvalue from a const, for host <double>. */
621 new_rvalue_from_const
<double> (type
*type
,
624 // FIXME: type-checking, or coercion?
625 tree inner_type
= type
->as_tree ();
627 /* We have a "double", we want a REAL_VALUE_TYPE.
629 real.c:real_from_target appears to require the representation to be
630 split into 32-bit values, and then sent as an pair of host long
632 REAL_VALUE_TYPE real_value
;
636 uint32_t as_uint32s
[2];
639 long int as_long_ints
[2];
640 as_long_ints
[0] = u
.as_uint32s
[0];
641 as_long_ints
[1] = u
.as_uint32s
[1];
642 real_from_target (&real_value
, as_long_ints
, DFmode
);
643 tree inner
= build_real (inner_type
, real_value
);
644 return new rvalue (this, inner
);
647 /* Specialization of making an rvalue from a const, for host <void *>. */
652 new_rvalue_from_const
<void *> (type
*type
,
655 tree inner_type
= type
->as_tree ();
656 /* FIXME: how to ensure we have a wide enough type? */
657 tree inner
= build_int_cstu (inner_type
, (unsigned HOST_WIDE_INT
)value
);
658 return new rvalue (this, inner
);
661 /* We're done implementing the specializations of
662 gcc::jit::playback::context::new_rvalue_from_const <T>
663 so we can exit the gcc::jit::playback namespace. */
665 } // namespace playback
667 /* Construct a playback::rvalue instance (wrapping a tree). */
671 new_string_literal (const char *value
)
673 tree t_str
= build_string (strlen (value
), value
);
674 gcc_assert (m_char_array_type_node
);
675 TREE_TYPE (t_str
) = m_char_array_type_node
;
677 /* Convert to (const char*), loosely based on
678 c/c-typeck.c: array_to_pointer_conversion,
679 by taking address of start of string. */
680 tree t_addr
= build1 (ADDR_EXPR
, m_const_char_ptr
, t_str
);
682 return new rvalue (this, t_addr
);
685 /* Construct a playback::rvalue instance (wrapping a tree) for a
689 playback::context::new_rvalue_from_vector (location
*,
691 const auto_vec
<rvalue
*> &elements
)
693 vec
<constructor_elt
, va_gc
> *v
;
694 vec_alloc (v
, elements
.length ());
695 for (unsigned i
= 0; i
< elements
.length (); ++i
)
696 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, elements
[i
]->as_tree ());
697 tree t_ctor
= build_constructor (type
->as_tree (), v
);
698 return new rvalue (this, t_ctor
);
701 /* Coerce a tree expression into a boolean tree expression. */
705 as_truth_value (tree expr
, location
*loc
)
707 /* Compare to c-typeck.c:c_objc_common_truthvalue_conversion */
708 tree typed_zero
= fold_build1 (CONVERT_EXPR
,
712 set_tree_location (typed_zero
, loc
);
714 expr
= build2 (NE_EXPR
, integer_type_node
, expr
, typed_zero
);
716 set_tree_location (expr
, loc
);
721 /* Construct a playback::rvalue instance (wrapping a tree) for a
726 new_unary_op (location
*loc
,
727 enum gcc_jit_unary_op op
,
731 // FIXME: type-checking, or coercion?
732 enum tree_code inner_op
;
734 gcc_assert (result_type
);
737 tree node
= a
->as_tree ();
738 tree inner_result
= NULL
;
743 add_error (loc
, "unrecognized (enum gcc_jit_unary_op) value: %i", op
);
746 case GCC_JIT_UNARY_OP_MINUS
:
747 inner_op
= NEGATE_EXPR
;
750 case GCC_JIT_UNARY_OP_BITWISE_NEGATE
:
751 inner_op
= BIT_NOT_EXPR
;
754 case GCC_JIT_UNARY_OP_LOGICAL_NEGATE
:
755 node
= as_truth_value (node
, loc
);
756 inner_result
= invert_truthvalue (node
);
758 set_tree_location (inner_result
, loc
);
759 return new rvalue (this, inner_result
);
761 case GCC_JIT_UNARY_OP_ABS
:
766 inner_result
= build1 (inner_op
,
767 result_type
->as_tree (),
770 set_tree_location (inner_result
, loc
);
772 return new rvalue (this, inner_result
);
775 /* Construct a playback::rvalue instance (wrapping a tree) for a
780 new_binary_op (location
*loc
,
781 enum gcc_jit_binary_op op
,
783 rvalue
*a
, rvalue
*b
)
785 // FIXME: type-checking, or coercion?
786 enum tree_code inner_op
;
788 gcc_assert (result_type
);
792 tree node_a
= a
->as_tree ();
793 tree node_b
= b
->as_tree ();
798 add_error (loc
, "unrecognized (enum gcc_jit_binary_op) value: %i", op
);
801 case GCC_JIT_BINARY_OP_PLUS
:
802 inner_op
= PLUS_EXPR
;
805 case GCC_JIT_BINARY_OP_MINUS
:
806 inner_op
= MINUS_EXPR
;
809 case GCC_JIT_BINARY_OP_MULT
:
810 inner_op
= MULT_EXPR
;
813 case GCC_JIT_BINARY_OP_DIVIDE
:
814 if (FLOAT_TYPE_P (result_type
->as_tree ()))
815 /* Floating-point division: */
816 inner_op
= RDIV_EXPR
;
818 /* Truncating to zero: */
819 inner_op
= TRUNC_DIV_EXPR
;
822 case GCC_JIT_BINARY_OP_MODULO
:
823 inner_op
= TRUNC_MOD_EXPR
;
826 case GCC_JIT_BINARY_OP_BITWISE_AND
:
827 inner_op
= BIT_AND_EXPR
;
830 case GCC_JIT_BINARY_OP_BITWISE_XOR
:
831 inner_op
= BIT_XOR_EXPR
;
834 case GCC_JIT_BINARY_OP_BITWISE_OR
:
835 inner_op
= BIT_IOR_EXPR
;
838 case GCC_JIT_BINARY_OP_LOGICAL_AND
:
839 node_a
= as_truth_value (node_a
, loc
);
840 node_b
= as_truth_value (node_b
, loc
);
841 inner_op
= TRUTH_ANDIF_EXPR
;
844 case GCC_JIT_BINARY_OP_LOGICAL_OR
:
845 node_a
= as_truth_value (node_a
, loc
);
846 node_b
= as_truth_value (node_b
, loc
);
847 inner_op
= TRUTH_ORIF_EXPR
;
850 case GCC_JIT_BINARY_OP_LSHIFT
:
851 inner_op
= LSHIFT_EXPR
;
854 case GCC_JIT_BINARY_OP_RSHIFT
:
855 inner_op
= RSHIFT_EXPR
;
859 tree inner_expr
= build2 (inner_op
,
860 result_type
->as_tree (),
864 set_tree_location (inner_expr
, loc
);
866 return new rvalue (this, inner_expr
);
869 /* Construct a playback::rvalue instance (wrapping a tree) for a
874 new_comparison (location
*loc
,
875 enum gcc_jit_comparison op
,
876 rvalue
*a
, rvalue
*b
)
878 // FIXME: type-checking, or coercion?
879 enum tree_code inner_op
;
887 add_error (loc
, "unrecognized (enum gcc_jit_comparison) value: %i", op
);
890 case GCC_JIT_COMPARISON_EQ
:
893 case GCC_JIT_COMPARISON_NE
:
896 case GCC_JIT_COMPARISON_LT
:
899 case GCC_JIT_COMPARISON_LE
:
902 case GCC_JIT_COMPARISON_GT
:
905 case GCC_JIT_COMPARISON_GE
:
910 tree inner_expr
= build2 (inner_op
,
915 set_tree_location (inner_expr
, loc
);
916 return new rvalue (this, inner_expr
);
919 /* Construct a playback::rvalue instance (wrapping a tree) for a
924 build_call (location
*loc
,
926 const auto_vec
<rvalue
*> *args
,
927 bool require_tail_call
)
929 vec
<tree
, va_gc
> *tree_args
;
930 vec_alloc (tree_args
, args
->length ());
931 for (unsigned i
= 0; i
< args
->length (); i
++)
932 tree_args
->quick_push ((*args
)[i
]->as_tree ());
935 set_tree_location (fn_ptr
, loc
);
937 tree fn
= TREE_TYPE (fn_ptr
);
938 tree fn_type
= TREE_TYPE (fn
);
939 tree return_type
= TREE_TYPE (fn_type
);
941 tree call
= build_call_vec (return_type
,
944 if (require_tail_call
)
945 CALL_EXPR_MUST_TAIL_CALL (call
) = 1;
947 return new rvalue (this, call
);
949 /* see c-typeck.c: build_function_call
950 which calls build_function_call_vec
952 which does lots of checking, then:
953 result = build_call_array_loc (loc, TREE_TYPE (fntype),
954 function, nargs, argarray);
956 (see also build_call_vec)
960 /* Construct a playback::rvalue instance (wrapping a tree) for a
961 call to a specific function. */
965 new_call (location
*loc
,
967 const auto_vec
<rvalue
*> *args
,
968 bool require_tail_call
)
974 fndecl
= func
->as_fndecl ();
976 tree fntype
= TREE_TYPE (fndecl
);
978 tree fn
= build1 (ADDR_EXPR
, build_pointer_type (fntype
), fndecl
);
980 return build_call (loc
, fn
, args
, require_tail_call
);
983 /* Construct a playback::rvalue instance (wrapping a tree) for a
984 call through a function pointer. */
988 new_call_through_ptr (location
*loc
,
990 const auto_vec
<rvalue
*> *args
,
991 bool require_tail_call
)
994 tree t_fn_ptr
= fn_ptr
->as_tree ();
996 return build_call (loc
, t_fn_ptr
, args
, require_tail_call
);
999 /* Construct a tree for a cast. */
1002 playback::context::build_cast (playback::location
*loc
,
1003 playback::rvalue
*expr
,
1004 playback::type
*type_
)
1006 /* For comparison, see:
1007 - c/c-typeck.c:build_c_cast
1008 - c/c-convert.c: convert
1011 Only some kinds of cast are currently supported here. */
1012 tree t_expr
= expr
->as_tree ();
1013 tree t_dst_type
= type_
->as_tree ();
1015 t_ret
= targetm
.convert_to_type (t_dst_type
, t_expr
);
1018 enum tree_code dst_code
= TREE_CODE (t_dst_type
);
1023 t_ret
= convert_to_integer (t_dst_type
, t_expr
);
1027 /* Compare with c_objc_common_truthvalue_conversion and
1028 c_common_truthvalue_conversion. */
1029 /* For now, convert to: (t_expr != 0) */
1030 t_ret
= build2 (NE_EXPR
, t_dst_type
,
1032 build_int_cst (TREE_TYPE (t_expr
), 0));
1036 t_ret
= convert_to_real (t_dst_type
, t_expr
);
1040 t_ret
= build1 (NOP_EXPR
, t_dst_type
, t_expr
);
1044 add_error (loc
, "couldn't handle cast during playback");
1045 fprintf (stderr
, "input expression:\n");
1046 debug_tree (t_expr
);
1047 fprintf (stderr
, "requested type:\n");
1048 debug_tree (t_dst_type
);
1049 return error_mark_node
;
1052 if (TREE_CODE (t_ret
) != C_MAYBE_CONST_EXPR
)
1053 t_ret
= fold (t_ret
);
1058 /* Construct a playback::rvalue instance (wrapping a tree) for a
1063 new_cast (playback::location
*loc
,
1064 playback::rvalue
*expr
,
1065 playback::type
*type_
)
1068 tree t_cast
= build_cast (loc
, expr
, type_
);
1070 set_tree_location (t_cast
, loc
);
1071 return new rvalue (this, t_cast
);
1074 /* Construct a playback::lvalue instance (wrapping a tree) for an
1079 new_array_access (location
*loc
,
1086 /* For comparison, see:
1087 c/c-typeck.c: build_array_ref
1088 c-family/c-common.c: pointer_int_sum
1090 tree t_ptr
= ptr
->as_tree ();
1091 tree t_index
= index
->as_tree ();
1092 tree t_type_ptr
= TREE_TYPE (t_ptr
);
1093 tree t_type_star_ptr
= TREE_TYPE (t_type_ptr
);
1095 if (TREE_CODE (t_type_ptr
) == ARRAY_TYPE
)
1097 tree t_result
= build4 (ARRAY_REF
, t_type_star_ptr
, t_ptr
, t_index
,
1098 NULL_TREE
, NULL_TREE
);
1100 set_tree_location (t_result
, loc
);
1101 return new lvalue (this, t_result
);
1105 /* Convert index to an offset in bytes. */
1106 tree t_sizeof
= size_in_bytes (t_type_star_ptr
);
1107 t_index
= fold_build1 (CONVERT_EXPR
, sizetype
, t_index
);
1108 tree t_offset
= build2 (MULT_EXPR
, sizetype
, t_index
, t_sizeof
);
1110 /* Locate (ptr + offset). */
1111 tree t_address
= build2 (POINTER_PLUS_EXPR
, t_type_ptr
, t_ptr
, t_offset
);
1113 tree t_indirection
= build1 (INDIRECT_REF
, t_type_star_ptr
, t_address
);
1116 set_tree_location (t_sizeof
, loc
);
1117 set_tree_location (t_offset
, loc
);
1118 set_tree_location (t_address
, loc
);
1119 set_tree_location (t_indirection
, loc
);
1122 return new lvalue (this, t_indirection
);
1126 /* Construct a tree for a field access. */
1130 new_field_access (location
*loc
,
1137 /* Compare with c/c-typeck.c:lookup_field, build_indirect_ref, and
1138 build_component_ref. */
1139 tree type
= TREE_TYPE (datum
);
1141 gcc_assert (TREE_CODE (type
) != POINTER_TYPE
);
1143 tree t_field
= field
->as_tree ();
1144 tree ref
= build3 (COMPONENT_REF
, TREE_TYPE (t_field
), datum
,
1145 t_field
, NULL_TREE
);
1147 set_tree_location (ref
, loc
);
1151 /* Construct a tree for a dereference. */
1155 new_dereference (tree ptr
,
1160 tree type
= TREE_TYPE (TREE_TYPE(ptr
));
1161 tree datum
= build1 (INDIRECT_REF
, type
, ptr
);
1163 set_tree_location (datum
, loc
);
1167 /* Construct a playback::type instance (wrapping a tree)
1168 with the given alignment. */
1172 get_aligned (size_t alignment_in_bytes
) const
1174 tree t_new_type
= build_variant_type_copy (m_inner
);
1176 SET_TYPE_ALIGN (t_new_type
, alignment_in_bytes
* BITS_PER_UNIT
);
1177 TYPE_USER_ALIGN (t_new_type
) = 1;
1179 return new type (t_new_type
);
1182 /* Construct a playback::type instance (wrapping a tree)
1183 for the given vector type. */
1187 get_vector (size_t num_units
) const
1189 tree t_new_type
= build_vector_type (m_inner
, num_units
);
1190 return new type (t_new_type
);
1193 /* Construct a playback::lvalue instance (wrapping a tree) for a
1198 access_field (location
*loc
,
1201 tree datum
= as_tree ();
1202 tree ref
= get_context ()->new_field_access (loc
, datum
, field
);
1205 return new lvalue (get_context (), ref
);
1208 /* Construct a playback::rvalue instance (wrapping a tree) for a
1213 access_field (location
*loc
,
1216 tree datum
= as_tree ();
1217 tree ref
= get_context ()->new_field_access (loc
, datum
, field
);
1220 return new rvalue (get_context (), ref
);
1223 /* Construct a playback::lvalue instance (wrapping a tree) for a
1224 dereferenced field access. */
1228 dereference_field (location
*loc
,
1231 tree ptr
= as_tree ();
1232 tree datum
= get_context ()->new_dereference (ptr
, loc
);
1235 tree ref
= get_context ()->new_field_access (loc
, datum
, field
);
1238 return new lvalue (get_context (), ref
);
1241 /* Construct a playback::lvalue instance (wrapping a tree) for a
1246 dereference (location
*loc
)
1248 tree ptr
= as_tree ();
1249 tree datum
= get_context ()->new_dereference (ptr
, loc
);
1250 return new lvalue (get_context (), datum
);
1253 /* Mark the lvalue saying that we need to be able to take the
1254 address of it; it should not be allocated in a register.
1255 Compare with e.g. c/c-typeck.c: c_mark_addressable really_atomic_lvalue.
1256 Returns false if a failure occurred (an error will already have been
1257 added to the active context for this case). */
1261 mark_addressable (location
*loc
)
1263 tree x
= as_tree ();;
1266 switch (TREE_CODE (x
))
1269 if (DECL_JIT_BIT_FIELD (TREE_OPERAND (x
, 1)))
1271 gcc_assert (gcc::jit::active_playback_ctxt
);
1273 active_playback_ctxt
->add_error (loc
,
1274 "cannot take address of "
1283 x
= TREE_OPERAND (x
, 0);
1286 case COMPOUND_LITERAL_EXPR
:
1288 TREE_ADDRESSABLE (x
) = 1;
1295 /* (we don't have a concept of a "register" declaration) */
1298 TREE_ADDRESSABLE (x
) = 1;
1305 /* Construct a playback::rvalue instance (wrapping a tree) for an
1310 get_address (location
*loc
)
1312 tree t_lvalue
= as_tree ();
1313 tree t_thistype
= TREE_TYPE (t_lvalue
);
1314 tree t_ptrtype
= build_pointer_type (t_thistype
);
1315 tree ptr
= build1 (ADDR_EXPR
, t_ptrtype
, t_lvalue
);
1317 get_context ()->set_tree_location (ptr
, loc
);
1318 if (mark_addressable (loc
))
1319 return new rvalue (get_context (), ptr
);
1324 /* The wrapper subclasses are GC-managed, but can own non-GC memory.
1325 Provide this finalization hook for calling then they are collected,
1326 which calls the finalizer vfunc. This allows them to call "release"
1327 on any vec<> within them. */
1330 wrapper_finalizer (void *ptr
)
1332 playback::wrapper
*wrapper
= reinterpret_cast <playback::wrapper
*> (ptr
);
1333 wrapper
->finalizer ();
1336 /* gcc::jit::playback::wrapper subclasses are GC-managed:
1337 allocate them using ggc_internal_cleared_alloc. */
1341 operator new (size_t sz
)
1343 return ggc_internal_cleared_alloc (sz
, wrapper_finalizer
, 0, 1);
1347 /* Constructor for gcc:jit::playback::function. */
1349 playback::function::
1350 function (context
*ctxt
,
1352 enum gcc_jit_function_kind kind
)
1354 m_inner_fndecl (fndecl
),
1355 m_inner_bind_expr (NULL
),
1358 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
)
1360 /* Create a BIND_EXPR, and within it, a statement list. */
1361 m_stmt_list
= alloc_stmt_list ();
1362 m_stmt_iter
= tsi_start (m_stmt_list
);
1363 m_inner_block
= make_node (BLOCK
);
1365 build3 (BIND_EXPR
, void_type_node
, NULL
, m_stmt_list
, m_inner_block
);
1369 m_inner_block
= NULL
;
1374 /* Hand-written GC-marking hook for playback functions. */
1377 playback::function::
1380 gt_ggc_m_9tree_node (m_inner_fndecl
);
1381 gt_ggc_m_9tree_node (m_inner_bind_expr
);
1382 gt_ggc_m_9tree_node (m_stmt_list
);
1383 gt_ggc_m_9tree_node (m_inner_block
);
1386 /* Don't leak vec's internal buffer (in non-GC heap) when we are
1390 playback::function::finalizer ()
1392 m_blocks
.release ();
1395 /* Get the return type of a playback function, in tree form. */
1398 playback::function::
1399 get_return_type_as_tree () const
1401 return TREE_TYPE (TREE_TYPE(m_inner_fndecl
));
1404 /* Construct a new local within this playback::function. */
1407 playback::function::
1408 new_local (location
*loc
,
1414 tree inner
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
1415 get_identifier (name
),
1417 DECL_CONTEXT (inner
) = this->m_inner_fndecl
;
1419 /* Prepend to BIND_EXPR_VARS: */
1420 DECL_CHAIN (inner
) = BIND_EXPR_VARS (m_inner_bind_expr
);
1421 BIND_EXPR_VARS (m_inner_bind_expr
) = inner
;
1424 set_tree_location (inner
, loc
);
1425 return new lvalue (m_ctxt
, inner
);
1428 /* Construct a new block within this playback::function. */
1431 playback::function::
1432 new_block (const char *name
)
1434 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
1436 block
*result
= new playback::block (this, name
);
1437 m_blocks
.safe_push (result
);
1441 /* Construct a playback::rvalue instance wrapping an ADDR_EXPR for
1442 this playback::function. */
1445 playback::function::get_address (location
*loc
)
1447 tree t_fndecl
= as_fndecl ();
1448 tree t_fntype
= TREE_TYPE (t_fndecl
);
1449 tree t_fnptr
= build1 (ADDR_EXPR
, build_pointer_type (t_fntype
), t_fndecl
);
1451 m_ctxt
->set_tree_location (t_fnptr
, loc
);
1452 return new rvalue (m_ctxt
, t_fnptr
);
1455 /* Build a statement list for the function as a whole out of the
1456 lists of statements for the individual blocks, building labels
1460 playback::function::
1466 JIT_LOG_SCOPE (m_ctxt
->get_logger ());
1468 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
1473 b
->m_label_expr
= build1 (LABEL_EXPR
,
1475 b
->as_label_decl ());
1476 tsi_link_after (&m_stmt_iter
, b
->m_label_expr
, TSI_CONTINUE_LINKING
);
1478 FOR_EACH_VEC_ELT (b
->m_stmts
, j
, stmt
)
1479 tsi_link_after (&m_stmt_iter
, stmt
, TSI_CONTINUE_LINKING
);
1483 /* Finish compiling the given function, potentially running the
1485 The function will have a statement list by now.
1486 Amongst other things, this gimplifies the statement list,
1487 and calls cgraph_node::finalize_function on the function. */
1490 playback::function::
1493 JIT_LOG_SCOPE (m_ctxt
->get_logger ());
1495 if (m_ctxt
->get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE
))
1496 debug_tree (m_stmt_list
);
1498 /* Do we need this to force cgraphunit.c to output the function? */
1499 if (m_kind
== GCC_JIT_FUNCTION_EXPORTED
)
1501 DECL_EXTERNAL (m_inner_fndecl
) = 0;
1502 DECL_PRESERVE_P (m_inner_fndecl
) = 1;
1505 if (m_kind
== GCC_JIT_FUNCTION_INTERNAL
1506 ||m_kind
== GCC_JIT_FUNCTION_ALWAYS_INLINE
)
1508 DECL_EXTERNAL (m_inner_fndecl
) = 0;
1509 TREE_PUBLIC (m_inner_fndecl
) = 0;
1512 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
)
1514 /* Seem to need this in gimple-low.c: */
1515 gcc_assert (m_inner_block
);
1516 DECL_INITIAL (m_inner_fndecl
) = m_inner_block
;
1518 /* how to add to function? the following appears to be how to
1519 set the body of a m_inner_fndecl: */
1520 DECL_SAVED_TREE(m_inner_fndecl
) = m_inner_bind_expr
;
1522 /* Ensure that locals appear in the debuginfo. */
1523 BLOCK_VARS (m_inner_block
) = BIND_EXPR_VARS (m_inner_bind_expr
);
1525 //debug_tree (m_inner_fndecl);
1527 /* Convert to gimple: */
1528 //printf("about to gimplify_function_tree\n");
1529 gimplify_function_tree (m_inner_fndecl
);
1530 //printf("finished gimplify_function_tree\n");
1532 current_function_decl
= m_inner_fndecl
;
1533 if (m_ctxt
->get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE
))
1534 dump_function_to_file (m_inner_fndecl
, stderr
, TDF_VOPS
|TDF_MEMSYMS
|TDF_LINENO
);
1535 //debug_tree (m_inner_fndecl);
1537 //printf("about to add to cgraph\n");
1538 /* Add to cgraph: */
1539 cgraph_node::finalize_function (m_inner_fndecl
, false);
1540 /* This can trigger a collection, so we need to have all of
1541 the funcs as roots. */
1543 current_function_decl
= NULL
;
1547 /* Don't leak vec's internal buffer (in non-GC heap) when we are
1551 playback::block::finalizer ()
1556 /* Add an eval of the rvalue to the function's statement list. */
1560 add_eval (location
*loc
,
1563 gcc_assert (rvalue
);
1566 set_tree_location (rvalue
->as_tree (), loc
);
1568 add_stmt (rvalue
->as_tree ());
1571 /* Add an assignment to the function's statement list. */
1575 add_assignment (location
*loc
,
1579 gcc_assert (lvalue
);
1580 gcc_assert (rvalue
);
1582 tree t_lvalue
= lvalue
->as_tree ();
1583 tree t_rvalue
= rvalue
->as_tree ();
1584 if (TREE_TYPE (t_rvalue
) != TREE_TYPE (t_lvalue
))
1586 t_rvalue
= build1 (CONVERT_EXPR
,
1587 TREE_TYPE (t_lvalue
),
1590 set_tree_location (t_rvalue
, loc
);
1594 build2 (MODIFY_EXPR
, TREE_TYPE (t_lvalue
),
1595 t_lvalue
, t_rvalue
);
1597 set_tree_location (stmt
, loc
);
1601 /* Add a comment to the function's statement list.
1602 For now this is done by adding a dummy label. */
1606 add_comment (location
*loc
,
1609 /* Wrap the text in C-style comment delimiters. */
1611 (3 /* opening delim */
1613 + 3 /* closing delim */
1614 + 1 /* terminator */);
1615 char *wrapped
= (char *)ggc_internal_alloc (sz
);
1616 snprintf (wrapped
, sz
, "/* %s */", text
);
1618 /* For now we simply implement this by adding a dummy label with a name
1619 containing the given text. */
1620 tree identifier
= get_identifier (wrapped
);
1621 tree label_decl
= build_decl (UNKNOWN_LOCATION
, LABEL_DECL
,
1622 identifier
, void_type_node
);
1623 DECL_CONTEXT (label_decl
) = m_func
->as_fndecl ();
1625 tree label_expr
= build1 (LABEL_EXPR
, void_type_node
, label_decl
);
1627 set_tree_location (label_expr
, loc
);
1628 add_stmt (label_expr
);
1631 /* Add a conditional jump statement to the function's statement list. */
1635 add_conditional (location
*loc
,
1640 gcc_assert (boolval
);
1641 gcc_assert (on_true
);
1642 gcc_assert (on_false
);
1644 /* COND_EXPR wants statement lists for the true/false operands, but we
1646 Shim it by creating jumps to the labels */
1647 tree true_jump
= build1 (GOTO_EXPR
, void_type_node
,
1648 on_true
->as_label_decl ());
1650 set_tree_location (true_jump
, loc
);
1652 tree false_jump
= build1 (GOTO_EXPR
, void_type_node
,
1653 on_false
->as_label_decl ());
1655 set_tree_location (false_jump
, loc
);
1658 build3 (COND_EXPR
, void_type_node
, boolval
->as_tree (),
1659 true_jump
, false_jump
);
1661 set_tree_location (stmt
, loc
);
1665 /* Add an unconditional jump statement to the function's statement list. */
1669 add_jump (location
*loc
,
1672 gcc_assert (target
);
1674 // see c_finish_loop
1675 //tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
1678 //tree stmt = build_and_jump (&LABEL_EXPR_LABEL (target->label_));
1679 TREE_USED (target
->as_label_decl ()) = 1;
1680 tree stmt
= build1 (GOTO_EXPR
, void_type_node
, target
->as_label_decl ());
1682 set_tree_location (stmt
, loc
);
1688 c_finish_goto_label (location_t loc, tree label)
1690 tree decl = lookup_label_for_goto (loc, label);
1693 TREE_USED (decl) = 1;
1695 tree t = build1 (GOTO_EXPR, void_type_node, decl);
1696 SET_EXPR_LOCATION (t, loc);
1697 return add_stmt (t);
1704 /* Add a return statement to the function's statement list. */
1708 add_return (location
*loc
,
1711 tree modify_retval
= NULL
;
1712 tree return_type
= m_func
->get_return_type_as_tree ();
1715 tree t_lvalue
= DECL_RESULT (m_func
->as_fndecl ());
1716 tree t_rvalue
= rvalue
->as_tree ();
1717 if (TREE_TYPE (t_rvalue
) != TREE_TYPE (t_lvalue
))
1718 t_rvalue
= build1 (CONVERT_EXPR
,
1719 TREE_TYPE (t_lvalue
),
1721 modify_retval
= build2 (MODIFY_EXPR
, return_type
,
1722 t_lvalue
, t_rvalue
);
1724 set_tree_location (modify_retval
, loc
);
1726 tree return_stmt
= build1 (RETURN_EXPR
, return_type
,
1729 set_tree_location (return_stmt
, loc
);
1731 add_stmt (return_stmt
);
1734 /* Helper function for playback::block::add_switch.
1735 Construct a case label for the given range, followed by a goto stmt
1736 to the given block, appending them to stmt list *ptr_t_switch_body. */
1739 add_case (tree
*ptr_t_switch_body
,
1742 playback::block
*dest_block
)
1744 tree t_label
= create_artificial_label (UNKNOWN_LOCATION
);
1745 DECL_CONTEXT (t_label
) = dest_block
->get_function ()->as_fndecl ();
1748 build_case_label (t_low_value
, t_high_value
, t_label
);
1749 append_to_statement_list (t_case_label
, ptr_t_switch_body
);
1752 build1 (GOTO_EXPR
, void_type_node
, dest_block
->as_label_decl ());
1753 append_to_statement_list (t_goto_stmt
, ptr_t_switch_body
);
1756 /* Add a switch statement to the function's statement list.
1758 We create a switch body, and populate it with case labels, each
1759 followed by a goto to the desired block. */
1763 add_switch (location
*loc
,
1765 block
*default_block
,
1766 const auto_vec
<case_
> *cases
)
1769 - c/c-typeck.c: c_start_case
1770 - c-family/c-common.c:c_add_case_label
1771 - java/expr.c:expand_java_switch and expand_java_add_case
1772 We've already rejected overlaps and duplicates in
1773 libgccjit.c:case_range_validator::validate. */
1775 tree t_expr
= expr
->as_tree ();
1776 tree t_type
= TREE_TYPE (t_expr
);
1778 tree t_switch_body
= alloc_stmt_list ();
1782 FOR_EACH_VEC_ELT (*cases
, i
, c
)
1784 tree t_low_value
= c
->m_min_value
->as_tree ();
1785 tree t_high_value
= c
->m_max_value
->as_tree ();
1786 add_case (&t_switch_body
, t_low_value
, t_high_value
, c
->m_dest_block
);
1788 /* Default label. */
1789 add_case (&t_switch_body
, NULL_TREE
, NULL_TREE
, default_block
);
1791 tree switch_stmt
= build2 (SWITCH_EXPR
, t_type
, t_expr
, t_switch_body
);
1793 set_tree_location (switch_stmt
, loc
);
1794 add_stmt (switch_stmt
);
1797 /* Constructor for gcc::jit::playback::block. */
1800 block (function
*func
,
1810 identifier
= get_identifier (name
);
1813 m_label_decl
= build_decl (UNKNOWN_LOCATION
, LABEL_DECL
,
1814 identifier
, void_type_node
);
1815 DECL_CONTEXT (m_label_decl
) = func
->as_fndecl ();
1816 m_label_expr
= NULL
;
1819 /* Compile a playback::context:
1821 - Use the context's options to cconstruct command-line options, and
1822 call into the rest of GCC (toplev::main).
1823 - Assuming it succeeds, we have a .s file.
1824 - We then run the "postprocess" vfunc:
1826 (A) In-memory compile ("gcc_jit_context_compile")
1828 For an in-memory compile we have the playback::compile_to_memory
1829 subclass; "postprocess" will convert the .s file to a .so DSO,
1830 and load it in memory (via dlopen), wrapping the result up as
1831 a jit::result and returning it.
1833 (B) Compile to file ("gcc_jit_context_compile_to_file")
1835 When compiling to a file, we have the playback::compile_to_file
1836 subclass; "postprocess" will either copy the .s file to the
1837 destination (for GCC_JIT_OUTPUT_KIND_ASSEMBLER), or invoke
1838 the driver to convert it as necessary, copying the result. */
1844 JIT_LOG_SCOPE (get_logger ());
1846 const char *ctxt_progname
;
1848 int keep_intermediates
=
1849 get_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES
);
1851 m_tempdir
= new tempdir (get_logger (), keep_intermediates
);
1852 if (!m_tempdir
->create ())
1855 /* Call into the rest of gcc.
1856 For now, we have to assemble command-line options to pass into
1857 toplev::main, so that they can be parsed. */
1859 /* Pass in user-provided program name as argv0, if any, so that it
1860 makes it into GCC's "progname" global, used in various diagnostics. */
1861 ctxt_progname
= get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1864 ctxt_progname
= "libgccjit.so";
1866 auto_vec
<recording::requested_dump
> requested_dumps
;
1867 m_recording_ctxt
->get_all_requested_dumps (&requested_dumps
);
1869 /* Acquire the JIT mutex and set "this" as the active playback ctxt. */
1872 auto_string_vec fake_args
;
1873 make_fake_args (&fake_args
, ctxt_progname
, &requested_dumps
);
1874 if (errors_occurred ())
1880 /* This runs the compiler. */
1881 toplev
toplev (get_timer (), /* external_timer */
1882 false); /* init_signals */
1883 enter_scope ("toplev::main");
1885 for (unsigned i
= 0; i
< fake_args
.length (); i
++)
1886 get_logger ()->log ("argv[%i]: %s", i
, fake_args
[i
]);
1887 toplev
.main (fake_args
.length (),
1888 const_cast <char **> (fake_args
.address ()));
1889 exit_scope ("toplev::main");
1891 /* Extracting dumps makes use of the gcc::dump_manager, hence we
1892 need to do it between toplev::main (which creates the dump manager)
1893 and toplev::finalize (which deletes it). */
1894 extract_any_requested_dumps (&requested_dumps
);
1896 /* Clean up the compiler. */
1897 enter_scope ("toplev::finalize");
1899 exit_scope ("toplev::finalize");
1901 /* Ideally we would release the jit mutex here, but we can't yet since
1902 followup activities use timevars, which are global state. */
1904 if (errors_occurred ())
1910 if (get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE
))
1911 dump_generated_code ();
1913 /* We now have a .s file.
1915 Run any postprocessing steps. This will either convert the .s file to
1916 a .so DSO, and load it in memory (playback::compile_to_memory), or
1917 convert the .s file to the requested output format, and copy it to a
1918 given file (playback::compile_to_file). */
1919 postprocess (ctxt_progname
);
1924 /* Implementation of class gcc::jit::playback::compile_to_memory,
1925 a subclass of gcc::jit::playback::context. */
1927 /* playback::compile_to_memory's trivial constructor. */
1929 playback::compile_to_memory::compile_to_memory (recording::context
*ctxt
) :
1930 playback::context (ctxt
),
1933 JIT_LOG_SCOPE (get_logger ());
1936 /* Implementation of the playback::context::process vfunc for compiling
1939 Convert the .s file to a .so DSO, and load it in memory (via dlopen),
1940 wrapping the result up as a jit::result and returning it. */
1943 playback::compile_to_memory::postprocess (const char *ctxt_progname
)
1945 JIT_LOG_SCOPE (get_logger ());
1946 convert_to_dso (ctxt_progname
);
1947 if (errors_occurred ())
1949 m_result
= dlopen_built_dso ();
1952 /* Implementation of class gcc::jit::playback::compile_to_file,
1953 a subclass of gcc::jit::playback::context. */
1955 /* playback::compile_to_file's trivial constructor. */
1957 playback::compile_to_file::compile_to_file (recording::context
*ctxt
,
1958 enum gcc_jit_output_kind output_kind
,
1959 const char *output_path
) :
1960 playback::context (ctxt
),
1961 m_output_kind (output_kind
),
1962 m_output_path (output_path
)
1964 JIT_LOG_SCOPE (get_logger ());
1967 /* Implementation of the playback::context::process vfunc for compiling
1970 Either copy the .s file to the given destination (for
1971 GCC_JIT_OUTPUT_KIND_ASSEMBLER), or invoke the driver to convert it
1972 as necessary, copying the result. */
1975 playback::compile_to_file::postprocess (const char *ctxt_progname
)
1977 JIT_LOG_SCOPE (get_logger ());
1979 /* The driver takes different actions based on the filename, so
1980 we provide a filename with an appropriate suffix for the
1981 output kind, and then copy it up to the user-provided path,
1982 rather than directly compiling it to the requested output path. */
1984 switch (m_output_kind
)
1989 case GCC_JIT_OUTPUT_KIND_ASSEMBLER
:
1990 copy_file (get_tempdir ()->get_path_s_file (),
1992 /* The .s file is automatically unlinked by tempdir::~tempdir. */
1995 case GCC_JIT_OUTPUT_KIND_OBJECT_FILE
:
1997 char *tmp_o_path
= ::concat (get_tempdir ()->get_path (),
2000 invoke_driver (ctxt_progname
,
2001 get_tempdir ()->get_path_s_file (),
2004 false, /* bool shared, */
2005 false);/* bool run_linker */
2006 if (!errors_occurred ())
2008 copy_file (tmp_o_path
,
2010 get_tempdir ()->add_temp_file (tmp_o_path
);
2017 case GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY
:
2018 invoke_driver (ctxt_progname
,
2019 get_tempdir ()->get_path_s_file (),
2020 get_tempdir ()->get_path_so_file (),
2022 true, /* bool shared, */
2023 true);/* bool run_linker */
2024 if (!errors_occurred ())
2025 copy_file (get_tempdir ()->get_path_so_file (),
2027 /* The .so file is automatically unlinked by tempdir::~tempdir. */
2030 case GCC_JIT_OUTPUT_KIND_EXECUTABLE
:
2032 char *tmp_exe_path
= ::concat (get_tempdir ()->get_path (),
2035 invoke_driver (ctxt_progname
,
2036 get_tempdir ()->get_path_s_file (),
2039 false, /* bool shared, */
2040 true);/* bool run_linker */
2041 if (!errors_occurred ())
2043 copy_file (tmp_exe_path
,
2045 get_tempdir ()->add_temp_file (tmp_exe_path
);
2048 free (tmp_exe_path
);
2056 /* Copy SRC_PATH to DST_PATH, preserving permission bits (in particular,
2057 the "executable" bits).
2059 Any errors that occur are reported on the context and hence count as
2060 a failure of the compile.
2062 We can't in general hardlink or use "rename" from the tempdir since
2063 it might be on a different filesystem to the destination. For example,
2064 I get EXDEV: "Invalid cross-device link". */
2067 playback::compile_to_file::copy_file (const char *src_path
,
2068 const char *dst_path
)
2070 JIT_LOG_SCOPE (get_logger ());
2073 get_logger ()->log ("src_path: %s", src_path
);
2074 get_logger ()->log ("dst_path: %s", dst_path
);
2079 size_t total_sz_in
= 0;
2080 size_t total_sz_out
= 0;
2083 struct stat stat_buf
;
2085 f_in
= fopen (src_path
, "rb");
2089 "unable to open %s for reading: %s",
2095 /* Use stat on the filedescriptor to get the mode,
2096 so that we can copy it over (in particular, the
2097 "executable" bits). */
2098 if (fstat (fileno (f_in
), &stat_buf
) == -1)
2101 "unable to fstat %s: %s",
2108 f_out
= fopen (dst_path
, "wb");
2112 "unable to open %s for writing: %s",
2119 while ( (sz_in
= fread (buf
, 1, sizeof (buf
), f_in
)) )
2121 total_sz_in
+= sz_in
;
2122 size_t sz_out_remaining
= sz_in
;
2123 size_t sz_out_so_far
= 0;
2124 while (sz_out_remaining
)
2126 size_t sz_out
= fwrite (buf
+ sz_out_so_far
,
2130 gcc_assert (sz_out
<= sz_out_remaining
);
2134 "error writing to %s: %s",
2141 total_sz_out
+= sz_out
;
2142 sz_out_so_far
+= sz_out
;
2143 sz_out_remaining
-= sz_out
;
2145 gcc_assert (sz_out_so_far
== sz_in
);
2150 "error reading from %s: %s",
2156 gcc_assert (total_sz_in
== total_sz_out
);
2158 get_logger ()->log ("total bytes copied: %ld", total_sz_out
);
2160 /* Set the permissions of the copy to those of the original file,
2161 in particular the "executable" bits. */
2162 if (fchmod (fileno (f_out
), stat_buf
.st_mode
) == -1)
2164 "error setting mode of %s: %s",
2171 /* Helper functions for gcc::jit::playback::context::compile. */
2173 /* This mutex guards gcc::jit::recording::context::compile, so that only
2174 one thread can be accessing the bulk of GCC's state at once. */
2176 static pthread_mutex_t jit_mutex
= PTHREAD_MUTEX_INITIALIZER
;
2178 /* Acquire jit_mutex and set "this" as the active playback ctxt. */
2181 playback::context::acquire_mutex ()
2183 auto_timevar
tv (get_timer (), TV_JIT_ACQUIRING_MUTEX
);
2185 /* Acquire the big GCC mutex. */
2186 JIT_LOG_SCOPE (get_logger ());
2187 pthread_mutex_lock (&jit_mutex
);
2188 gcc_assert (active_playback_ctxt
== NULL
);
2189 active_playback_ctxt
= this;
2192 /* Release jit_mutex and clear the active playback ctxt. */
2195 playback::context::release_mutex ()
2197 /* Release the big GCC mutex. */
2198 JIT_LOG_SCOPE (get_logger ());
2199 gcc_assert (active_playback_ctxt
== this);
2200 active_playback_ctxt
= NULL
;
2201 pthread_mutex_unlock (&jit_mutex
);
2204 /* Callback used by gcc::jit::playback::context::make_fake_args when
2205 invoking driver_get_configure_time_options.
2206 Populate a vec <char * > with the configure-time options. */
2209 append_arg_from_driver (const char *option
, void *user_data
)
2211 gcc_assert (option
);
2212 gcc_assert (user_data
);
2213 vec
<char *> *argvec
= static_cast <vec
<char *> *> (user_data
);
2214 argvec
->safe_push (concat ("-", option
, NULL
));
2217 /* Build a fake argv for toplev::main from the options set
2218 by the user on the context . */
2222 make_fake_args (vec
<char *> *argvec
,
2223 const char *ctxt_progname
,
2224 vec
<recording::requested_dump
> *requested_dumps
)
2226 JIT_LOG_SCOPE (get_logger ());
2228 #define ADD_ARG(arg) argvec->safe_push (xstrdup (arg))
2229 #define ADD_ARG_TAKE_OWNERSHIP(arg) argvec->safe_push (arg)
2231 ADD_ARG (ctxt_progname
);
2232 ADD_ARG (get_path_c_file ());
2235 /* Handle int options: */
2236 switch (get_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL
))
2240 "unrecognized optimization level: %i",
2241 get_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL
));
2260 /* What about -Os? */
2262 /* Handle bool options: */
2263 if (get_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO
))
2266 /* Suppress timing (and other) info. */
2267 if (!get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_SUMMARY
))
2273 /* Aggressively garbage-collect, to shake out bugs: */
2274 if (get_bool_option (GCC_JIT_BOOL_OPTION_SELFCHECK_GC
))
2276 ADD_ARG ("--param=ggc-min-expand=0");
2277 ADD_ARG ("--param=ggc-min-heapsize=0");
2280 if (get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING
))
2282 ADD_ARG ("-fdump-tree-all");
2283 ADD_ARG ("-fdump-rtl-all");
2284 ADD_ARG ("-fdump-ipa-all");
2287 /* Add "-fdump-" options for any calls to
2288 gcc_jit_context_enable_dump. */
2291 recording::requested_dump
*d
;
2292 FOR_EACH_VEC_ELT (*requested_dumps
, i
, d
)
2294 char *arg
= concat ("-fdump-", d
->m_dumpname
, NULL
);
2295 ADD_ARG_TAKE_OWNERSHIP (arg
);
2299 /* PR jit/64810: Add any target-specific default options
2300 from OPTION_DEFAULT_SPECS, normally provided by the driver
2301 in the non-jit case.
2303 The target-specific code can define OPTION_DEFAULT_SPECS:
2304 default command options in the form of spec macros for the
2305 driver to expand ().
2307 For cc1 etc, the driver processes OPTION_DEFAULT_SPECS and,
2308 if not overriden, injects the defaults as extra arguments to
2310 For the jit case, we need to add these arguments here. The
2311 input format (using the specs language) means that we have to run
2312 part of the driver code here (driver_get_configure_time_options).
2314 To avoid running the spec-expansion code every time, we just do
2315 it the first time (via a function-static flag), saving the result
2316 into a function-static vec.
2317 This flag and vec are global state (i.e. per-process).
2318 They are guarded by the jit mutex. */
2320 static bool have_configure_time_options
= false;
2321 static vec
<char *> configure_time_options
;
2323 if (have_configure_time_options
)
2324 log ("reusing cached configure-time options");
2327 have_configure_time_options
= true;
2328 log ("getting configure-time options from driver");
2329 driver_get_configure_time_options (append_arg_from_driver
,
2330 &configure_time_options
);
2337 FOR_EACH_VEC_ELT (configure_time_options
, i
, opt
)
2338 log ("configure_time_options[%i]: %s", i
, opt
);
2340 /* configure_time_options should now contain the expanded options
2341 from OPTION_DEFAULT_SPECS (if any). */
2342 FOR_EACH_VEC_ELT (configure_time_options
, i
, opt
)
2345 gcc_assert (opt
[0] == '-');
2351 ADD_ARG ("-ftime-report");
2353 /* Add any user-provided extra options, starting with any from
2355 m_recording_ctxt
->append_command_line_options (argvec
);
2358 #undef ADD_ARG_TAKE_OWNERSHIP
2361 /* The second half of the implementation of gcc_jit_context_enable_dump.
2362 Iterate through the requested dumps, reading the underlying files
2363 into heap-allocated buffers, writing pointers to the buffers into
2364 the char ** pointers provided by client code.
2365 Client code is responsible for calling free on the results. */
2369 extract_any_requested_dumps (vec
<recording::requested_dump
> *requested_dumps
)
2371 JIT_LOG_SCOPE (get_logger ());
2374 recording::requested_dump
*d
;
2375 FOR_EACH_VEC_ELT (*requested_dumps
, i
, d
)
2377 dump_file_info
*dfi
;
2381 dfi
= g
->get_dumps ()->get_dump_file_info_by_switch (d
->m_dumpname
);
2384 add_error (NULL
, "unrecognized dump: %s", d
->m_dumpname
);
2388 filename
= g
->get_dumps ()->get_dump_file_name (dfi
);
2389 content
= read_dump_file (filename
);
2390 *(d
->m_out_ptr
) = content
;
2391 m_tempdir
->add_temp_file (filename
);
2395 /* Helper function for playback::context::extract_any_requested_dumps
2396 (itself for use in implementation of gcc_jit_context_enable_dump).
2398 Attempt to read the complete file at the given path, returning the
2399 bytes found there as a buffer.
2400 The caller is responsible for calling free on the result.
2401 Errors will be reported on the context, and lead to NULL being
2402 returned; an out-of-memory error will terminate the process. */
2405 playback::context::read_dump_file (const char *path
)
2407 char *result
= NULL
;
2408 size_t total_sz
= 0;
2413 f_in
= fopen (path
, "r");
2416 add_error (NULL
, "unable to open %s for reading", path
);
2420 while ( (sz
= fread (buf
, 1, sizeof (buf
), f_in
)) )
2422 size_t old_total_sz
= total_sz
;
2424 result
= reinterpret_cast <char *> (xrealloc (result
, total_sz
+ 1));
2425 memcpy (result
+ old_total_sz
, buf
, sz
);
2430 add_error (NULL
, "error reading from %s", path
);
2440 result
[total_sz
] = '\0';
2444 return xstrdup ("");
2447 /* Part of playback::context::compile ().
2449 We have a .s file; we want a .so file.
2450 We could reuse parts of gcc/gcc.c to do this.
2451 For now, just use the driver binary from the install, as
2452 named in gcc-driver-name.h
2453 e.g. "x86_64-unknown-linux-gnu-gcc-5.0.0". */
2457 convert_to_dso (const char *ctxt_progname
)
2459 JIT_LOG_SCOPE (get_logger ());
2461 invoke_driver (ctxt_progname
,
2462 m_tempdir
->get_path_s_file (),
2463 m_tempdir
->get_path_so_file (),
2465 true, /* bool shared, */
2466 true);/* bool run_linker */
2469 static const char * const gcc_driver_name
= GCC_DRIVER_NAME
;
2473 invoke_driver (const char *ctxt_progname
,
2474 const char *input_file
,
2475 const char *output_file
,
2480 JIT_LOG_SCOPE (get_logger ());
2482 bool embedded_driver
2483 = !get_inner_bool_option (INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER
);
2485 /* Currently this lumps together both assembling and linking into
2487 auto_timevar
assemble_timevar (get_timer (), tv_id
);
2488 auto_string_vec argvec
;
2489 #define ADD_ARG(arg) argvec.safe_push (xstrdup (arg))
2491 ADD_ARG (gcc_driver_name
);
2493 add_multilib_driver_arguments (&argvec
);
2496 ADD_ARG ("-shared");
2501 ADD_ARG (input_file
);
2503 ADD_ARG (output_file
);
2505 /* Don't use the linker plugin.
2506 If running with just a "make" and not a "make install", then we'd
2508 "fatal error: -fuse-linker-plugin, but liblto_plugin.so not found"
2509 libto_plugin is a .la at build time, with it becoming installed with
2510 ".so" suffix: i.e. it doesn't exist with a .so suffix until install
2512 ADD_ARG ("-fno-use-linker-plugin");
2514 #if defined (DARWIN_X86) || defined (DARWIN_PPC)
2515 /* OS X's linker defaults to treating undefined symbols as errors.
2516 If the context has any imported functions or globals they will be
2517 undefined until the .so is dynamically-linked into the process.
2518 Ensure that the driver passes in "-undefined dynamic_lookup" to the
2520 ADD_ARG ("-Wl,-undefined,dynamic_lookup");
2526 /* Add any user-provided driver extra options. */
2528 m_recording_ctxt
->append_driver_options (&argvec
);
2532 /* pex_one's error-handling requires pname to be non-NULL. */
2533 gcc_assert (ctxt_progname
);
2536 for (unsigned i
= 0; i
< argvec
.length (); i
++)
2537 get_logger ()->log ("argv[%i]: %s", i
, argvec
[i
]);
2539 if (embedded_driver
)
2540 invoke_embedded_driver (&argvec
);
2542 invoke_external_driver (ctxt_progname
, &argvec
);
2547 invoke_embedded_driver (const vec
<char *> *argvec
)
2549 JIT_LOG_SCOPE (get_logger ());
2550 driver
d (true, /* can_finalize */
2552 int result
= d
.main (argvec
->length (),
2553 const_cast <char **> (argvec
->address ()));
2556 add_error (NULL
, "error invoking gcc driver");
2561 invoke_external_driver (const char *ctxt_progname
,
2562 vec
<char *> *argvec
)
2564 JIT_LOG_SCOPE (get_logger ());
2566 int exit_status
= 0;
2569 /* pex argv arrays are NULL-terminated. */
2570 argvec
->safe_push (NULL
);
2572 errmsg
= pex_one (PEX_SEARCH
, /* int flags, */
2574 const_cast <char *const *> (argvec
->address ()),
2575 ctxt_progname
, /* const char *pname */
2576 NULL
, /* const char *outname */
2577 NULL
, /* const char *errname */
2578 &exit_status
, /* int *status */
2579 &err
); /* int *err*/
2582 add_error (NULL
, "error invoking gcc driver: %s", errmsg
);
2586 /* pex_one can return a NULL errmsg when the executable wasn't
2587 found (or doesn't exist), so trap these cases also. */
2588 if (exit_status
|| err
)
2591 "error invoking gcc driver: exit_status: %i err: %i",
2594 "whilst attempting to run a driver named: %s",
2603 /* Extract the target-specific MULTILIB_DEFAULTS to
2604 multilib_defaults_raw for use by
2605 playback::context::add_multilib_driver_arguments (). */
2607 #ifndef MULTILIB_DEFAULTS
2608 #define MULTILIB_DEFAULTS { "" }
2611 static const char *const multilib_defaults_raw
[] = MULTILIB_DEFAULTS
;
2613 /* Helper function for playback::context::invoke_driver ().
2615 32-bit and 64-bit multilib peer builds of libgccjit.so may share
2616 a driver binary. We need to pass in options to the shared driver
2617 to get the appropriate assembler/linker options for this multilib
2622 add_multilib_driver_arguments (vec
<char *> *argvec
)
2624 JIT_LOG_SCOPE (get_logger ());
2626 /* Add copies of the arguments in multilib_defaults_raw to argvec,
2627 prepending each with a "-". */
2628 for (size_t i
= 0; i
< ARRAY_SIZE (multilib_defaults_raw
); i
++)
2629 if (multilib_defaults_raw
[i
][0])
2630 argvec
->safe_push (concat ("-", multilib_defaults_raw
[i
], NULL
));
2633 /* Dynamically-link the built DSO file into this process, using dlopen.
2634 Wrap it up within a jit::result *, and return that.
2635 Return NULL if any errors occur, reporting them on this context. */
2641 JIT_LOG_SCOPE (get_logger ());
2642 auto_timevar
load_timevar (get_timer (), TV_LOAD
);
2643 void *handle
= NULL
;
2644 const char *error
= NULL
;
2645 result
*result_obj
= NULL
;
2647 /* Clear any existing error. */
2650 handle
= dlopen (m_tempdir
->get_path_so_file (),
2651 RTLD_NOW
| RTLD_LOCAL
);
2652 if ((error
= dlerror()) != NULL
) {
2653 add_error (NULL
, "%s", error
);
2657 /* We've successfully dlopened the result; create a
2658 jit::result object to wrap it.
2660 We're done with the tempdir for now, but if the user
2661 has requested debugging, the user's debugger might not
2662 be capable of dealing with the .so file being unlinked
2663 immediately, so keep it around until after the result
2664 is released. We do this by handing over ownership of
2665 the jit::tempdir to the result. See PR jit/64206. */
2666 tempdir
*handover_tempdir
;
2667 if (get_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO
))
2669 handover_tempdir
= m_tempdir
;
2671 /* The tempdir will eventually be cleaned up in the
2672 jit::result's dtor. */
2673 log ("GCC_JIT_BOOL_OPTION_DEBUGINFO was set:"
2674 " handing over tempdir to jit::result");
2678 handover_tempdir
= NULL
;
2679 /* ... and retain ownership of m_tempdir so we clean it
2680 up it the playback::context's dtor. */
2681 log ("GCC_JIT_BOOL_OPTION_DEBUGINFO was not set:"
2682 " retaining ownership of tempdir");
2685 result_obj
= new result (get_logger (), handle
, handover_tempdir
);
2693 /* Top-level hook for playing back a recording context.
2695 This plays back m_recording_ctxt, and, if no errors
2696 occurred builds statement lists for and then postprocesses
2697 every function in the result. */
2703 JIT_LOG_SCOPE (get_logger ());
2704 /* Adapted from c-common.c:c_common_nodes_and_builtins. */
2705 tree array_domain_type
= build_index_type (size_int (200));
2706 m_char_array_type_node
2707 = build_array_type (char_type_node
, array_domain_type
);
2710 = build_pointer_type (build_qualified_type (char_type_node
,
2713 /* Replay the recorded events: */
2714 timevar_push (TV_JIT_REPLAY
);
2716 m_recording_ctxt
->replay_into (this);
2718 /* Clean away the temporary references from recording objects
2719 to playback objects. We have to do this now since the
2720 latter are GC-allocated, but the former don't mark these
2721 refs. Hence we must stop using them before the GC can run. */
2722 m_recording_ctxt
->disassociate_from_playback ();
2724 /* The builtins_manager, if any, is associated with the recording::context
2725 and might be reused for future compiles on other playback::contexts,
2726 but its m_attributes array is not GTY-labeled and hence will become
2727 nonsense if the GC runs. Purge this state. */
2728 builtins_manager
*bm
= get_builtins_manager ();
2730 bm
->finish_playback ();
2732 timevar_pop (TV_JIT_REPLAY
);
2734 if (!errors_occurred ())
2739 /* No GC can happen yet; process the cached source locations. */
2740 handle_locations ();
2742 /* We've now created tree nodes for the stmts in the various blocks
2743 in each function, but we haven't built each function's single stmt
2744 list yet. Do so now. */
2745 FOR_EACH_VEC_ELT (m_functions
, i
, func
)
2746 func
->build_stmt_list ();
2748 /* No GC can have happened yet. */
2750 /* Postprocess the functions. This could trigger GC. */
2751 FOR_EACH_VEC_ELT (m_functions
, i
, func
)
2754 func
->postprocess ();
2759 /* Dump the generated .s file to stderr. */
2763 dump_generated_code ()
2765 JIT_LOG_SCOPE (get_logger ());
2768 FILE *f_in
= fopen (get_path_s_file (), "r");
2772 while ( (sz
= fread (buf
, 1, sizeof (buf
), f_in
)) )
2773 fwrite (buf
, 1, sz
, stderr
);
2778 /* Get the supposed path of the notional "fake.c" file within the
2779 tempdir. This file doesn't exist, but the rest of the compiler
2784 get_path_c_file () const
2786 return m_tempdir
->get_path_c_file ();
2789 /* Get the path of the assembler output file "fake.s" file within the
2794 get_path_s_file () const
2796 return m_tempdir
->get_path_s_file ();
2799 /* Get the path of the DSO object file "fake.so" file within the
2804 get_path_so_file () const
2806 return m_tempdir
->get_path_so_file ();
2809 /* qsort comparator for comparing pairs of playback::source_line *,
2810 ordering them by line number. */
2813 line_comparator (const void *lhs
, const void *rhs
)
2815 const playback::source_line
*line_lhs
= \
2816 *static_cast<const playback::source_line
* const*> (lhs
);
2817 const playback::source_line
*line_rhs
= \
2818 *static_cast<const playback::source_line
* const*> (rhs
);
2819 return line_lhs
->get_line_num () - line_rhs
->get_line_num ();
2822 /* qsort comparator for comparing pairs of playback::location *,
2823 ordering them by column number. */
2826 location_comparator (const void *lhs
, const void *rhs
)
2828 const playback::location
*loc_lhs
= \
2829 *static_cast<const playback::location
* const *> (lhs
);
2830 const playback::location
*loc_rhs
= \
2831 *static_cast<const playback::location
* const *> (rhs
);
2832 return loc_lhs
->get_column_num () - loc_rhs
->get_column_num ();
2835 /* Our API allows locations to be created in arbitrary orders, but the
2836 linemap API requires locations to be created in ascending order
2837 as if we were tokenizing files.
2839 This hook sorts all of the locations that have been created, and
2840 calls into the linemap API, creating linemap entries in sorted order
2841 for our locations. */
2847 /* Create the source code locations, following the ordering rules
2848 imposed by the linemap API.
2850 line_table is a global. */
2851 JIT_LOG_SCOPE (get_logger ());
2855 FOR_EACH_VEC_ELT (m_source_files
, i
, file
)
2857 linemap_add (line_table
, LC_ENTER
, false, file
->get_filename (), 0);
2859 /* Sort lines by ascending line numbers. */
2860 file
->m_source_lines
.qsort (&line_comparator
);
2864 FOR_EACH_VEC_ELT (file
->m_source_lines
, j
, line
)
2869 /* Sort locations in line by ascending column numbers. */
2870 line
->m_locations
.qsort (&location_comparator
);
2872 /* Determine maximum column within this line. */
2873 gcc_assert (line
->m_locations
.length () > 0);
2874 location
*final_column
=
2875 line
->m_locations
[line
->m_locations
.length () - 1];
2876 int max_col
= final_column
->get_column_num ();
2878 linemap_line_start (line_table
, line
->get_line_num (), max_col
);
2879 FOR_EACH_VEC_ELT (line
->m_locations
, k
, loc
)
2882 linemap_position_for_column (line_table
, loc
->get_column_num ());
2886 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2889 /* line_table should now be populated; every playback::location should
2890 now have an m_srcloc. */
2892 /* Now assign them to tree nodes as appropriate. */
2893 std::pair
<tree
, location
*> *cached_location
;
2895 FOR_EACH_VEC_ELT (m_cached_locations
, i
, cached_location
)
2897 tree t
= cached_location
->first
;
2898 location_t srcloc
= cached_location
->second
->m_srcloc
;
2900 /* This covers expressions: */
2901 if (CAN_HAVE_LOCATION_P (t
))
2902 SET_EXPR_LOCATION (t
, srcloc
);
2903 else if (CODE_CONTAINS_STRUCT(TREE_CODE(t
), TS_DECL_MINIMAL
))
2904 DECL_SOURCE_LOCATION (t
) = srcloc
;
2907 /* Don't know how to set location on this node. */
2912 /* We handle errors on a playback::context by adding them to the
2913 corresponding recording::context. */
2917 add_error (location
*loc
, const char *fmt
, ...)
2921 m_recording_ctxt
->add_error_va (loc
? loc
->get_recording_loc () : NULL
,
2926 /* We handle errors on a playback::context by adding them to the
2927 corresponding recording::context. */
2931 add_error_va (location
*loc
, const char *fmt
, va_list ap
)
2933 m_recording_ctxt
->add_error_va (loc
? loc
->get_recording_loc () : NULL
,
2937 /* Report a diagnostic up to the jit context as an error,
2938 so that the compilation is treated as a failure.
2939 For now, any kind of diagnostic is treated as an error by the jit
2944 add_diagnostic (struct diagnostic_context
*diag_context
,
2945 struct diagnostic_info
*diagnostic
)
2947 /* At this point the text has been formatted into the pretty-printer's
2949 pretty_printer
*pp
= diag_context
->printer
;
2950 const char *text
= pp_formatted_text (pp
);
2952 /* Get location information (if any) from the diagnostic.
2953 The recording::context::add_error[_va] methods require a
2954 recording::location. We can't lookup the playback::location
2955 from the file/line/column since any playback location instances
2956 may have been garbage-collected away by now, so instead we create
2957 another recording::location directly. */
2958 location_t gcc_loc
= diagnostic_location (diagnostic
);
2959 recording::location
*rec_loc
= NULL
;
2962 expanded_location exploc
= expand_location (gcc_loc
);
2964 rec_loc
= m_recording_ctxt
->new_location (exploc
.file
,
2970 m_recording_ctxt
->add_error (rec_loc
, "%s", text
);
2971 pp_clear_output_area (pp
);
2974 /* Dealing with the linemap API. */
2976 /* Construct a playback::location for a recording::location, if it
2977 doesn't exist already. */
2979 playback::location
*
2981 new_location (recording::location
*rloc
,
2982 const char *filename
,
2986 /* Get the source_file for filename, creating if necessary. */
2987 source_file
*src_file
= get_source_file (filename
);
2988 /* Likewise for the line within the file. */
2989 source_line
*src_line
= src_file
->get_source_line (line
);
2990 /* Likewise for the column within the line. */
2991 location
*loc
= src_line
->get_location (rloc
, column
);
2995 /* Deferred setting of the location for a given tree, by adding the
2996 (tree, playback::location) pair to a list of deferred associations.
2997 We will actually set the location on the tree later on once
2998 the location_t for the playback::location exists. */
3002 set_tree_location (tree t
, location
*loc
)
3005 m_cached_locations
.safe_push (std::make_pair (t
, loc
));
3009 /* Construct a playback::source_file for the given source
3010 filename, if it doesn't exist already. */
3012 playback::source_file
*
3014 get_source_file (const char *filename
)
3017 For simplicitly, this is currently a linear search.
3018 Replace with a hash if this shows up in the profile. */
3021 tree ident_filename
= get_identifier (filename
);
3023 FOR_EACH_VEC_ELT (m_source_files
, i
, file
)
3024 if (file
->filename_as_tree () == ident_filename
)
3028 file
= new source_file (ident_filename
);
3029 m_source_files
.safe_push (file
);
3033 /* Constructor for gcc::jit::playback::source_file. */
3035 playback::source_file::source_file (tree filename
) :
3037 m_filename (filename
)
3041 /* Don't leak vec's internal buffer (in non-GC heap) when we are
3045 playback::source_file::finalizer ()
3047 m_source_lines
.release ();
3050 /* Construct a playback::source_line for the given line
3051 within this source file, if one doesn't exist already. */
3053 playback::source_line
*
3054 playback::source_file::
3055 get_source_line (int line_num
)
3058 For simplicitly, this is currently a linear search.
3059 Replace with a hash if this shows up in the profile. */
3063 FOR_EACH_VEC_ELT (m_source_lines
, i
, line
)
3064 if (line
->get_line_num () == line_num
)
3068 line
= new source_line (this, line_num
);
3069 m_source_lines
.safe_push (line
);
3073 /* Constructor for gcc::jit::playback::source_line. */
3075 playback::source_line::source_line (source_file
*file
, int line_num
) :
3077 m_source_file (file
),
3078 m_line_num (line_num
)
3082 /* Don't leak vec's internal buffer (in non-GC heap) when we are
3086 playback::source_line::finalizer ()
3088 m_locations
.release ();
3091 /* Construct a playback::location for the given column
3092 within this line of a specific source file, if one doesn't exist
3095 playback::location
*
3096 playback::source_line::
3097 get_location (recording::location
*rloc
, int column_num
)
3102 /* Another linear search that probably should be a hash table. */
3103 FOR_EACH_VEC_ELT (m_locations
, i
, loc
)
3104 if (loc
->get_column_num () == column_num
)
3108 loc
= new location (rloc
, this, column_num
);
3109 m_locations
.safe_push (loc
);
3113 /* Constructor for gcc::jit::playback::location. */
3115 playback::location::location (recording::location
*loc
,
3118 m_srcloc (UNKNOWN_LOCATION
),
3119 m_recording_loc (loc
),
3121 m_column_num(column_num
)
3125 /* The active gcc::jit::playback::context instance. This is a singleton,
3126 guarded by jit_mutex. */
3128 playback::context
*active_playback_ctxt
;
3130 } // namespace gcc::jit