1 /* Internals of libgccjit: classes for playing back recorded API calls.
2 Copyright (C) 2013-2014 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"
28 #include "plugin-api.h"
34 #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"
50 #include "jit-common.h"
51 #include "jit-playback.h"
54 /* gcc::jit::playback::context::build_cast uses the convert.h API,
55 which in turn requires the frontend to provide a "convert"
56 function, apparently as a fallback.
58 Hence we provide this dummy one, with the requirement that any casts
59 are handled before reaching this. */
60 extern tree
convert (tree type
, tree expr
);
63 convert (tree dst_type
, tree expr
)
65 gcc_assert (gcc::jit::active_playback_ctxt
);
66 gcc::jit::active_playback_ctxt
->add_error (NULL
, "unhandled conversion");
67 fprintf (stderr
, "input expression:\n");
69 fprintf (stderr
, "requested type:\n");
70 debug_tree (dst_type
);
71 return error_mark_node
;
77 /**********************************************************************
79 **********************************************************************/
81 /* The constructor for gcc::jit::playback::context. */
83 playback::context::context (recording::context
*ctxt
)
84 : m_recording_ctxt (ctxt
),
85 m_char_array_type_node (NULL
),
86 m_const_char_ptr (NULL
)
88 m_functions
.create (0);
89 m_source_files
.create (0);
90 m_cached_locations
.create (0);
93 /* The destructor for gcc::jit::playback::context. */
95 playback::context::~context ()
97 if (get_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES
))
98 fprintf (stderr
, "intermediate files written to %s\n", m_path_tempdir
);
101 /* Clean up .s/.so and tempdir. */
103 unlink (m_path_s_file
);
105 unlink (m_path_so_file
);
107 rmdir (m_path_tempdir
);
110 free (m_path_template
);
111 /* m_path_tempdir aliases m_path_template, or is NULL, so don't
112 attempt to free it . */
113 free (m_path_c_file
);
114 free (m_path_s_file
);
115 free (m_path_so_file
);
116 m_functions
.release ();
119 /* A playback::context can reference GC-managed pointers. Mark them
120 ("by hand", rather than by gengtype).
122 This is called on the active playback context (if any) by the
123 my_ggc_walker hook in the jit_root_table in dummy-frontend.c. */
131 FOR_EACH_VEC_ELT (m_functions
, i
, func
)
133 if (ggc_test_and_set_mark (func
))
138 /* Given an enum gcc_jit_types value, get a "tree" type. */
141 get_tree_node_for_type (enum gcc_jit_types type_
)
145 case GCC_JIT_TYPE_VOID
:
146 return void_type_node
;
148 case GCC_JIT_TYPE_VOID_PTR
:
149 return ptr_type_node
;
151 case GCC_JIT_TYPE_BOOL
:
152 return boolean_type_node
;
154 case GCC_JIT_TYPE_CHAR
:
155 return char_type_node
;
156 case GCC_JIT_TYPE_SIGNED_CHAR
:
157 return signed_char_type_node
;
158 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
159 return unsigned_char_type_node
;
161 case GCC_JIT_TYPE_SHORT
:
162 return short_integer_type_node
;
163 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
164 return short_unsigned_type_node
;
166 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
168 tree const_char
= build_qualified_type (char_type_node
,
170 return build_pointer_type (const_char
);
173 case GCC_JIT_TYPE_INT
:
174 return integer_type_node
;
175 case GCC_JIT_TYPE_UNSIGNED_INT
:
176 return unsigned_type_node
;
178 case GCC_JIT_TYPE_LONG
:
179 return long_integer_type_node
;
180 case GCC_JIT_TYPE_UNSIGNED_LONG
:
181 return long_unsigned_type_node
;
183 case GCC_JIT_TYPE_LONG_LONG
:
184 return long_long_integer_type_node
;
185 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
186 return long_long_unsigned_type_node
;
188 case GCC_JIT_TYPE_FLOAT
:
189 return float_type_node
;
190 case GCC_JIT_TYPE_DOUBLE
:
191 return double_type_node
;
192 case GCC_JIT_TYPE_LONG_DOUBLE
:
193 return long_double_type_node
;
195 case GCC_JIT_TYPE_SIZE_T
:
196 return size_type_node
;
198 case GCC_JIT_TYPE_FILE_PTR
:
199 return fileptr_type_node
;
205 /* Construct a playback::type instance (wrapping a tree) for the given
210 get_type (enum gcc_jit_types type_
)
212 tree type_node
= get_tree_node_for_type (type_
);
213 if (NULL
== type_node
)
216 "unrecognized (enum gcc_jit_types) value: %i", type_
);
220 return new type (type_node
);
223 /* Construct a playback::type instance (wrapping a tree) for the given
228 new_array_type (playback::location
*loc
,
229 playback::type
*element_type
,
232 gcc_assert (element_type
);
234 tree t
= build_array_type_nelts (element_type
->as_tree (),
239 set_tree_location (t
, loc
);
244 /* Construct a playback::field instance (wrapping a tree). */
248 new_field (location
*loc
,
255 /* compare with c/c-decl.c:grokfield and grokdeclarator. */
256 tree decl
= build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
257 get_identifier (name
), type
->as_tree ());
260 set_tree_location (decl
, loc
);
262 return new field (decl
);
265 /* Construct a playback::compound_type instance (wrapping a tree). */
267 playback::compound_type
*
269 new_compound_type (location
*loc
,
271 bool is_struct
) /* else is union */
275 /* Compare with c/c-decl.c: start_struct. */
277 tree t
= make_node (is_struct
? RECORD_TYPE
: UNION_TYPE
);
278 TYPE_NAME (t
) = get_identifier (name
);
282 set_tree_location (t
, loc
);
284 return new compound_type (t
);
288 playback::compound_type::set_fields (const vec
<playback::field
*> &fields
)
290 /* Compare with c/c-decl.c: finish_struct. */
293 tree fieldlist
= NULL
;
294 for (unsigned i
= 0; i
< fields
.length (); i
++)
296 field
*f
= fields
[i
];
297 DECL_CONTEXT (f
->as_tree ()) = t
;
298 fieldlist
= chainon (f
->as_tree (), fieldlist
);
300 fieldlist
= nreverse (fieldlist
);
301 TYPE_FIELDS (t
) = fieldlist
;
306 /* Construct a playback::type instance (wrapping a tree) for a function
311 new_function_type (type
*return_type
,
312 vec
<type
*> *param_types
,
318 tree
*arg_types
= (tree
*)xcalloc(param_types
->length (), sizeof(tree
*));
320 FOR_EACH_VEC_ELT (*param_types
, i
, param_type
)
321 arg_types
[i
] = param_type
->as_tree ();
326 build_varargs_function_type_array (return_type
->as_tree (),
327 param_types
->length (),
330 fn_type
= build_function_type_array (return_type
->as_tree (),
331 param_types
->length (),
335 return new type (fn_type
);
338 /* Construct a playback::param instance (wrapping a tree). */
342 new_param (location
*loc
,
348 tree inner
= build_decl (UNKNOWN_LOCATION
, PARM_DECL
,
349 get_identifier (name
), type
->as_tree ());
351 set_tree_location (inner
, loc
);
353 return new param (this, inner
);
356 /* Construct a playback::function instance. */
360 new_function (location
*loc
,
361 enum gcc_jit_function_kind kind
,
364 vec
<param
*> *params
,
366 enum built_in_function builtin_id
)
371 //can return_type be NULL?
374 tree
*arg_types
= (tree
*)xcalloc(params
->length (), sizeof(tree
*));
375 FOR_EACH_VEC_ELT (*params
, i
, param
)
376 arg_types
[i
] = TREE_TYPE (param
->as_tree ());
380 fn_type
= build_varargs_function_type_array (return_type
->as_tree (),
381 params
->length (), arg_types
);
383 fn_type
= build_function_type_array (return_type
->as_tree (),
384 params
->length (), arg_types
);
387 /* FIXME: this uses input_location: */
388 tree fndecl
= build_fn_decl (name
, fn_type
);
391 set_tree_location (fndecl
, loc
);
393 tree resdecl
= build_decl (UNKNOWN_LOCATION
, RESULT_DECL
,
394 NULL_TREE
, return_type
->as_tree ());
395 DECL_ARTIFICIAL (resdecl
) = 1;
396 DECL_IGNORED_P (resdecl
) = 1;
397 DECL_RESULT (fndecl
) = resdecl
;
401 DECL_BUILT_IN_CLASS (fndecl
) = BUILT_IN_NORMAL
;
402 DECL_FUNCTION_CODE (fndecl
) = builtin_id
;
403 gcc_assert (loc
== NULL
);
404 DECL_SOURCE_LOCATION (fndecl
) = BUILTINS_LOCATION
;
407 if (kind
!= GCC_JIT_FUNCTION_IMPORTED
)
409 tree param_decl_list
= NULL
;
410 FOR_EACH_VEC_ELT (*params
, i
, param
)
412 param_decl_list
= chainon (param
->as_tree (), param_decl_list
);
415 /* The param list was created in reverse order; fix it: */
416 param_decl_list
= nreverse (param_decl_list
);
419 for (t
= param_decl_list
; t
; t
= DECL_CHAIN (t
))
421 DECL_CONTEXT (t
) = fndecl
;
422 DECL_ARG_TYPE (t
) = TREE_TYPE (t
);
425 /* Set it up on DECL_ARGUMENTS */
426 DECL_ARGUMENTS(fndecl
) = param_decl_list
;
429 if (kind
== GCC_JIT_FUNCTION_ALWAYS_INLINE
)
431 DECL_DECLARED_INLINE_P (fndecl
) = 1;
433 /* Add attribute "always_inline": */
434 DECL_ATTRIBUTES (fndecl
) =
435 tree_cons (get_identifier ("always_inline"),
437 DECL_ATTRIBUTES (fndecl
));
440 function
*func
= new function (this, fndecl
, kind
);
441 m_functions
.safe_push (func
);
445 /* Construct a playback::lvalue instance (wrapping a tree). */
449 new_global (location
*loc
,
455 tree inner
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
456 get_identifier (name
),
458 TREE_PUBLIC (inner
) = 1;
459 DECL_COMMON (inner
) = 1;
460 DECL_EXTERNAL (inner
) = 1;
463 set_tree_location (inner
, loc
);
465 return new lvalue (this, inner
);
468 /* Construct a playback::rvalue instance (wrapping a tree). */
472 new_rvalue_from_int (type
*type
,
475 // FIXME: type-checking, or coercion?
476 tree inner_type
= type
->as_tree ();
477 if (INTEGRAL_TYPE_P (inner_type
))
479 tree inner
= build_int_cst (inner_type
, value
);
480 return new rvalue (this, inner
);
484 REAL_VALUE_TYPE real_value
;
485 real_from_integer (&real_value
, VOIDmode
, value
, SIGNED
);
486 tree inner
= build_real (inner_type
, real_value
);
487 return new rvalue (this, inner
);
491 /* Construct a playback::rvalue instance (wrapping a tree). */
495 new_rvalue_from_double (type
*type
,
498 // FIXME: type-checking, or coercion?
499 tree inner_type
= type
->as_tree ();
501 /* We have a "double", we want a REAL_VALUE_TYPE.
503 real.c:real_from_target appears to require the representation to be
504 split into 32-bit values, and then sent as an pair of host long
506 REAL_VALUE_TYPE real_value
;
510 uint32_t as_uint32s
[2];
513 long int as_long_ints
[2];
514 as_long_ints
[0] = u
.as_uint32s
[0];
515 as_long_ints
[1] = u
.as_uint32s
[1];
516 real_from_target (&real_value
, as_long_ints
, DFmode
);
517 tree inner
= build_real (inner_type
, real_value
);
518 return new rvalue (this, inner
);
521 /* Construct a playback::rvalue instance (wrapping a tree). */
525 new_rvalue_from_ptr (type
*type
,
528 tree inner_type
= type
->as_tree ();
529 /* FIXME: how to ensure we have a wide enough type? */
530 tree inner
= build_int_cstu (inner_type
, (unsigned HOST_WIDE_INT
)value
);
531 return new rvalue (this, inner
);
534 /* Construct a playback::rvalue instance (wrapping a tree). */
538 new_string_literal (const char *value
)
540 tree t_str
= build_string (strlen (value
), value
);
541 gcc_assert (m_char_array_type_node
);
542 TREE_TYPE (t_str
) = m_char_array_type_node
;
544 /* Convert to (const char*), loosely based on
545 c/c-typeck.c: array_to_pointer_conversion,
546 by taking address of start of string. */
547 tree t_addr
= build1 (ADDR_EXPR
, m_const_char_ptr
, t_str
);
549 return new rvalue (this, t_addr
);
552 /* Coerce a tree expression into a boolean tree expression. */
556 as_truth_value (tree expr
, location
*loc
)
558 /* Compare to c-typeck.c:c_objc_common_truthvalue_conversion */
559 tree typed_zero
= fold_build1 (CONVERT_EXPR
,
563 set_tree_location (typed_zero
, loc
);
565 expr
= build2 (NE_EXPR
, integer_type_node
, expr
, typed_zero
);
567 set_tree_location (expr
, loc
);
572 /* Construct a playback::rvalue instance (wrapping a tree) for a
577 new_unary_op (location
*loc
,
578 enum gcc_jit_unary_op op
,
582 // FIXME: type-checking, or coercion?
583 enum tree_code inner_op
;
585 gcc_assert (result_type
);
588 tree node
= a
->as_tree ();
589 tree inner_result
= NULL
;
594 add_error (loc
, "unrecognized (enum gcc_jit_unary_op) value: %i", op
);
597 case GCC_JIT_UNARY_OP_MINUS
:
598 inner_op
= NEGATE_EXPR
;
601 case GCC_JIT_UNARY_OP_BITWISE_NEGATE
:
602 inner_op
= BIT_NOT_EXPR
;
605 case GCC_JIT_UNARY_OP_LOGICAL_NEGATE
:
606 node
= as_truth_value (node
, loc
);
607 inner_result
= invert_truthvalue (node
);
609 set_tree_location (inner_result
, loc
);
610 return new rvalue (this, inner_result
);
613 inner_result
= build1 (inner_op
,
614 result_type
->as_tree (),
617 set_tree_location (inner_result
, loc
);
619 return new rvalue (this, inner_result
);
622 /* Construct a playback::rvalue instance (wrapping a tree) for a
627 new_binary_op (location
*loc
,
628 enum gcc_jit_binary_op op
,
630 rvalue
*a
, rvalue
*b
)
632 // FIXME: type-checking, or coercion?
633 enum tree_code inner_op
;
635 gcc_assert (result_type
);
639 tree node_a
= a
->as_tree ();
640 tree node_b
= b
->as_tree ();
645 add_error (loc
, "unrecognized (enum gcc_jit_binary_op) value: %i", op
);
648 case GCC_JIT_BINARY_OP_PLUS
:
649 inner_op
= PLUS_EXPR
;
652 case GCC_JIT_BINARY_OP_MINUS
:
653 inner_op
= MINUS_EXPR
;
656 case GCC_JIT_BINARY_OP_MULT
:
657 inner_op
= MULT_EXPR
;
660 case GCC_JIT_BINARY_OP_DIVIDE
:
661 if (FLOAT_TYPE_P (result_type
->as_tree ()))
662 /* Floating-point division: */
663 inner_op
= RDIV_EXPR
;
665 /* Truncating to zero: */
666 inner_op
= TRUNC_DIV_EXPR
;
669 case GCC_JIT_BINARY_OP_MODULO
:
670 inner_op
= TRUNC_MOD_EXPR
;
673 case GCC_JIT_BINARY_OP_BITWISE_AND
:
674 inner_op
= BIT_AND_EXPR
;
677 case GCC_JIT_BINARY_OP_BITWISE_XOR
:
678 inner_op
= BIT_XOR_EXPR
;
681 case GCC_JIT_BINARY_OP_BITWISE_OR
:
682 inner_op
= BIT_IOR_EXPR
;
685 case GCC_JIT_BINARY_OP_LOGICAL_AND
:
686 node_a
= as_truth_value (node_a
, loc
);
687 node_b
= as_truth_value (node_b
, loc
);
688 inner_op
= TRUTH_ANDIF_EXPR
;
691 case GCC_JIT_BINARY_OP_LOGICAL_OR
:
692 node_a
= as_truth_value (node_a
, loc
);
693 node_b
= as_truth_value (node_b
, loc
);
694 inner_op
= TRUTH_ORIF_EXPR
;
697 case GCC_JIT_BINARY_OP_LSHIFT
:
698 inner_op
= LSHIFT_EXPR
;
701 case GCC_JIT_BINARY_OP_RSHIFT
:
702 inner_op
= RSHIFT_EXPR
;
706 tree inner_expr
= build2 (inner_op
,
707 result_type
->as_tree (),
711 set_tree_location (inner_expr
, loc
);
713 return new rvalue (this, inner_expr
);
716 /* Construct a playback::rvalue instance (wrapping a tree) for a
721 new_comparison (location
*loc
,
722 enum gcc_jit_comparison op
,
723 rvalue
*a
, rvalue
*b
)
725 // FIXME: type-checking, or coercion?
726 enum tree_code inner_op
;
734 add_error (loc
, "unrecognized (enum gcc_jit_comparison) value: %i", op
);
737 case GCC_JIT_COMPARISON_EQ
:
740 case GCC_JIT_COMPARISON_NE
:
743 case GCC_JIT_COMPARISON_LT
:
746 case GCC_JIT_COMPARISON_LE
:
749 case GCC_JIT_COMPARISON_GT
:
752 case GCC_JIT_COMPARISON_GE
:
757 tree inner_expr
= build2 (inner_op
,
762 set_tree_location (inner_expr
, loc
);
763 return new rvalue (this, inner_expr
);
766 /* Construct a playback::rvalue instance (wrapping a tree) for a
771 build_call (location
*loc
,
775 vec
<tree
, va_gc
> *tree_args
;
776 vec_alloc (tree_args
, args
.length ());
777 for (unsigned i
= 0; i
< args
.length (); i
++)
778 tree_args
->quick_push (args
[i
]->as_tree ());
781 set_tree_location (fn_ptr
, loc
);
783 tree fn
= TREE_TYPE (fn_ptr
);
784 tree fn_type
= TREE_TYPE (fn
);
785 tree return_type
= TREE_TYPE (fn_type
);
787 return new rvalue (this,
788 build_call_vec (return_type
,
791 /* see c-typeck.c: build_function_call
792 which calls build_function_call_vec
794 which does lots of checking, then:
795 result = build_call_array_loc (loc, TREE_TYPE (fntype),
796 function, nargs, argarray);
798 (see also build_call_vec)
802 /* Construct a playback::rvalue instance (wrapping a tree) for a
803 call to a specific function. */
807 new_call (location
*loc
,
815 fndecl
= func
->as_fndecl ();
817 tree fntype
= TREE_TYPE (fndecl
);
819 tree fn
= build1 (ADDR_EXPR
, build_pointer_type (fntype
), fndecl
);
821 return build_call (loc
, fn
, args
);
824 /* Construct a playback::rvalue instance (wrapping a tree) for a
825 call through a function pointer. */
829 new_call_through_ptr (location
*loc
,
834 tree t_fn_ptr
= fn_ptr
->as_tree ();
836 return build_call (loc
, t_fn_ptr
, args
);
839 /* Construct a tree for a cast. */
842 playback::context::build_cast (playback::location
*loc
,
843 playback::rvalue
*expr
,
844 playback::type
*type_
)
846 /* For comparison, see:
847 - c/c-typeck.c:build_c_cast
848 - c/c-convert.c: convert
851 Only some kinds of cast are currently supported here. */
852 tree t_expr
= expr
->as_tree ();
853 tree t_dst_type
= type_
->as_tree ();
855 t_ret
= targetm
.convert_to_type (t_dst_type
, t_expr
);
858 enum tree_code dst_code
= TREE_CODE (t_dst_type
);
863 t_ret
= convert_to_integer (t_dst_type
, t_expr
);
867 /* Compare with c_objc_common_truthvalue_conversion and
868 c_common_truthvalue_conversion. */
869 /* For now, convert to: (t_expr != 0) */
870 t_ret
= build2 (NE_EXPR
, t_dst_type
,
871 t_expr
, integer_zero_node
);
875 t_ret
= convert_to_real (t_dst_type
, t_expr
);
879 t_ret
= build1 (NOP_EXPR
, t_dst_type
, t_expr
);
883 add_error (loc
, "couldn't handle cast during playback");
884 fprintf (stderr
, "input expression:\n");
886 fprintf (stderr
, "requested type:\n");
887 debug_tree (t_dst_type
);
888 return error_mark_node
;
891 if (TREE_CODE (t_ret
) != C_MAYBE_CONST_EXPR
)
892 t_ret
= fold (t_ret
);
897 /* Construct a playback::rvalue instance (wrapping a tree) for a
902 new_cast (playback::location
*loc
,
903 playback::rvalue
*expr
,
904 playback::type
*type_
)
907 tree t_cast
= build_cast (loc
, expr
, type_
);
909 set_tree_location (t_cast
, loc
);
910 return new rvalue (this, t_cast
);
913 /* Construct a playback::lvalue instance (wrapping a tree) for an
918 new_array_access (location
*loc
,
925 /* For comparison, see:
926 c/c-typeck.c: build_array_ref
927 c-family/c-common.c: pointer_int_sum
929 tree t_ptr
= ptr
->as_tree ();
930 tree t_index
= index
->as_tree ();
931 tree t_type_ptr
= TREE_TYPE (t_ptr
);
932 tree t_type_star_ptr
= TREE_TYPE (t_type_ptr
);
934 if (TREE_CODE (t_type_ptr
) == ARRAY_TYPE
)
936 tree t_result
= build4 (ARRAY_REF
, t_type_star_ptr
, t_ptr
, t_index
,
937 NULL_TREE
, NULL_TREE
);
939 set_tree_location (t_result
, loc
);
940 return new lvalue (this, t_result
);
944 /* Convert index to an offset in bytes. */
945 tree t_sizeof
= size_in_bytes (t_type_star_ptr
);
946 t_index
= fold_build1 (CONVERT_EXPR
, sizetype
, t_index
);
947 tree t_offset
= build2 (MULT_EXPR
, sizetype
, t_index
, t_sizeof
);
949 /* Locate (ptr + offset). */
950 tree t_address
= build2 (POINTER_PLUS_EXPR
, t_type_ptr
, t_ptr
, t_offset
);
952 tree t_indirection
= build1 (INDIRECT_REF
, t_type_star_ptr
, t_address
);
955 set_tree_location (t_sizeof
, loc
);
956 set_tree_location (t_offset
, loc
);
957 set_tree_location (t_address
, loc
);
958 set_tree_location (t_indirection
, loc
);
961 return new lvalue (this, t_indirection
);
965 /* Construct a tree for a field access. */
969 new_field_access (location
*loc
,
976 /* Compare with c/c-typeck.c:lookup_field, build_indirect_ref, and
977 build_component_ref. */
978 tree type
= TREE_TYPE (datum
);
980 gcc_assert (TREE_CODE (type
) != POINTER_TYPE
);
982 tree t_field
= field
->as_tree ();
983 tree ref
= build3 (COMPONENT_REF
, TREE_TYPE (t_field
), datum
,
986 set_tree_location (ref
, loc
);
990 /* Construct a tree for a dereference. */
994 new_dereference (tree ptr
,
999 tree type
= TREE_TYPE (TREE_TYPE(ptr
));
1000 tree datum
= build1 (INDIRECT_REF
, type
, ptr
);
1002 set_tree_location (datum
, loc
);
1006 /* Construct a playback::lvalue instance (wrapping a tree) for a
1011 access_field (location
*loc
,
1014 tree datum
= as_tree ();
1015 tree ref
= get_context ()->new_field_access (loc
, datum
, field
);
1018 return new lvalue (get_context (), ref
);
1021 /* Construct a playback::rvalue instance (wrapping a tree) for a
1026 access_field (location
*loc
,
1029 tree datum
= as_tree ();
1030 tree ref
= get_context ()->new_field_access (loc
, datum
, field
);
1033 return new rvalue (get_context (), ref
);
1036 /* Construct a playback::lvalue instance (wrapping a tree) for a
1037 dereferenced field access. */
1041 dereference_field (location
*loc
,
1044 tree ptr
= as_tree ();
1045 tree datum
= get_context ()->new_dereference (ptr
, loc
);
1048 tree ref
= get_context ()->new_field_access (loc
, datum
, field
);
1051 return new lvalue (get_context (), ref
);
1054 /* Construct a playback::lvalue instance (wrapping a tree) for a
1059 dereference (location
*loc
)
1061 tree ptr
= as_tree ();
1062 tree datum
= get_context ()->new_dereference (ptr
, loc
);
1063 return new lvalue (get_context (), datum
);
1066 /* Construct a playback::rvalue instance (wrapping a tree) for an
1071 get_address (location
*loc
)
1073 tree t_lvalue
= as_tree ();
1074 tree t_thistype
= TREE_TYPE (t_lvalue
);
1075 tree t_ptrtype
= build_pointer_type (t_thistype
);
1076 tree ptr
= build1 (ADDR_EXPR
, t_ptrtype
, t_lvalue
);
1078 get_context ()->set_tree_location (ptr
, loc
);
1079 return new rvalue (get_context (), ptr
);
1082 /* gcc::jit::playback::wrapper subclasses are GC-managed:
1083 allocate them using ggc_internal_cleared_alloc. */
1087 operator new (size_t sz
)
1089 return ggc_internal_cleared_alloc (sz MEM_STAT_INFO
);
1092 /* Constructor for gcc:jit::playback::function. */
1094 playback::function::
1095 function (context
*ctxt
,
1097 enum gcc_jit_function_kind kind
)
1099 m_inner_fndecl (fndecl
),
1100 m_inner_bind_expr (NULL
),
1103 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
)
1105 /* Create a BIND_EXPR, and within it, a statement list. */
1106 m_stmt_list
= alloc_stmt_list ();
1107 m_stmt_iter
= tsi_start (m_stmt_list
);
1108 m_inner_block
= make_node (BLOCK
);
1110 build3 (BIND_EXPR
, void_type_node
, NULL
, m_stmt_list
, m_inner_block
);
1114 m_inner_block
= NULL
;
1119 /* Hand-written GC-marking hook for playback functions. */
1122 playback::function::
1125 gt_ggc_m_9tree_node (m_inner_fndecl
);
1126 gt_ggc_m_9tree_node (m_inner_bind_expr
);
1127 gt_ggc_m_9tree_node (m_stmt_list
);
1128 gt_ggc_m_9tree_node (m_inner_block
);
1131 /* Get the return type of a playback function, in tree form. */
1134 playback::function::
1135 get_return_type_as_tree () const
1137 return TREE_TYPE (TREE_TYPE(m_inner_fndecl
));
1140 /* Construct a new local within this playback::function. */
1143 playback::function::
1144 new_local (location
*loc
,
1150 tree inner
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
1151 get_identifier (name
),
1153 DECL_CONTEXT (inner
) = this->m_inner_fndecl
;
1155 /* Prepend to BIND_EXPR_VARS: */
1156 DECL_CHAIN (inner
) = BIND_EXPR_VARS (m_inner_bind_expr
);
1157 BIND_EXPR_VARS (m_inner_bind_expr
) = inner
;
1160 set_tree_location (inner
, loc
);
1161 return new lvalue (m_ctxt
, inner
);
1164 /* Construct a new block within this playback::function. */
1167 playback::function::
1168 new_block (const char *name
)
1170 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
1172 block
*result
= new playback::block (this, name
);
1173 m_blocks
.safe_push (result
);
1177 /* Build a statement list for the function as a whole out of the
1178 lists of statements for the individual blocks, building labels
1182 playback::function::
1188 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
1193 b
->m_label_expr
= build1 (LABEL_EXPR
,
1195 b
->as_label_decl ());
1196 tsi_link_after (&m_stmt_iter
, b
->m_label_expr
, TSI_CONTINUE_LINKING
);
1198 FOR_EACH_VEC_ELT (b
->m_stmts
, j
, stmt
)
1199 tsi_link_after (&m_stmt_iter
, stmt
, TSI_CONTINUE_LINKING
);
1203 /* Finish compiling the given function, potentially running the
1205 The function will have a statement list by now.
1206 Amongst other things, this gimplifies the statement list,
1207 and calls cgraph_node::finalize_function on the function. */
1210 playback::function::
1213 if (m_ctxt
->get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE
))
1214 debug_tree (m_stmt_list
);
1216 /* Do we need this to force cgraphunit.c to output the function? */
1217 if (m_kind
== GCC_JIT_FUNCTION_EXPORTED
)
1219 DECL_EXTERNAL (m_inner_fndecl
) = 0;
1220 DECL_PRESERVE_P (m_inner_fndecl
) = 1;
1223 if (m_kind
== GCC_JIT_FUNCTION_INTERNAL
1224 ||m_kind
== GCC_JIT_FUNCTION_ALWAYS_INLINE
)
1226 DECL_EXTERNAL (m_inner_fndecl
) = 0;
1227 TREE_PUBLIC (m_inner_fndecl
) = 0;
1230 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
)
1232 /* Seem to need this in gimple-low.c: */
1233 gcc_assert (m_inner_block
);
1234 DECL_INITIAL (m_inner_fndecl
) = m_inner_block
;
1236 /* how to add to function? the following appears to be how to
1237 set the body of a m_inner_fndecl: */
1238 DECL_SAVED_TREE(m_inner_fndecl
) = m_inner_bind_expr
;
1240 /* Ensure that locals appear in the debuginfo. */
1241 BLOCK_VARS (m_inner_block
) = BIND_EXPR_VARS (m_inner_bind_expr
);
1243 //debug_tree (m_inner_fndecl);
1245 /* Convert to gimple: */
1246 //printf("about to gimplify_function_tree\n");
1247 gimplify_function_tree (m_inner_fndecl
);
1248 //printf("finished gimplify_function_tree\n");
1250 current_function_decl
= m_inner_fndecl
;
1251 if (m_ctxt
->get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE
))
1252 dump_function_to_file (m_inner_fndecl
, stderr
, TDF_VOPS
|TDF_MEMSYMS
|TDF_LINENO
);
1253 //debug_tree (m_inner_fndecl);
1255 //printf("about to add to cgraph\n");
1256 /* Add to cgraph: */
1257 cgraph_node::finalize_function (m_inner_fndecl
, false);
1258 /* This can trigger a collection, so we need to have all of
1259 the funcs as roots. */
1261 current_function_decl
= NULL
;
1265 /* Add an eval of the rvalue to the function's statement list. */
1269 add_eval (location
*loc
,
1272 gcc_assert (rvalue
);
1275 set_tree_location (rvalue
->as_tree (), loc
);
1277 add_stmt (rvalue
->as_tree ());
1280 /* Add an assignment to the function's statement list. */
1284 add_assignment (location
*loc
,
1288 gcc_assert (lvalue
);
1289 gcc_assert (rvalue
);
1291 tree t_lvalue
= lvalue
->as_tree ();
1292 tree t_rvalue
= rvalue
->as_tree ();
1293 if (TREE_TYPE (t_rvalue
) != TREE_TYPE (t_lvalue
))
1295 t_rvalue
= build1 (CONVERT_EXPR
,
1296 TREE_TYPE (t_lvalue
),
1299 set_tree_location (t_rvalue
, loc
);
1303 build2 (MODIFY_EXPR
, TREE_TYPE (t_lvalue
),
1304 t_lvalue
, t_rvalue
);
1306 set_tree_location (stmt
, loc
);
1310 /* Add a comment to the function's statement list.
1311 For now this is done by adding a dummy label. */
1315 add_comment (location
*loc
,
1318 /* Wrap the text in C-style comment delimiters. */
1320 (3 /* opening delim */
1322 + 3 /* closing delim */
1323 + 1 /* terminator */);
1324 char *wrapped
= (char *)ggc_internal_alloc (sz
);
1325 snprintf (wrapped
, sz
, "/* %s */", text
);
1327 /* For now we simply implement this by adding a dummy label with a name
1328 containing the given text. */
1329 tree identifier
= get_identifier (wrapped
);
1330 tree label_decl
= build_decl (UNKNOWN_LOCATION
, LABEL_DECL
,
1331 identifier
, void_type_node
);
1332 DECL_CONTEXT (label_decl
) = m_func
->as_fndecl ();
1334 tree label_expr
= build1 (LABEL_EXPR
, void_type_node
, label_decl
);
1336 set_tree_location (label_expr
, loc
);
1337 add_stmt (label_expr
);
1340 /* Add a conditional jump statement to the function's statement list. */
1344 add_conditional (location
*loc
,
1349 gcc_assert (boolval
);
1350 gcc_assert (on_true
);
1351 gcc_assert (on_false
);
1353 /* COND_EXPR wants statement lists for the true/false operands, but we
1355 Shim it by creating jumps to the labels */
1356 tree true_jump
= build1 (GOTO_EXPR
, void_type_node
,
1357 on_true
->as_label_decl ());
1359 set_tree_location (true_jump
, loc
);
1361 tree false_jump
= build1 (GOTO_EXPR
, void_type_node
,
1362 on_false
->as_label_decl ());
1364 set_tree_location (false_jump
, loc
);
1367 build3 (COND_EXPR
, void_type_node
, boolval
->as_tree (),
1368 true_jump
, false_jump
);
1370 set_tree_location (stmt
, loc
);
1374 /* Add an unconditional jump statement to the function's statement list. */
1378 add_jump (location
*loc
,
1381 gcc_assert (target
);
1383 // see c_finish_loop
1384 //tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
1387 //tree stmt = build_and_jump (&LABEL_EXPR_LABEL (target->label_));
1388 TREE_USED (target
->as_label_decl ()) = 1;
1389 tree stmt
= build1 (GOTO_EXPR
, void_type_node
, target
->as_label_decl ());
1391 set_tree_location (stmt
, loc
);
1397 c_finish_goto_label (location_t loc, tree label)
1399 tree decl = lookup_label_for_goto (loc, label);
1402 TREE_USED (decl) = 1;
1404 tree t = build1 (GOTO_EXPR, void_type_node, decl);
1405 SET_EXPR_LOCATION (t, loc);
1406 return add_stmt (t);
1413 /* Add a return statement to the function's statement list. */
1417 add_return (location
*loc
,
1420 tree modify_retval
= NULL
;
1421 tree return_type
= m_func
->get_return_type_as_tree ();
1424 tree t_lvalue
= DECL_RESULT (m_func
->as_fndecl ());
1425 tree t_rvalue
= rvalue
->as_tree ();
1426 if (TREE_TYPE (t_rvalue
) != TREE_TYPE (t_lvalue
))
1427 t_rvalue
= build1 (CONVERT_EXPR
,
1428 TREE_TYPE (t_lvalue
),
1430 modify_retval
= build2 (MODIFY_EXPR
, return_type
,
1431 t_lvalue
, t_rvalue
);
1433 set_tree_location (modify_retval
, loc
);
1435 tree return_stmt
= build1 (RETURN_EXPR
, return_type
,
1438 set_tree_location (return_stmt
, loc
);
1440 add_stmt (return_stmt
);
1443 /* Constructor for gcc::jit::playback::block. */
1446 block (function
*func
,
1456 identifier
= get_identifier (name
);
1459 m_label_decl
= build_decl (UNKNOWN_LOCATION
, LABEL_DECL
,
1460 identifier
, void_type_node
);
1461 DECL_CONTEXT (m_label_decl
) = func
->as_fndecl ();
1462 m_label_expr
= NULL
;
1465 /* Construct a tempdir path template suitable for use by mkdtemp
1466 e.g. "/tmp/libgccjit-XXXXXX", but respecting the rules in
1467 libiberty's choose_tempdir rather than hardcoding "/tmp/".
1469 The memory is allocated using malloc and must be freed.
1470 Aborts the process if allocation fails. */
1473 make_tempdir_path_template ()
1475 const char *tmpdir_buf
;
1477 const char *file_template_buf
;
1478 size_t file_template_len
;
1481 /* The result of choose_tmpdir is a cached buffer within libiberty, so
1482 we must *not* free it. */
1483 tmpdir_buf
= choose_tmpdir ();
1485 /* choose_tmpdir aborts on malloc failure. */
1486 gcc_assert (tmpdir_buf
);
1488 tmpdir_len
= strlen (tmpdir_buf
);
1489 /* tmpdir_buf should now have a dir separator as the final byte. */
1490 gcc_assert (tmpdir_len
> 0);
1491 gcc_assert (tmpdir_buf
[tmpdir_len
- 1] == DIR_SEPARATOR
);
1493 file_template_buf
= "libgccjit-XXXXXX";
1494 file_template_len
= strlen (file_template_buf
);
1496 result
= XNEWVEC (char, tmpdir_len
+ file_template_len
+ 1);
1497 strcpy (result
, tmpdir_buf
);
1498 strcpy (result
+ tmpdir_len
, file_template_buf
);
1503 /* Compile a playback::context:
1505 - Use the context's options to cconstruct command-line options, and
1506 call into the rest of GCC (toplev::main).
1507 - Assuming it succeeds, we have a .s file; we want a .so file.
1508 Invoke another gcc to convert the .s file to a .so file.
1509 - dlopen the .so file
1510 - Wrap the result up as a playback::result and return it. */
1516 void *handle
= NULL
;
1517 const char *ctxt_progname
;
1518 result
*result_obj
= NULL
;
1519 const char *fake_args
[20];
1520 unsigned int num_args
;
1522 m_path_template
= make_tempdir_path_template ();
1523 if (!m_path_template
)
1526 /* Create tempdir using mkdtemp. This is created with 0700 perms and
1527 is unique. Hence no other (non-root) users should have access to
1528 the paths within it. */
1529 m_path_tempdir
= mkdtemp (m_path_template
);
1530 if (!m_path_tempdir
)
1532 m_path_c_file
= concat (m_path_tempdir
, "/fake.c", NULL
);
1533 m_path_s_file
= concat (m_path_tempdir
, "/fake.s", NULL
);
1534 m_path_so_file
= concat (m_path_tempdir
, "/fake.so", NULL
);
1536 /* Call into the rest of gcc.
1537 For now, we have to assemble command-line options to pass into
1538 toplev::main, so that they can be parsed. */
1540 /* Pass in user-provided program name as argv0, if any, so that it
1541 makes it into GCC's "progname" global, used in various diagnostics. */
1542 ctxt_progname
= get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1544 (ctxt_progname
? ctxt_progname
: "libgccjit.so");
1546 fake_args
[1] = m_path_c_file
;
1549 #define ADD_ARG(arg) \
1552 gcc_assert(num_args < sizeof(fake_args)/sizeof(char*)); \
1553 fake_args[num_args++] = arg; \
1559 /* Handle int options: */
1560 switch (get_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL
))
1564 "unrecognized optimization level: %i",
1565 get_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL
));
1584 /* What about -Os? */
1586 /* Handle bool options: */
1587 if (get_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO
))
1590 /* Suppress timing (and other) info. */
1591 if (!get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_SUMMARY
))
1597 /* Aggressively garbage-collect, to shake out bugs: */
1598 if (get_bool_option (GCC_JIT_BOOL_OPTION_SELFCHECK_GC
))
1600 ADD_ARG ("--param");
1601 ADD_ARG ("ggc-min-expand=0");
1602 ADD_ARG ("--param");
1603 ADD_ARG ("ggc-min-heapsize=0");
1606 if (get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING
))
1608 ADD_ARG ("-fdump-tree-all");
1609 ADD_ARG ("-fdump-rtl-all");
1610 ADD_ARG ("-fdump-ipa-all");
1613 toplev
toplev (false);
1615 toplev
.main (num_args
, const_cast <char **> (fake_args
));
1618 active_playback_ctxt
= NULL
;
1620 if (errors_occurred ())
1623 if (get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE
))
1624 dump_generated_code ();
1626 /* Gross hacks follow:
1627 We have a .s file; we want a .so file.
1628 We could reuse parts of gcc/gcc.c to do this.
1629 For now, just use the driver binary from the install, as
1630 named in gcc-driver-name.h
1631 e.g. "x86_64-unknown-linux-gnu-gcc-5.0.0".
1634 auto_timevar
assemble_timevar (TV_ASSEMBLE
);
1636 const char *argv
[7];
1637 int exit_status
= 0;
1639 const char *gcc_driver_name
= GCC_DRIVER_NAME
;
1641 argv
[0] = gcc_driver_name
;
1642 argv
[1] = "-shared";
1643 /* The input: assembler. */
1644 argv
[2] = m_path_s_file
;
1645 /* The output: shared library. */
1647 argv
[4] = m_path_so_file
;
1649 /* Don't use the linker plugin.
1650 If running with just a "make" and not a "make install", then we'd
1652 "fatal error: -fuse-linker-plugin, but liblto_plugin.so not found"
1653 libto_plugin is a .la at build time, with it becoming installed with
1654 ".so" suffix: i.e. it doesn't exist with a .so suffix until install
1656 argv
[5] = "-fno-use-linker-plugin";
1658 /* pex argv arrays are NULL-terminated. */
1661 errmsg
= pex_one (PEX_SEARCH
, /* int flags, */
1663 const_cast<char * const *> (argv
),
1664 ctxt_progname
, /* const char *pname */
1665 NULL
, /* const char *outname */
1666 NULL
, /* const char *errname */
1667 &exit_status
, /* int *status */
1668 &err
); /* int *err*/
1671 add_error (NULL
, "error invoking gcc driver: %s", errmsg
);
1675 /* pex_one can return a NULL errmsg when the executable wasn't
1676 found (or doesn't exist), so trap these cases also. */
1677 if (exit_status
|| err
)
1680 "error invoking gcc driver: exit_status: %i err: %i",
1683 "whilst attempting to run a driver named: %s",
1692 // TODO: split out assembles vs linker
1694 /* dlopen the .so file. */
1696 auto_timevar
load_timevar (TV_LOAD
);
1700 /* Clear any existing error. */
1703 handle
= dlopen (m_path_so_file
, RTLD_NOW
| RTLD_LOCAL
);
1704 if ((error
= dlerror()) != NULL
) {
1705 add_error (NULL
, "%s", error
);
1708 result_obj
= new result (handle
);
1716 /* Top-level hook for playing back a recording context.
1718 This plays back m_recording_ctxt, and, if no errors
1719 occurred builds statement lists for and then postprocesses
1720 every function in the result. */
1726 /* Adapted from c-common.c:c_common_nodes_and_builtins. */
1727 tree array_domain_type
= build_index_type (size_int (200));
1728 m_char_array_type_node
1729 = build_array_type (char_type_node
, array_domain_type
);
1732 = build_pointer_type (build_qualified_type (char_type_node
,
1735 /* Replay the recorded events: */
1736 timevar_push (TV_JIT_REPLAY
);
1738 m_recording_ctxt
->replay_into (this);
1740 /* Clean away the temporary references from recording objects
1741 to playback objects. We have to do this now since the
1742 latter are GC-allocated, but the former don't mark these
1743 refs. Hence we must stop using them before the GC can run. */
1744 m_recording_ctxt
->disassociate_from_playback ();
1746 timevar_pop (TV_JIT_REPLAY
);
1748 if (!errors_occurred ())
1753 /* No GC can happen yet; process the cached source locations. */
1754 handle_locations ();
1756 /* We've now created tree nodes for the stmts in the various blocks
1757 in each function, but we haven't built each function's single stmt
1758 list yet. Do so now. */
1759 FOR_EACH_VEC_ELT (m_functions
, i
, func
)
1760 func
->build_stmt_list ();
1762 /* No GC can have happened yet. */
1764 /* Postprocess the functions. This could trigger GC. */
1765 FOR_EACH_VEC_ELT (m_functions
, i
, func
)
1768 func
->postprocess ();
1773 /* Dump the generated .s file to stderr. */
1777 dump_generated_code ()
1781 FILE *f_in
= fopen (m_path_s_file
, "r");
1785 while ( (sz
= fread (buf
, 1, sizeof (buf
), f_in
)) )
1786 fwrite (buf
, 1, sz
, stderr
);
1791 /* qsort comparator for comparing pairs of playback::source_line *,
1792 ordering them by line number. */
1795 line_comparator (const void *lhs
, const void *rhs
)
1797 const playback::source_line
*line_lhs
= \
1798 *static_cast<const playback::source_line
* const*> (lhs
);
1799 const playback::source_line
*line_rhs
= \
1800 *static_cast<const playback::source_line
* const*> (rhs
);
1801 return line_lhs
->get_line_num () - line_rhs
->get_line_num ();
1804 /* qsort comparator for comparing pairs of playback::location *,
1805 ordering them by column number. */
1808 location_comparator (const void *lhs
, const void *rhs
)
1810 const playback::location
*loc_lhs
= \
1811 *static_cast<const playback::location
* const *> (lhs
);
1812 const playback::location
*loc_rhs
= \
1813 *static_cast<const playback::location
* const *> (rhs
);
1814 return loc_lhs
->get_column_num () - loc_rhs
->get_column_num ();
1817 /* Our API allows locations to be created in arbitrary orders, but the
1818 linemap API requires locations to be created in ascending order
1819 as if we were tokenizing files.
1821 This hook sorts all of the the locations that have been created, and
1822 calls into the linemap API, creating linemap entries in sorted order
1823 for our locations. */
1829 /* Create the source code locations, following the ordering rules
1830 imposed by the linemap API.
1832 line_table is a global. */
1836 FOR_EACH_VEC_ELT (m_source_files
, i
, file
)
1838 linemap_add (line_table
, LC_ENTER
, false, file
->get_filename (), 0);
1840 /* Sort lines by ascending line numbers. */
1841 file
->m_source_lines
.qsort (&line_comparator
);
1845 FOR_EACH_VEC_ELT (file
->m_source_lines
, j
, line
)
1850 /* Sort locations in line by ascending column numbers. */
1851 line
->m_locations
.qsort (&location_comparator
);
1853 /* Determine maximum column within this line. */
1854 gcc_assert (line
->m_locations
.length () > 0);
1855 location
*final_column
=
1856 line
->m_locations
[line
->m_locations
.length () - 1];
1857 int max_col
= final_column
->get_column_num ();
1859 linemap_line_start (line_table
, line
->get_line_num (), max_col
);
1860 FOR_EACH_VEC_ELT (line
->m_locations
, k
, loc
)
1863 linemap_position_for_column (line_table
, loc
->get_column_num ());
1867 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
1870 /* line_table should now be populated; every playback::location should
1871 now have an m_srcloc. */
1873 /* Now assign them to tree nodes as appropriate. */
1874 std::pair
<tree
, location
*> *cached_location
;
1876 FOR_EACH_VEC_ELT (m_cached_locations
, i
, cached_location
)
1878 tree t
= cached_location
->first
;
1879 source_location srcloc
= cached_location
->second
->m_srcloc
;
1881 /* This covers expressions: */
1882 if (CAN_HAVE_LOCATION_P (t
))
1883 SET_EXPR_LOCATION (t
, srcloc
);
1884 else if (CODE_CONTAINS_STRUCT(TREE_CODE(t
), TS_DECL_MINIMAL
))
1885 DECL_SOURCE_LOCATION (t
) = srcloc
;
1888 /* Don't know how to set location on this node. */
1893 /* We handle errors on a playback::context by adding them to the
1894 corresponding recording::context. */
1898 add_error (location
*loc
, const char *fmt
, ...)
1902 m_recording_ctxt
->add_error_va (loc
? loc
->get_recording_loc () : NULL
,
1907 /* We handle errors on a playback::context by adding them to the
1908 corresponding recording::context. */
1912 add_error_va (location
*loc
, const char *fmt
, va_list ap
)
1914 m_recording_ctxt
->add_error_va (loc
? loc
->get_recording_loc () : NULL
,
1918 /* Constructor for gcc::jit::playback::result. */
1921 result(void *dso_handle
)
1922 : m_dso_handle(dso_handle
)
1926 /* gcc::jit::playback::result's destructor.
1928 Called implicitly by gcc_jit_result_release. */
1932 dlclose (m_dso_handle
);
1935 /* Attempt to locate the given function by name within the
1936 playback::result, using dlsym.
1938 Implements the post-error-checking part of
1939 gcc_jit_result_get_code. */
1943 get_code (const char *funcname
)
1948 /* Clear any existing error. */
1951 code
= dlsym (m_dso_handle
, funcname
);
1953 if ((error
= dlerror()) != NULL
) {
1954 fprintf(stderr
, "%s\n", error
);
1960 /* Dealing with the linemap API. */
1962 /* Construct a playback::location for a recording::location, if it
1963 doesn't exist already. */
1965 playback::location
*
1967 new_location (recording::location
*rloc
,
1968 const char *filename
,
1972 /* Get the source_file for filename, creating if necessary. */
1973 source_file
*src_file
= get_source_file (filename
);
1974 /* Likewise for the line within the file. */
1975 source_line
*src_line
= src_file
->get_source_line (line
);
1976 /* Likewise for the column within the line. */
1977 location
*loc
= src_line
->get_location (rloc
, column
);
1981 /* Deferred setting of the location for a given tree, by adding the
1982 (tree, playback::location) pair to a list of deferred associations.
1983 We will actually set the location on the tree later on once
1984 the source_location for the playback::location exists. */
1988 set_tree_location (tree t
, location
*loc
)
1991 m_cached_locations
.safe_push (std::make_pair (t
, loc
));
1995 /* Construct a playback::source_file for the given source
1996 filename, if it doesn't exist already. */
1998 playback::source_file
*
2000 get_source_file (const char *filename
)
2003 For simplicitly, this is currently a linear search.
2004 Replace with a hash if this shows up in the profile. */
2007 tree ident_filename
= get_identifier (filename
);
2009 FOR_EACH_VEC_ELT (m_source_files
, i
, file
)
2010 if (file
->filename_as_tree () == ident_filename
)
2014 file
= new source_file (ident_filename
);
2015 m_source_files
.safe_push (file
);
2019 /* Constructor for gcc::jit::playback::source_file. */
2021 playback::source_file::source_file (tree filename
) :
2023 m_filename (filename
)
2027 /* Construct a playback::source_line for the given line
2028 within this source file, if one doesn't exist already. */
2030 playback::source_line
*
2031 playback::source_file::
2032 get_source_line (int line_num
)
2035 For simplicitly, this is currently a linear search.
2036 Replace with a hash if this shows up in the profile. */
2040 FOR_EACH_VEC_ELT (m_source_lines
, i
, line
)
2041 if (line
->get_line_num () == line_num
)
2045 line
= new source_line (this, line_num
);
2046 m_source_lines
.safe_push (line
);
2050 /* Constructor for gcc::jit::playback::source_line. */
2052 playback::source_line::source_line (source_file
*file
, int line_num
) :
2054 m_source_file (file
),
2055 m_line_num (line_num
)
2059 /* Construct a playback::location for the given column
2060 within this line of a specific source file, if one doesn't exist
2063 playback::location
*
2064 playback::source_line::
2065 get_location (recording::location
*rloc
, int column_num
)
2070 /* Another linear search that probably should be a hash table. */
2071 FOR_EACH_VEC_ELT (m_locations
, i
, loc
)
2072 if (loc
->get_column_num () == column_num
)
2076 loc
= new location (rloc
, this, column_num
);
2077 m_locations
.safe_push (loc
);
2081 /* Constructor for gcc::jit::playback::location. */
2083 playback::location::location (recording::location
*loc
,
2086 m_srcloc (UNKNOWN_LOCATION
),
2087 m_recording_loc (loc
),
2089 m_column_num(column_num
)
2093 /* The active gcc::jit::playback::context instance. This is a singleton,
2094 guarded by jit_mutex. */
2096 playback::context
*active_playback_ctxt
;
2098 } // namespace gcc::jit