annotate gcc/jit/jit-playback.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Internals of libgccjit: classes for playing back recorded API calls.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2013-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it
kono
parents:
diff changeset
8 under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
9 the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
10 any later version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but
kono
parents:
diff changeset
13 WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
kono
parents:
diff changeset
15 General Public License for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 #include "config.h"
kono
parents:
diff changeset
22 #include "system.h"
kono
parents:
diff changeset
23 #include "coretypes.h"
kono
parents:
diff changeset
24 #include "target.h"
kono
parents:
diff changeset
25 #include "tree.h"
kono
parents:
diff changeset
26 #include "stringpool.h"
kono
parents:
diff changeset
27 #include "cgraph.h"
kono
parents:
diff changeset
28 #include "dumpfile.h"
kono
parents:
diff changeset
29 #include "toplev.h"
kono
parents:
diff changeset
30 #include "tree-cfg.h"
kono
parents:
diff changeset
31 #include "convert.h"
kono
parents:
diff changeset
32 #include "stor-layout.h"
kono
parents:
diff changeset
33 #include "print-tree.h"
kono
parents:
diff changeset
34 #include "gimplify.h"
kono
parents:
diff changeset
35 #include "gcc-driver-name.h"
kono
parents:
diff changeset
36 #include "attribs.h"
kono
parents:
diff changeset
37 #include "context.h"
kono
parents:
diff changeset
38 #include "fold-const.h"
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
39 #include "opt-suggestions.h"
111
kono
parents:
diff changeset
40 #include "gcc.h"
kono
parents:
diff changeset
41 #include "diagnostic.h"
kono
parents:
diff changeset
42
kono
parents:
diff changeset
43 #include <pthread.h>
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 #include "jit-playback.h"
kono
parents:
diff changeset
46 #include "jit-result.h"
kono
parents:
diff changeset
47 #include "jit-builtins.h"
kono
parents:
diff changeset
48 #include "jit-tempdir.h"
kono
parents:
diff changeset
49
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
50 /* Compare with gcc/c-family/c-common.h: DECL_C_BIT_FIELD,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
51 SET_DECL_C_BIT_FIELD.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
52 These are redefined here to avoid depending from the C frontend. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
53 #define DECL_JIT_BIT_FIELD(NODE) \
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
54 (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
55 #define SET_DECL_JIT_BIT_FIELD(NODE) \
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
56 (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) = 1)
111
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 /* gcc::jit::playback::context::build_cast uses the convert.h API,
kono
parents:
diff changeset
59 which in turn requires the frontend to provide a "convert"
kono
parents:
diff changeset
60 function, apparently as a fallback.
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 Hence we provide this dummy one, with the requirement that any casts
kono
parents:
diff changeset
63 are handled before reaching this. */
kono
parents:
diff changeset
64 extern tree convert (tree type, tree expr);
kono
parents:
diff changeset
65
kono
parents:
diff changeset
66 tree
kono
parents:
diff changeset
67 convert (tree dst_type, tree expr)
kono
parents:
diff changeset
68 {
kono
parents:
diff changeset
69 gcc_assert (gcc::jit::active_playback_ctxt);
kono
parents:
diff changeset
70 gcc::jit::active_playback_ctxt->add_error (NULL, "unhandled conversion");
kono
parents:
diff changeset
71 fprintf (stderr, "input expression:\n");
kono
parents:
diff changeset
72 debug_tree (expr);
kono
parents:
diff changeset
73 fprintf (stderr, "requested type:\n");
kono
parents:
diff changeset
74 debug_tree (dst_type);
kono
parents:
diff changeset
75 return error_mark_node;
kono
parents:
diff changeset
76 }
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 namespace gcc {
kono
parents:
diff changeset
79 namespace jit {
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 /**********************************************************************
kono
parents:
diff changeset
82 Playback.
kono
parents:
diff changeset
83 **********************************************************************/
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 /* The constructor for gcc::jit::playback::context. */
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 playback::context::context (recording::context *ctxt)
kono
parents:
diff changeset
88 : log_user (ctxt->get_logger ()),
kono
parents:
diff changeset
89 m_recording_ctxt (ctxt),
kono
parents:
diff changeset
90 m_tempdir (NULL),
kono
parents:
diff changeset
91 m_char_array_type_node (NULL),
kono
parents:
diff changeset
92 m_const_char_ptr (NULL)
kono
parents:
diff changeset
93 {
kono
parents:
diff changeset
94 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
95 m_functions.create (0);
kono
parents:
diff changeset
96 m_globals.create (0);
kono
parents:
diff changeset
97 m_source_files.create (0);
kono
parents:
diff changeset
98 m_cached_locations.create (0);
kono
parents:
diff changeset
99 }
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 /* The destructor for gcc::jit::playback::context. */
kono
parents:
diff changeset
102
kono
parents:
diff changeset
103 playback::context::~context ()
kono
parents:
diff changeset
104 {
kono
parents:
diff changeset
105 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
106
kono
parents:
diff changeset
107 /* Normally the playback::context is responsible for cleaning up the
kono
parents:
diff changeset
108 tempdir (including "fake.so" within the filesystem).
kono
parents:
diff changeset
109
kono
parents:
diff changeset
110 In the normal case, clean it up now.
kono
parents:
diff changeset
111
kono
parents:
diff changeset
112 However m_tempdir can be NULL if the context has handed over
kono
parents:
diff changeset
113 responsibility for the tempdir cleanup to the jit::result object, so
kono
parents:
diff changeset
114 that the cleanup can be delayed (see PR jit/64206). If that's the
kono
parents:
diff changeset
115 case this "delete NULL;" is a no-op. */
kono
parents:
diff changeset
116 delete m_tempdir;
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 m_functions.release ();
kono
parents:
diff changeset
119 }
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 /* A playback::context can reference GC-managed pointers. Mark them
kono
parents:
diff changeset
122 ("by hand", rather than by gengtype).
kono
parents:
diff changeset
123
kono
parents:
diff changeset
124 This is called on the active playback context (if any) by the
kono
parents:
diff changeset
125 my_ggc_walker hook in the jit_root_table in dummy-frontend.c. */
kono
parents:
diff changeset
126
kono
parents:
diff changeset
127 void
kono
parents:
diff changeset
128 playback::context::
kono
parents:
diff changeset
129 gt_ggc_mx ()
kono
parents:
diff changeset
130 {
kono
parents:
diff changeset
131 int i;
kono
parents:
diff changeset
132 function *func;
kono
parents:
diff changeset
133 FOR_EACH_VEC_ELT (m_functions, i, func)
kono
parents:
diff changeset
134 {
kono
parents:
diff changeset
135 if (ggc_test_and_set_mark (func))
kono
parents:
diff changeset
136 func->gt_ggc_mx ();
kono
parents:
diff changeset
137 }
kono
parents:
diff changeset
138 }
kono
parents:
diff changeset
139
kono
parents:
diff changeset
140 /* Given an enum gcc_jit_types value, get a "tree" type. */
kono
parents:
diff changeset
141
kono
parents:
diff changeset
142 static tree
kono
parents:
diff changeset
143 get_tree_node_for_type (enum gcc_jit_types type_)
kono
parents:
diff changeset
144 {
kono
parents:
diff changeset
145 switch (type_)
kono
parents:
diff changeset
146 {
kono
parents:
diff changeset
147 case GCC_JIT_TYPE_VOID:
kono
parents:
diff changeset
148 return void_type_node;
kono
parents:
diff changeset
149
kono
parents:
diff changeset
150 case GCC_JIT_TYPE_VOID_PTR:
kono
parents:
diff changeset
151 return ptr_type_node;
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 case GCC_JIT_TYPE_BOOL:
kono
parents:
diff changeset
154 return boolean_type_node;
kono
parents:
diff changeset
155
kono
parents:
diff changeset
156 case GCC_JIT_TYPE_CHAR:
kono
parents:
diff changeset
157 return char_type_node;
kono
parents:
diff changeset
158 case GCC_JIT_TYPE_SIGNED_CHAR:
kono
parents:
diff changeset
159 return signed_char_type_node;
kono
parents:
diff changeset
160 case GCC_JIT_TYPE_UNSIGNED_CHAR:
kono
parents:
diff changeset
161 return unsigned_char_type_node;
kono
parents:
diff changeset
162
kono
parents:
diff changeset
163 case GCC_JIT_TYPE_SHORT:
kono
parents:
diff changeset
164 return short_integer_type_node;
kono
parents:
diff changeset
165 case GCC_JIT_TYPE_UNSIGNED_SHORT:
kono
parents:
diff changeset
166 return short_unsigned_type_node;
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 case GCC_JIT_TYPE_CONST_CHAR_PTR:
kono
parents:
diff changeset
169 {
kono
parents:
diff changeset
170 tree const_char = build_qualified_type (char_type_node,
kono
parents:
diff changeset
171 TYPE_QUAL_CONST);
kono
parents:
diff changeset
172 return build_pointer_type (const_char);
kono
parents:
diff changeset
173 }
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 case GCC_JIT_TYPE_INT:
kono
parents:
diff changeset
176 return integer_type_node;
kono
parents:
diff changeset
177 case GCC_JIT_TYPE_UNSIGNED_INT:
kono
parents:
diff changeset
178 return unsigned_type_node;
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 case GCC_JIT_TYPE_LONG:
kono
parents:
diff changeset
181 return long_integer_type_node;
kono
parents:
diff changeset
182 case GCC_JIT_TYPE_UNSIGNED_LONG:
kono
parents:
diff changeset
183 return long_unsigned_type_node;
kono
parents:
diff changeset
184
kono
parents:
diff changeset
185 case GCC_JIT_TYPE_LONG_LONG:
kono
parents:
diff changeset
186 return long_long_integer_type_node;
kono
parents:
diff changeset
187 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
kono
parents:
diff changeset
188 return long_long_unsigned_type_node;
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 case GCC_JIT_TYPE_FLOAT:
kono
parents:
diff changeset
191 return float_type_node;
kono
parents:
diff changeset
192 case GCC_JIT_TYPE_DOUBLE:
kono
parents:
diff changeset
193 return double_type_node;
kono
parents:
diff changeset
194 case GCC_JIT_TYPE_LONG_DOUBLE:
kono
parents:
diff changeset
195 return long_double_type_node;
kono
parents:
diff changeset
196
kono
parents:
diff changeset
197 case GCC_JIT_TYPE_SIZE_T:
kono
parents:
diff changeset
198 return size_type_node;
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 case GCC_JIT_TYPE_FILE_PTR:
kono
parents:
diff changeset
201 return fileptr_type_node;
kono
parents:
diff changeset
202
kono
parents:
diff changeset
203 case GCC_JIT_TYPE_COMPLEX_FLOAT:
kono
parents:
diff changeset
204 return complex_float_type_node;
kono
parents:
diff changeset
205 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
kono
parents:
diff changeset
206 return complex_double_type_node;
kono
parents:
diff changeset
207 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
kono
parents:
diff changeset
208 return complex_long_double_type_node;
kono
parents:
diff changeset
209 }
kono
parents:
diff changeset
210
kono
parents:
diff changeset
211 return NULL;
kono
parents:
diff changeset
212 }
kono
parents:
diff changeset
213
kono
parents:
diff changeset
214 /* Construct a playback::type instance (wrapping a tree) for the given
kono
parents:
diff changeset
215 enum value. */
kono
parents:
diff changeset
216
kono
parents:
diff changeset
217 playback::type *
kono
parents:
diff changeset
218 playback::context::
kono
parents:
diff changeset
219 get_type (enum gcc_jit_types type_)
kono
parents:
diff changeset
220 {
kono
parents:
diff changeset
221 tree type_node = get_tree_node_for_type (type_);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
222 if (type_node == NULL)
111
kono
parents:
diff changeset
223 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
224 add_error (NULL, "unrecognized (enum gcc_jit_types) value: %i", type_);
111
kono
parents:
diff changeset
225 return NULL;
kono
parents:
diff changeset
226 }
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 return new type (type_node);
kono
parents:
diff changeset
229 }
kono
parents:
diff changeset
230
kono
parents:
diff changeset
231 /* Construct a playback::type instance (wrapping a tree) for the given
kono
parents:
diff changeset
232 array type. */
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234 playback::type *
kono
parents:
diff changeset
235 playback::context::
kono
parents:
diff changeset
236 new_array_type (playback::location *loc,
kono
parents:
diff changeset
237 playback::type *element_type,
kono
parents:
diff changeset
238 int num_elements)
kono
parents:
diff changeset
239 {
kono
parents:
diff changeset
240 gcc_assert (element_type);
kono
parents:
diff changeset
241
kono
parents:
diff changeset
242 tree t = build_array_type_nelts (element_type->as_tree (),
kono
parents:
diff changeset
243 num_elements);
kono
parents:
diff changeset
244 layout_type (t);
kono
parents:
diff changeset
245
kono
parents:
diff changeset
246 if (loc)
kono
parents:
diff changeset
247 set_tree_location (t, loc);
kono
parents:
diff changeset
248
kono
parents:
diff changeset
249 return new type (t);
kono
parents:
diff changeset
250 }
kono
parents:
diff changeset
251
kono
parents:
diff changeset
252 /* Construct a playback::field instance (wrapping a tree). */
kono
parents:
diff changeset
253
kono
parents:
diff changeset
254 playback::field *
kono
parents:
diff changeset
255 playback::context::
kono
parents:
diff changeset
256 new_field (location *loc,
kono
parents:
diff changeset
257 type *type,
kono
parents:
diff changeset
258 const char *name)
kono
parents:
diff changeset
259 {
kono
parents:
diff changeset
260 gcc_assert (type);
kono
parents:
diff changeset
261 gcc_assert (name);
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 /* compare with c/c-decl.c:grokfield and grokdeclarator. */
kono
parents:
diff changeset
264 tree decl = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
kono
parents:
diff changeset
265 get_identifier (name), type->as_tree ());
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 if (loc)
kono
parents:
diff changeset
268 set_tree_location (decl, loc);
kono
parents:
diff changeset
269
kono
parents:
diff changeset
270 return new field (decl);
kono
parents:
diff changeset
271 }
kono
parents:
diff changeset
272
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
273 /* Construct a playback::bitfield instance (wrapping a tree). */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
274
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
275 playback::field *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
276 playback::context::
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
277 new_bitfield (location *loc,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
278 type *type,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
279 int width,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
280 const char *name)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
281 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
282 gcc_assert (type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
283 gcc_assert (name);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
284 gcc_assert (width);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
285
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
286 /* compare with c/c-decl.c:grokfield, grokdeclarator and
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
287 check_bitfield_type_and_width. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
288
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
289 tree tree_type = type->as_tree ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
290 gcc_assert (INTEGRAL_TYPE_P (tree_type));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
291 tree tree_width = build_int_cst (integer_type_node, width);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
292 if (compare_tree_int (tree_width, TYPE_PRECISION (tree_type)) > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
293 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
294 add_error (
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
295 loc,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
296 "width of bit-field %s (width: %i) is wider than its type (width: %i)",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
297 name, width, TYPE_PRECISION (tree_type));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
298 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
299 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
300
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
301 tree decl = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
302 get_identifier (name), type->as_tree ());
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
303 DECL_NONADDRESSABLE_P (decl) = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
304 DECL_INITIAL (decl) = tree_width;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
305 SET_DECL_JIT_BIT_FIELD (decl);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
306
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
307 if (loc)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
308 set_tree_location (decl, loc);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
309
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
310 return new field (decl);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
311 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
312
111
kono
parents:
diff changeset
313 /* Construct a playback::compound_type instance (wrapping a tree). */
kono
parents:
diff changeset
314
kono
parents:
diff changeset
315 playback::compound_type *
kono
parents:
diff changeset
316 playback::context::
kono
parents:
diff changeset
317 new_compound_type (location *loc,
kono
parents:
diff changeset
318 const char *name,
kono
parents:
diff changeset
319 bool is_struct) /* else is union */
kono
parents:
diff changeset
320 {
kono
parents:
diff changeset
321 gcc_assert (name);
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 /* Compare with c/c-decl.c: start_struct. */
kono
parents:
diff changeset
324
kono
parents:
diff changeset
325 tree t = make_node (is_struct ? RECORD_TYPE : UNION_TYPE);
kono
parents:
diff changeset
326 TYPE_NAME (t) = get_identifier (name);
kono
parents:
diff changeset
327 TYPE_SIZE (t) = 0;
kono
parents:
diff changeset
328
kono
parents:
diff changeset
329 if (loc)
kono
parents:
diff changeset
330 set_tree_location (t, loc);
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 return new compound_type (t);
kono
parents:
diff changeset
333 }
kono
parents:
diff changeset
334
kono
parents:
diff changeset
335 void
kono
parents:
diff changeset
336 playback::compound_type::set_fields (const auto_vec<playback::field *> *fields)
kono
parents:
diff changeset
337 {
kono
parents:
diff changeset
338 /* Compare with c/c-decl.c: finish_struct. */
kono
parents:
diff changeset
339 tree t = as_tree ();
kono
parents:
diff changeset
340
kono
parents:
diff changeset
341 tree fieldlist = NULL;
kono
parents:
diff changeset
342 for (unsigned i = 0; i < fields->length (); i++)
kono
parents:
diff changeset
343 {
kono
parents:
diff changeset
344 field *f = (*fields)[i];
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
345 tree x = f->as_tree ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
346 DECL_CONTEXT (x) = t;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
347 if (DECL_JIT_BIT_FIELD (x))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
348 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
349 unsigned HOST_WIDE_INT width = tree_to_uhwi (DECL_INITIAL (x));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
350 DECL_SIZE (x) = bitsize_int (width);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
351 DECL_BIT_FIELD (x) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
352 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
353 fieldlist = chainon (x, fieldlist);
111
kono
parents:
diff changeset
354 }
kono
parents:
diff changeset
355 fieldlist = nreverse (fieldlist);
kono
parents:
diff changeset
356 TYPE_FIELDS (t) = fieldlist;
kono
parents:
diff changeset
357
kono
parents:
diff changeset
358 layout_type (t);
kono
parents:
diff changeset
359 }
kono
parents:
diff changeset
360
kono
parents:
diff changeset
361 /* Construct a playback::type instance (wrapping a tree) for a function
kono
parents:
diff changeset
362 type. */
kono
parents:
diff changeset
363
kono
parents:
diff changeset
364 playback::type *
kono
parents:
diff changeset
365 playback::context::
kono
parents:
diff changeset
366 new_function_type (type *return_type,
kono
parents:
diff changeset
367 const auto_vec<type *> *param_types,
kono
parents:
diff changeset
368 int is_variadic)
kono
parents:
diff changeset
369 {
kono
parents:
diff changeset
370 int i;
kono
parents:
diff changeset
371 type *param_type;
kono
parents:
diff changeset
372
kono
parents:
diff changeset
373 tree *arg_types = (tree *)xcalloc(param_types->length (), sizeof(tree*));
kono
parents:
diff changeset
374
kono
parents:
diff changeset
375 FOR_EACH_VEC_ELT (*param_types, i, param_type)
kono
parents:
diff changeset
376 arg_types[i] = param_type->as_tree ();
kono
parents:
diff changeset
377
kono
parents:
diff changeset
378 tree fn_type;
kono
parents:
diff changeset
379 if (is_variadic)
kono
parents:
diff changeset
380 fn_type =
kono
parents:
diff changeset
381 build_varargs_function_type_array (return_type->as_tree (),
kono
parents:
diff changeset
382 param_types->length (),
kono
parents:
diff changeset
383 arg_types);
kono
parents:
diff changeset
384 else
kono
parents:
diff changeset
385 fn_type = build_function_type_array (return_type->as_tree (),
kono
parents:
diff changeset
386 param_types->length (),
kono
parents:
diff changeset
387 arg_types);
kono
parents:
diff changeset
388 free (arg_types);
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 return new type (fn_type);
kono
parents:
diff changeset
391 }
kono
parents:
diff changeset
392
kono
parents:
diff changeset
393 /* Construct a playback::param instance (wrapping a tree). */
kono
parents:
diff changeset
394
kono
parents:
diff changeset
395 playback::param *
kono
parents:
diff changeset
396 playback::context::
kono
parents:
diff changeset
397 new_param (location *loc,
kono
parents:
diff changeset
398 type *type,
kono
parents:
diff changeset
399 const char *name)
kono
parents:
diff changeset
400 {
kono
parents:
diff changeset
401 gcc_assert (type);
kono
parents:
diff changeset
402 gcc_assert (name);
kono
parents:
diff changeset
403 tree inner = build_decl (UNKNOWN_LOCATION, PARM_DECL,
kono
parents:
diff changeset
404 get_identifier (name), type->as_tree ());
kono
parents:
diff changeset
405 if (loc)
kono
parents:
diff changeset
406 set_tree_location (inner, loc);
kono
parents:
diff changeset
407
kono
parents:
diff changeset
408 return new param (this, inner);
kono
parents:
diff changeset
409 }
kono
parents:
diff changeset
410
kono
parents:
diff changeset
411 /* Construct a playback::function instance. */
kono
parents:
diff changeset
412
kono
parents:
diff changeset
413 playback::function *
kono
parents:
diff changeset
414 playback::context::
kono
parents:
diff changeset
415 new_function (location *loc,
kono
parents:
diff changeset
416 enum gcc_jit_function_kind kind,
kono
parents:
diff changeset
417 type *return_type,
kono
parents:
diff changeset
418 const char *name,
kono
parents:
diff changeset
419 const auto_vec<param *> *params,
kono
parents:
diff changeset
420 int is_variadic,
kono
parents:
diff changeset
421 enum built_in_function builtin_id)
kono
parents:
diff changeset
422 {
kono
parents:
diff changeset
423 int i;
kono
parents:
diff changeset
424 param *param;
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 //can return_type be NULL?
kono
parents:
diff changeset
427 gcc_assert (name);
kono
parents:
diff changeset
428
kono
parents:
diff changeset
429 tree *arg_types = (tree *)xcalloc(params->length (), sizeof(tree*));
kono
parents:
diff changeset
430 FOR_EACH_VEC_ELT (*params, i, param)
kono
parents:
diff changeset
431 arg_types[i] = TREE_TYPE (param->as_tree ());
kono
parents:
diff changeset
432
kono
parents:
diff changeset
433 tree fn_type;
kono
parents:
diff changeset
434 if (is_variadic)
kono
parents:
diff changeset
435 fn_type = build_varargs_function_type_array (return_type->as_tree (),
kono
parents:
diff changeset
436 params->length (), arg_types);
kono
parents:
diff changeset
437 else
kono
parents:
diff changeset
438 fn_type = build_function_type_array (return_type->as_tree (),
kono
parents:
diff changeset
439 params->length (), arg_types);
kono
parents:
diff changeset
440 free (arg_types);
kono
parents:
diff changeset
441
kono
parents:
diff changeset
442 /* FIXME: this uses input_location: */
kono
parents:
diff changeset
443 tree fndecl = build_fn_decl (name, fn_type);
kono
parents:
diff changeset
444
kono
parents:
diff changeset
445 if (loc)
kono
parents:
diff changeset
446 set_tree_location (fndecl, loc);
kono
parents:
diff changeset
447
kono
parents:
diff changeset
448 tree resdecl = build_decl (UNKNOWN_LOCATION, RESULT_DECL,
kono
parents:
diff changeset
449 NULL_TREE, return_type->as_tree ());
kono
parents:
diff changeset
450 DECL_ARTIFICIAL (resdecl) = 1;
kono
parents:
diff changeset
451 DECL_IGNORED_P (resdecl) = 1;
kono
parents:
diff changeset
452 DECL_RESULT (fndecl) = resdecl;
kono
parents:
diff changeset
453
kono
parents:
diff changeset
454 if (builtin_id)
kono
parents:
diff changeset
455 {
kono
parents:
diff changeset
456 gcc_assert (loc == NULL);
kono
parents:
diff changeset
457 DECL_SOURCE_LOCATION (fndecl) = BUILTINS_LOCATION;
kono
parents:
diff changeset
458
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
459 built_in_class fclass = builtins_manager::get_class (builtin_id);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
460 set_decl_built_in_function (fndecl, fclass, builtin_id);
111
kono
parents:
diff changeset
461 set_builtin_decl (builtin_id, fndecl,
kono
parents:
diff changeset
462 builtins_manager::implicit_p (builtin_id));
kono
parents:
diff changeset
463
kono
parents:
diff changeset
464 builtins_manager *bm = get_builtins_manager ();
kono
parents:
diff changeset
465 tree attrs = bm->get_attrs_tree (builtin_id);
kono
parents:
diff changeset
466 if (attrs)
kono
parents:
diff changeset
467 decl_attributes (&fndecl, attrs, ATTR_FLAG_BUILT_IN);
kono
parents:
diff changeset
468 else
kono
parents:
diff changeset
469 decl_attributes (&fndecl, NULL_TREE, 0);
kono
parents:
diff changeset
470 }
kono
parents:
diff changeset
471
kono
parents:
diff changeset
472 if (kind != GCC_JIT_FUNCTION_IMPORTED)
kono
parents:
diff changeset
473 {
kono
parents:
diff changeset
474 tree param_decl_list = NULL;
kono
parents:
diff changeset
475 FOR_EACH_VEC_ELT (*params, i, param)
kono
parents:
diff changeset
476 {
kono
parents:
diff changeset
477 param_decl_list = chainon (param->as_tree (), param_decl_list);
kono
parents:
diff changeset
478 }
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 /* The param list was created in reverse order; fix it: */
kono
parents:
diff changeset
481 param_decl_list = nreverse (param_decl_list);
kono
parents:
diff changeset
482
kono
parents:
diff changeset
483 tree t;
kono
parents:
diff changeset
484 for (t = param_decl_list; t; t = DECL_CHAIN (t))
kono
parents:
diff changeset
485 {
kono
parents:
diff changeset
486 DECL_CONTEXT (t) = fndecl;
kono
parents:
diff changeset
487 DECL_ARG_TYPE (t) = TREE_TYPE (t);
kono
parents:
diff changeset
488 }
kono
parents:
diff changeset
489
kono
parents:
diff changeset
490 /* Set it up on DECL_ARGUMENTS */
kono
parents:
diff changeset
491 DECL_ARGUMENTS(fndecl) = param_decl_list;
kono
parents:
diff changeset
492 }
kono
parents:
diff changeset
493
kono
parents:
diff changeset
494 if (kind == GCC_JIT_FUNCTION_ALWAYS_INLINE)
kono
parents:
diff changeset
495 {
kono
parents:
diff changeset
496 DECL_DECLARED_INLINE_P (fndecl) = 1;
kono
parents:
diff changeset
497
kono
parents:
diff changeset
498 /* Add attribute "always_inline": */
kono
parents:
diff changeset
499 DECL_ATTRIBUTES (fndecl) =
kono
parents:
diff changeset
500 tree_cons (get_identifier ("always_inline"),
kono
parents:
diff changeset
501 NULL,
kono
parents:
diff changeset
502 DECL_ATTRIBUTES (fndecl));
kono
parents:
diff changeset
503 }
kono
parents:
diff changeset
504
kono
parents:
diff changeset
505 function *func = new function (this, fndecl, kind);
kono
parents:
diff changeset
506 m_functions.safe_push (func);
kono
parents:
diff changeset
507 return func;
kono
parents:
diff changeset
508 }
kono
parents:
diff changeset
509
kono
parents:
diff changeset
510 /* Construct a playback::lvalue instance (wrapping a tree). */
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 playback::lvalue *
kono
parents:
diff changeset
513 playback::context::
kono
parents:
diff changeset
514 new_global (location *loc,
kono
parents:
diff changeset
515 enum gcc_jit_global_kind kind,
kono
parents:
diff changeset
516 type *type,
kono
parents:
diff changeset
517 const char *name)
kono
parents:
diff changeset
518 {
kono
parents:
diff changeset
519 gcc_assert (type);
kono
parents:
diff changeset
520 gcc_assert (name);
kono
parents:
diff changeset
521 tree inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
kono
parents:
diff changeset
522 get_identifier (name),
kono
parents:
diff changeset
523 type->as_tree ());
kono
parents:
diff changeset
524 TREE_PUBLIC (inner) = (kind != GCC_JIT_GLOBAL_INTERNAL);
kono
parents:
diff changeset
525 DECL_COMMON (inner) = 1;
kono
parents:
diff changeset
526 switch (kind)
kono
parents:
diff changeset
527 {
kono
parents:
diff changeset
528 default:
kono
parents:
diff changeset
529 gcc_unreachable ();
kono
parents:
diff changeset
530
kono
parents:
diff changeset
531 case GCC_JIT_GLOBAL_EXPORTED:
kono
parents:
diff changeset
532 TREE_STATIC (inner) = 1;
kono
parents:
diff changeset
533 break;
kono
parents:
diff changeset
534
kono
parents:
diff changeset
535 case GCC_JIT_GLOBAL_INTERNAL:
kono
parents:
diff changeset
536 TREE_STATIC (inner) = 1;
kono
parents:
diff changeset
537 break;
kono
parents:
diff changeset
538
kono
parents:
diff changeset
539 case GCC_JIT_GLOBAL_IMPORTED:
kono
parents:
diff changeset
540 DECL_EXTERNAL (inner) = 1;
kono
parents:
diff changeset
541 break;
kono
parents:
diff changeset
542 }
kono
parents:
diff changeset
543
kono
parents:
diff changeset
544 if (loc)
kono
parents:
diff changeset
545 set_tree_location (inner, loc);
kono
parents:
diff changeset
546
kono
parents:
diff changeset
547 varpool_node::get_create (inner);
kono
parents:
diff changeset
548
kono
parents:
diff changeset
549 varpool_node::finalize_decl (inner);
kono
parents:
diff changeset
550
kono
parents:
diff changeset
551 m_globals.safe_push (inner);
kono
parents:
diff changeset
552
kono
parents:
diff changeset
553 return new lvalue (this, inner);
kono
parents:
diff changeset
554 }
kono
parents:
diff changeset
555
kono
parents:
diff changeset
556 /* Implementation of the various
kono
parents:
diff changeset
557 gcc::jit::playback::context::new_rvalue_from_const <HOST_TYPE>
kono
parents:
diff changeset
558 methods.
kono
parents:
diff changeset
559 Each of these constructs a playback::rvalue instance (wrapping a tree).
kono
parents:
diff changeset
560
kono
parents:
diff changeset
561 These specializations are required to be in the same namespace
kono
parents:
diff changeset
562 as the template, hence we now have to enter the gcc::jit::playback
kono
parents:
diff changeset
563 namespace. */
kono
parents:
diff changeset
564
kono
parents:
diff changeset
565 namespace playback
kono
parents:
diff changeset
566 {
kono
parents:
diff changeset
567
kono
parents:
diff changeset
568 /* Specialization of making an rvalue from a const, for host <int>. */
kono
parents:
diff changeset
569
kono
parents:
diff changeset
570 template <>
kono
parents:
diff changeset
571 rvalue *
kono
parents:
diff changeset
572 context::
kono
parents:
diff changeset
573 new_rvalue_from_const <int> (type *type,
kono
parents:
diff changeset
574 int value)
kono
parents:
diff changeset
575 {
kono
parents:
diff changeset
576 // FIXME: type-checking, or coercion?
kono
parents:
diff changeset
577 tree inner_type = type->as_tree ();
kono
parents:
diff changeset
578 if (INTEGRAL_TYPE_P (inner_type))
kono
parents:
diff changeset
579 {
kono
parents:
diff changeset
580 tree inner = build_int_cst (inner_type, value);
kono
parents:
diff changeset
581 return new rvalue (this, inner);
kono
parents:
diff changeset
582 }
kono
parents:
diff changeset
583 else
kono
parents:
diff changeset
584 {
kono
parents:
diff changeset
585 REAL_VALUE_TYPE real_value;
kono
parents:
diff changeset
586 real_from_integer (&real_value, VOIDmode, value, SIGNED);
kono
parents:
diff changeset
587 tree inner = build_real (inner_type, real_value);
kono
parents:
diff changeset
588 return new rvalue (this, inner);
kono
parents:
diff changeset
589 }
kono
parents:
diff changeset
590 }
kono
parents:
diff changeset
591
kono
parents:
diff changeset
592 /* Specialization of making an rvalue from a const, for host <long>. */
kono
parents:
diff changeset
593
kono
parents:
diff changeset
594 template <>
kono
parents:
diff changeset
595 rvalue *
kono
parents:
diff changeset
596 context::
kono
parents:
diff changeset
597 new_rvalue_from_const <long> (type *type,
kono
parents:
diff changeset
598 long value)
kono
parents:
diff changeset
599 {
kono
parents:
diff changeset
600 // FIXME: type-checking, or coercion?
kono
parents:
diff changeset
601 tree inner_type = type->as_tree ();
kono
parents:
diff changeset
602 if (INTEGRAL_TYPE_P (inner_type))
kono
parents:
diff changeset
603 {
kono
parents:
diff changeset
604 tree inner = build_int_cst (inner_type, value);
kono
parents:
diff changeset
605 return new rvalue (this, inner);
kono
parents:
diff changeset
606 }
kono
parents:
diff changeset
607 else
kono
parents:
diff changeset
608 {
kono
parents:
diff changeset
609 REAL_VALUE_TYPE real_value;
kono
parents:
diff changeset
610 real_from_integer (&real_value, VOIDmode, value, SIGNED);
kono
parents:
diff changeset
611 tree inner = build_real (inner_type, real_value);
kono
parents:
diff changeset
612 return new rvalue (this, inner);
kono
parents:
diff changeset
613 }
kono
parents:
diff changeset
614 }
kono
parents:
diff changeset
615
kono
parents:
diff changeset
616 /* Specialization of making an rvalue from a const, for host <double>. */
kono
parents:
diff changeset
617
kono
parents:
diff changeset
618 template <>
kono
parents:
diff changeset
619 rvalue *
kono
parents:
diff changeset
620 context::
kono
parents:
diff changeset
621 new_rvalue_from_const <double> (type *type,
kono
parents:
diff changeset
622 double value)
kono
parents:
diff changeset
623 {
kono
parents:
diff changeset
624 // FIXME: type-checking, or coercion?
kono
parents:
diff changeset
625 tree inner_type = type->as_tree ();
kono
parents:
diff changeset
626
kono
parents:
diff changeset
627 /* We have a "double", we want a REAL_VALUE_TYPE.
kono
parents:
diff changeset
628
kono
parents:
diff changeset
629 real.c:real_from_target appears to require the representation to be
kono
parents:
diff changeset
630 split into 32-bit values, and then sent as an pair of host long
kono
parents:
diff changeset
631 ints. */
kono
parents:
diff changeset
632 REAL_VALUE_TYPE real_value;
kono
parents:
diff changeset
633 union
kono
parents:
diff changeset
634 {
kono
parents:
diff changeset
635 double as_double;
kono
parents:
diff changeset
636 uint32_t as_uint32s[2];
kono
parents:
diff changeset
637 } u;
kono
parents:
diff changeset
638 u.as_double = value;
kono
parents:
diff changeset
639 long int as_long_ints[2];
kono
parents:
diff changeset
640 as_long_ints[0] = u.as_uint32s[0];
kono
parents:
diff changeset
641 as_long_ints[1] = u.as_uint32s[1];
kono
parents:
diff changeset
642 real_from_target (&real_value, as_long_ints, DFmode);
kono
parents:
diff changeset
643 tree inner = build_real (inner_type, real_value);
kono
parents:
diff changeset
644 return new rvalue (this, inner);
kono
parents:
diff changeset
645 }
kono
parents:
diff changeset
646
kono
parents:
diff changeset
647 /* Specialization of making an rvalue from a const, for host <void *>. */
kono
parents:
diff changeset
648
kono
parents:
diff changeset
649 template <>
kono
parents:
diff changeset
650 rvalue *
kono
parents:
diff changeset
651 context::
kono
parents:
diff changeset
652 new_rvalue_from_const <void *> (type *type,
kono
parents:
diff changeset
653 void *value)
kono
parents:
diff changeset
654 {
kono
parents:
diff changeset
655 tree inner_type = type->as_tree ();
kono
parents:
diff changeset
656 /* FIXME: how to ensure we have a wide enough type? */
kono
parents:
diff changeset
657 tree inner = build_int_cstu (inner_type, (unsigned HOST_WIDE_INT)value);
kono
parents:
diff changeset
658 return new rvalue (this, inner);
kono
parents:
diff changeset
659 }
kono
parents:
diff changeset
660
kono
parents:
diff changeset
661 /* We're done implementing the specializations of
kono
parents:
diff changeset
662 gcc::jit::playback::context::new_rvalue_from_const <T>
kono
parents:
diff changeset
663 so we can exit the gcc::jit::playback namespace. */
kono
parents:
diff changeset
664
kono
parents:
diff changeset
665 } // namespace playback
kono
parents:
diff changeset
666
kono
parents:
diff changeset
667 /* Construct a playback::rvalue instance (wrapping a tree). */
kono
parents:
diff changeset
668
kono
parents:
diff changeset
669 playback::rvalue *
kono
parents:
diff changeset
670 playback::context::
kono
parents:
diff changeset
671 new_string_literal (const char *value)
kono
parents:
diff changeset
672 {
kono
parents:
diff changeset
673 tree t_str = build_string (strlen (value), value);
kono
parents:
diff changeset
674 gcc_assert (m_char_array_type_node);
kono
parents:
diff changeset
675 TREE_TYPE (t_str) = m_char_array_type_node;
kono
parents:
diff changeset
676
kono
parents:
diff changeset
677 /* Convert to (const char*), loosely based on
kono
parents:
diff changeset
678 c/c-typeck.c: array_to_pointer_conversion,
kono
parents:
diff changeset
679 by taking address of start of string. */
kono
parents:
diff changeset
680 tree t_addr = build1 (ADDR_EXPR, m_const_char_ptr, t_str);
kono
parents:
diff changeset
681
kono
parents:
diff changeset
682 return new rvalue (this, t_addr);
kono
parents:
diff changeset
683 }
kono
parents:
diff changeset
684
kono
parents:
diff changeset
685 /* Construct a playback::rvalue instance (wrapping a tree) for a
kono
parents:
diff changeset
686 vector. */
kono
parents:
diff changeset
687
kono
parents:
diff changeset
688 playback::rvalue *
kono
parents:
diff changeset
689 playback::context::new_rvalue_from_vector (location *,
kono
parents:
diff changeset
690 type *type,
kono
parents:
diff changeset
691 const auto_vec<rvalue *> &elements)
kono
parents:
diff changeset
692 {
kono
parents:
diff changeset
693 vec<constructor_elt, va_gc> *v;
kono
parents:
diff changeset
694 vec_alloc (v, elements.length ());
kono
parents:
diff changeset
695 for (unsigned i = 0; i < elements.length (); ++i)
kono
parents:
diff changeset
696 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elements[i]->as_tree ());
kono
parents:
diff changeset
697 tree t_ctor = build_constructor (type->as_tree (), v);
kono
parents:
diff changeset
698 return new rvalue (this, t_ctor);
kono
parents:
diff changeset
699 }
kono
parents:
diff changeset
700
kono
parents:
diff changeset
701 /* Coerce a tree expression into a boolean tree expression. */
kono
parents:
diff changeset
702
kono
parents:
diff changeset
703 tree
kono
parents:
diff changeset
704 playback::context::
kono
parents:
diff changeset
705 as_truth_value (tree expr, location *loc)
kono
parents:
diff changeset
706 {
kono
parents:
diff changeset
707 /* Compare to c-typeck.c:c_objc_common_truthvalue_conversion */
kono
parents:
diff changeset
708 tree typed_zero = fold_build1 (CONVERT_EXPR,
kono
parents:
diff changeset
709 TREE_TYPE (expr),
kono
parents:
diff changeset
710 integer_zero_node);
kono
parents:
diff changeset
711 if (loc)
kono
parents:
diff changeset
712 set_tree_location (typed_zero, loc);
kono
parents:
diff changeset
713
kono
parents:
diff changeset
714 expr = build2 (NE_EXPR, integer_type_node, expr, typed_zero);
kono
parents:
diff changeset
715 if (loc)
kono
parents:
diff changeset
716 set_tree_location (expr, loc);
kono
parents:
diff changeset
717
kono
parents:
diff changeset
718 return expr;
kono
parents:
diff changeset
719 }
kono
parents:
diff changeset
720
kono
parents:
diff changeset
721 /* Construct a playback::rvalue instance (wrapping a tree) for a
kono
parents:
diff changeset
722 unary op. */
kono
parents:
diff changeset
723
kono
parents:
diff changeset
724 playback::rvalue *
kono
parents:
diff changeset
725 playback::context::
kono
parents:
diff changeset
726 new_unary_op (location *loc,
kono
parents:
diff changeset
727 enum gcc_jit_unary_op op,
kono
parents:
diff changeset
728 type *result_type,
kono
parents:
diff changeset
729 rvalue *a)
kono
parents:
diff changeset
730 {
kono
parents:
diff changeset
731 // FIXME: type-checking, or coercion?
kono
parents:
diff changeset
732 enum tree_code inner_op;
kono
parents:
diff changeset
733
kono
parents:
diff changeset
734 gcc_assert (result_type);
kono
parents:
diff changeset
735 gcc_assert (a);
kono
parents:
diff changeset
736
kono
parents:
diff changeset
737 tree node = a->as_tree ();
kono
parents:
diff changeset
738 tree inner_result = NULL;
kono
parents:
diff changeset
739
kono
parents:
diff changeset
740 switch (op)
kono
parents:
diff changeset
741 {
kono
parents:
diff changeset
742 default:
kono
parents:
diff changeset
743 add_error (loc, "unrecognized (enum gcc_jit_unary_op) value: %i", op);
kono
parents:
diff changeset
744 return NULL;
kono
parents:
diff changeset
745
kono
parents:
diff changeset
746 case GCC_JIT_UNARY_OP_MINUS:
kono
parents:
diff changeset
747 inner_op = NEGATE_EXPR;
kono
parents:
diff changeset
748 break;
kono
parents:
diff changeset
749
kono
parents:
diff changeset
750 case GCC_JIT_UNARY_OP_BITWISE_NEGATE:
kono
parents:
diff changeset
751 inner_op = BIT_NOT_EXPR;
kono
parents:
diff changeset
752 break;
kono
parents:
diff changeset
753
kono
parents:
diff changeset
754 case GCC_JIT_UNARY_OP_LOGICAL_NEGATE:
kono
parents:
diff changeset
755 node = as_truth_value (node, loc);
kono
parents:
diff changeset
756 inner_result = invert_truthvalue (node);
kono
parents:
diff changeset
757 if (loc)
kono
parents:
diff changeset
758 set_tree_location (inner_result, loc);
kono
parents:
diff changeset
759 return new rvalue (this, inner_result);
kono
parents:
diff changeset
760
kono
parents:
diff changeset
761 case GCC_JIT_UNARY_OP_ABS:
kono
parents:
diff changeset
762 inner_op = ABS_EXPR;
kono
parents:
diff changeset
763 break;
kono
parents:
diff changeset
764 }
kono
parents:
diff changeset
765
kono
parents:
diff changeset
766 inner_result = build1 (inner_op,
kono
parents:
diff changeset
767 result_type->as_tree (),
kono
parents:
diff changeset
768 node);
kono
parents:
diff changeset
769 if (loc)
kono
parents:
diff changeset
770 set_tree_location (inner_result, loc);
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772 return new rvalue (this, inner_result);
kono
parents:
diff changeset
773 }
kono
parents:
diff changeset
774
kono
parents:
diff changeset
775 /* Construct a playback::rvalue instance (wrapping a tree) for a
kono
parents:
diff changeset
776 binary op. */
kono
parents:
diff changeset
777
kono
parents:
diff changeset
778 playback::rvalue *
kono
parents:
diff changeset
779 playback::context::
kono
parents:
diff changeset
780 new_binary_op (location *loc,
kono
parents:
diff changeset
781 enum gcc_jit_binary_op op,
kono
parents:
diff changeset
782 type *result_type,
kono
parents:
diff changeset
783 rvalue *a, rvalue *b)
kono
parents:
diff changeset
784 {
kono
parents:
diff changeset
785 // FIXME: type-checking, or coercion?
kono
parents:
diff changeset
786 enum tree_code inner_op;
kono
parents:
diff changeset
787
kono
parents:
diff changeset
788 gcc_assert (result_type);
kono
parents:
diff changeset
789 gcc_assert (a);
kono
parents:
diff changeset
790 gcc_assert (b);
kono
parents:
diff changeset
791
kono
parents:
diff changeset
792 tree node_a = a->as_tree ();
kono
parents:
diff changeset
793 tree node_b = b->as_tree ();
kono
parents:
diff changeset
794
kono
parents:
diff changeset
795 switch (op)
kono
parents:
diff changeset
796 {
kono
parents:
diff changeset
797 default:
kono
parents:
diff changeset
798 add_error (loc, "unrecognized (enum gcc_jit_binary_op) value: %i", op);
kono
parents:
diff changeset
799 return NULL;
kono
parents:
diff changeset
800
kono
parents:
diff changeset
801 case GCC_JIT_BINARY_OP_PLUS:
kono
parents:
diff changeset
802 inner_op = PLUS_EXPR;
kono
parents:
diff changeset
803 break;
kono
parents:
diff changeset
804
kono
parents:
diff changeset
805 case GCC_JIT_BINARY_OP_MINUS:
kono
parents:
diff changeset
806 inner_op = MINUS_EXPR;
kono
parents:
diff changeset
807 break;
kono
parents:
diff changeset
808
kono
parents:
diff changeset
809 case GCC_JIT_BINARY_OP_MULT:
kono
parents:
diff changeset
810 inner_op = MULT_EXPR;
kono
parents:
diff changeset
811 break;
kono
parents:
diff changeset
812
kono
parents:
diff changeset
813 case GCC_JIT_BINARY_OP_DIVIDE:
kono
parents:
diff changeset
814 if (FLOAT_TYPE_P (result_type->as_tree ()))
kono
parents:
diff changeset
815 /* Floating-point division: */
kono
parents:
diff changeset
816 inner_op = RDIV_EXPR;
kono
parents:
diff changeset
817 else
kono
parents:
diff changeset
818 /* Truncating to zero: */
kono
parents:
diff changeset
819 inner_op = TRUNC_DIV_EXPR;
kono
parents:
diff changeset
820 break;
kono
parents:
diff changeset
821
kono
parents:
diff changeset
822 case GCC_JIT_BINARY_OP_MODULO:
kono
parents:
diff changeset
823 inner_op = TRUNC_MOD_EXPR;
kono
parents:
diff changeset
824 break;
kono
parents:
diff changeset
825
kono
parents:
diff changeset
826 case GCC_JIT_BINARY_OP_BITWISE_AND:
kono
parents:
diff changeset
827 inner_op = BIT_AND_EXPR;
kono
parents:
diff changeset
828 break;
kono
parents:
diff changeset
829
kono
parents:
diff changeset
830 case GCC_JIT_BINARY_OP_BITWISE_XOR:
kono
parents:
diff changeset
831 inner_op = BIT_XOR_EXPR;
kono
parents:
diff changeset
832 break;
kono
parents:
diff changeset
833
kono
parents:
diff changeset
834 case GCC_JIT_BINARY_OP_BITWISE_OR:
kono
parents:
diff changeset
835 inner_op = BIT_IOR_EXPR;
kono
parents:
diff changeset
836 break;
kono
parents:
diff changeset
837
kono
parents:
diff changeset
838 case GCC_JIT_BINARY_OP_LOGICAL_AND:
kono
parents:
diff changeset
839 node_a = as_truth_value (node_a, loc);
kono
parents:
diff changeset
840 node_b = as_truth_value (node_b, loc);
kono
parents:
diff changeset
841 inner_op = TRUTH_ANDIF_EXPR;
kono
parents:
diff changeset
842 break;
kono
parents:
diff changeset
843
kono
parents:
diff changeset
844 case GCC_JIT_BINARY_OP_LOGICAL_OR:
kono
parents:
diff changeset
845 node_a = as_truth_value (node_a, loc);
kono
parents:
diff changeset
846 node_b = as_truth_value (node_b, loc);
kono
parents:
diff changeset
847 inner_op = TRUTH_ORIF_EXPR;
kono
parents:
diff changeset
848 break;
kono
parents:
diff changeset
849
kono
parents:
diff changeset
850 case GCC_JIT_BINARY_OP_LSHIFT:
kono
parents:
diff changeset
851 inner_op = LSHIFT_EXPR;
kono
parents:
diff changeset
852 break;
kono
parents:
diff changeset
853
kono
parents:
diff changeset
854 case GCC_JIT_BINARY_OP_RSHIFT:
kono
parents:
diff changeset
855 inner_op = RSHIFT_EXPR;
kono
parents:
diff changeset
856 break;
kono
parents:
diff changeset
857 }
kono
parents:
diff changeset
858
kono
parents:
diff changeset
859 tree inner_expr = build2 (inner_op,
kono
parents:
diff changeset
860 result_type->as_tree (),
kono
parents:
diff changeset
861 node_a,
kono
parents:
diff changeset
862 node_b);
kono
parents:
diff changeset
863 if (loc)
kono
parents:
diff changeset
864 set_tree_location (inner_expr, loc);
kono
parents:
diff changeset
865
kono
parents:
diff changeset
866 return new rvalue (this, inner_expr);
kono
parents:
diff changeset
867 }
kono
parents:
diff changeset
868
kono
parents:
diff changeset
869 /* Construct a playback::rvalue instance (wrapping a tree) for a
kono
parents:
diff changeset
870 comparison. */
kono
parents:
diff changeset
871
kono
parents:
diff changeset
872 playback::rvalue *
kono
parents:
diff changeset
873 playback::context::
kono
parents:
diff changeset
874 new_comparison (location *loc,
kono
parents:
diff changeset
875 enum gcc_jit_comparison op,
kono
parents:
diff changeset
876 rvalue *a, rvalue *b)
kono
parents:
diff changeset
877 {
kono
parents:
diff changeset
878 // FIXME: type-checking, or coercion?
kono
parents:
diff changeset
879 enum tree_code inner_op;
kono
parents:
diff changeset
880
kono
parents:
diff changeset
881 gcc_assert (a);
kono
parents:
diff changeset
882 gcc_assert (b);
kono
parents:
diff changeset
883
kono
parents:
diff changeset
884 switch (op)
kono
parents:
diff changeset
885 {
kono
parents:
diff changeset
886 default:
kono
parents:
diff changeset
887 add_error (loc, "unrecognized (enum gcc_jit_comparison) value: %i", op);
kono
parents:
diff changeset
888 return NULL;
kono
parents:
diff changeset
889
kono
parents:
diff changeset
890 case GCC_JIT_COMPARISON_EQ:
kono
parents:
diff changeset
891 inner_op = EQ_EXPR;
kono
parents:
diff changeset
892 break;
kono
parents:
diff changeset
893 case GCC_JIT_COMPARISON_NE:
kono
parents:
diff changeset
894 inner_op = NE_EXPR;
kono
parents:
diff changeset
895 break;
kono
parents:
diff changeset
896 case GCC_JIT_COMPARISON_LT:
kono
parents:
diff changeset
897 inner_op = LT_EXPR;
kono
parents:
diff changeset
898 break;
kono
parents:
diff changeset
899 case GCC_JIT_COMPARISON_LE:
kono
parents:
diff changeset
900 inner_op = LE_EXPR;
kono
parents:
diff changeset
901 break;
kono
parents:
diff changeset
902 case GCC_JIT_COMPARISON_GT:
kono
parents:
diff changeset
903 inner_op = GT_EXPR;
kono
parents:
diff changeset
904 break;
kono
parents:
diff changeset
905 case GCC_JIT_COMPARISON_GE:
kono
parents:
diff changeset
906 inner_op = GE_EXPR;
kono
parents:
diff changeset
907 break;
kono
parents:
diff changeset
908 }
kono
parents:
diff changeset
909
kono
parents:
diff changeset
910 tree inner_expr = build2 (inner_op,
kono
parents:
diff changeset
911 boolean_type_node,
kono
parents:
diff changeset
912 a->as_tree (),
kono
parents:
diff changeset
913 b->as_tree ());
kono
parents:
diff changeset
914 if (loc)
kono
parents:
diff changeset
915 set_tree_location (inner_expr, loc);
kono
parents:
diff changeset
916 return new rvalue (this, inner_expr);
kono
parents:
diff changeset
917 }
kono
parents:
diff changeset
918
kono
parents:
diff changeset
919 /* Construct a playback::rvalue instance (wrapping a tree) for a
kono
parents:
diff changeset
920 function call. */
kono
parents:
diff changeset
921
kono
parents:
diff changeset
922 playback::rvalue *
kono
parents:
diff changeset
923 playback::context::
kono
parents:
diff changeset
924 build_call (location *loc,
kono
parents:
diff changeset
925 tree fn_ptr,
kono
parents:
diff changeset
926 const auto_vec<rvalue *> *args,
kono
parents:
diff changeset
927 bool require_tail_call)
kono
parents:
diff changeset
928 {
kono
parents:
diff changeset
929 vec<tree, va_gc> *tree_args;
kono
parents:
diff changeset
930 vec_alloc (tree_args, args->length ());
kono
parents:
diff changeset
931 for (unsigned i = 0; i < args->length (); i++)
kono
parents:
diff changeset
932 tree_args->quick_push ((*args)[i]->as_tree ());
kono
parents:
diff changeset
933
kono
parents:
diff changeset
934 if (loc)
kono
parents:
diff changeset
935 set_tree_location (fn_ptr, loc);
kono
parents:
diff changeset
936
kono
parents:
diff changeset
937 tree fn = TREE_TYPE (fn_ptr);
kono
parents:
diff changeset
938 tree fn_type = TREE_TYPE (fn);
kono
parents:
diff changeset
939 tree return_type = TREE_TYPE (fn_type);
kono
parents:
diff changeset
940
kono
parents:
diff changeset
941 tree call = build_call_vec (return_type,
kono
parents:
diff changeset
942 fn_ptr, tree_args);
kono
parents:
diff changeset
943
kono
parents:
diff changeset
944 if (require_tail_call)
kono
parents:
diff changeset
945 CALL_EXPR_MUST_TAIL_CALL (call) = 1;
kono
parents:
diff changeset
946
kono
parents:
diff changeset
947 return new rvalue (this, call);
kono
parents:
diff changeset
948
kono
parents:
diff changeset
949 /* see c-typeck.c: build_function_call
kono
parents:
diff changeset
950 which calls build_function_call_vec
kono
parents:
diff changeset
951
kono
parents:
diff changeset
952 which does lots of checking, then:
kono
parents:
diff changeset
953 result = build_call_array_loc (loc, TREE_TYPE (fntype),
kono
parents:
diff changeset
954 function, nargs, argarray);
kono
parents:
diff changeset
955 which is in tree.c
kono
parents:
diff changeset
956 (see also build_call_vec)
kono
parents:
diff changeset
957 */
kono
parents:
diff changeset
958 }
kono
parents:
diff changeset
959
kono
parents:
diff changeset
960 /* Construct a playback::rvalue instance (wrapping a tree) for a
kono
parents:
diff changeset
961 call to a specific function. */
kono
parents:
diff changeset
962
kono
parents:
diff changeset
963 playback::rvalue *
kono
parents:
diff changeset
964 playback::context::
kono
parents:
diff changeset
965 new_call (location *loc,
kono
parents:
diff changeset
966 function *func,
kono
parents:
diff changeset
967 const auto_vec<rvalue *> *args,
kono
parents:
diff changeset
968 bool require_tail_call)
kono
parents:
diff changeset
969 {
kono
parents:
diff changeset
970 tree fndecl;
kono
parents:
diff changeset
971
kono
parents:
diff changeset
972 gcc_assert (func);
kono
parents:
diff changeset
973
kono
parents:
diff changeset
974 fndecl = func->as_fndecl ();
kono
parents:
diff changeset
975
kono
parents:
diff changeset
976 tree fntype = TREE_TYPE (fndecl);
kono
parents:
diff changeset
977
kono
parents:
diff changeset
978 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
kono
parents:
diff changeset
979
kono
parents:
diff changeset
980 return build_call (loc, fn, args, require_tail_call);
kono
parents:
diff changeset
981 }
kono
parents:
diff changeset
982
kono
parents:
diff changeset
983 /* Construct a playback::rvalue instance (wrapping a tree) for a
kono
parents:
diff changeset
984 call through a function pointer. */
kono
parents:
diff changeset
985
kono
parents:
diff changeset
986 playback::rvalue *
kono
parents:
diff changeset
987 playback::context::
kono
parents:
diff changeset
988 new_call_through_ptr (location *loc,
kono
parents:
diff changeset
989 rvalue *fn_ptr,
kono
parents:
diff changeset
990 const auto_vec<rvalue *> *args,
kono
parents:
diff changeset
991 bool require_tail_call)
kono
parents:
diff changeset
992 {
kono
parents:
diff changeset
993 gcc_assert (fn_ptr);
kono
parents:
diff changeset
994 tree t_fn_ptr = fn_ptr->as_tree ();
kono
parents:
diff changeset
995
kono
parents:
diff changeset
996 return build_call (loc, t_fn_ptr, args, require_tail_call);
kono
parents:
diff changeset
997 }
kono
parents:
diff changeset
998
kono
parents:
diff changeset
999 /* Construct a tree for a cast. */
kono
parents:
diff changeset
1000
kono
parents:
diff changeset
1001 tree
kono
parents:
diff changeset
1002 playback::context::build_cast (playback::location *loc,
kono
parents:
diff changeset
1003 playback::rvalue *expr,
kono
parents:
diff changeset
1004 playback::type *type_)
kono
parents:
diff changeset
1005 {
kono
parents:
diff changeset
1006 /* For comparison, see:
kono
parents:
diff changeset
1007 - c/c-typeck.c:build_c_cast
kono
parents:
diff changeset
1008 - c/c-convert.c: convert
kono
parents:
diff changeset
1009 - convert.h
kono
parents:
diff changeset
1010
kono
parents:
diff changeset
1011 Only some kinds of cast are currently supported here. */
kono
parents:
diff changeset
1012 tree t_expr = expr->as_tree ();
kono
parents:
diff changeset
1013 tree t_dst_type = type_->as_tree ();
kono
parents:
diff changeset
1014 tree t_ret = NULL;
kono
parents:
diff changeset
1015 t_ret = targetm.convert_to_type (t_dst_type, t_expr);
kono
parents:
diff changeset
1016 if (t_ret)
kono
parents:
diff changeset
1017 return t_ret;
kono
parents:
diff changeset
1018 enum tree_code dst_code = TREE_CODE (t_dst_type);
kono
parents:
diff changeset
1019 switch (dst_code)
kono
parents:
diff changeset
1020 {
kono
parents:
diff changeset
1021 case INTEGER_TYPE:
kono
parents:
diff changeset
1022 case ENUMERAL_TYPE:
kono
parents:
diff changeset
1023 t_ret = convert_to_integer (t_dst_type, t_expr);
kono
parents:
diff changeset
1024 goto maybe_fold;
kono
parents:
diff changeset
1025
kono
parents:
diff changeset
1026 case BOOLEAN_TYPE:
kono
parents:
diff changeset
1027 /* Compare with c_objc_common_truthvalue_conversion and
kono
parents:
diff changeset
1028 c_common_truthvalue_conversion. */
kono
parents:
diff changeset
1029 /* For now, convert to: (t_expr != 0) */
kono
parents:
diff changeset
1030 t_ret = build2 (NE_EXPR, t_dst_type,
kono
parents:
diff changeset
1031 t_expr,
kono
parents:
diff changeset
1032 build_int_cst (TREE_TYPE (t_expr), 0));
kono
parents:
diff changeset
1033 goto maybe_fold;
kono
parents:
diff changeset
1034
kono
parents:
diff changeset
1035 case REAL_TYPE:
kono
parents:
diff changeset
1036 t_ret = convert_to_real (t_dst_type, t_expr);
kono
parents:
diff changeset
1037 goto maybe_fold;
kono
parents:
diff changeset
1038
kono
parents:
diff changeset
1039 case POINTER_TYPE:
kono
parents:
diff changeset
1040 t_ret = build1 (NOP_EXPR, t_dst_type, t_expr);
kono
parents:
diff changeset
1041 goto maybe_fold;
kono
parents:
diff changeset
1042
kono
parents:
diff changeset
1043 default:
kono
parents:
diff changeset
1044 add_error (loc, "couldn't handle cast during playback");
kono
parents:
diff changeset
1045 fprintf (stderr, "input expression:\n");
kono
parents:
diff changeset
1046 debug_tree (t_expr);
kono
parents:
diff changeset
1047 fprintf (stderr, "requested type:\n");
kono
parents:
diff changeset
1048 debug_tree (t_dst_type);
kono
parents:
diff changeset
1049 return error_mark_node;
kono
parents:
diff changeset
1050
kono
parents:
diff changeset
1051 maybe_fold:
kono
parents:
diff changeset
1052 if (TREE_CODE (t_ret) != C_MAYBE_CONST_EXPR)
kono
parents:
diff changeset
1053 t_ret = fold (t_ret);
kono
parents:
diff changeset
1054 return t_ret;
kono
parents:
diff changeset
1055 }
kono
parents:
diff changeset
1056 }
kono
parents:
diff changeset
1057
kono
parents:
diff changeset
1058 /* Construct a playback::rvalue instance (wrapping a tree) for a
kono
parents:
diff changeset
1059 cast. */
kono
parents:
diff changeset
1060
kono
parents:
diff changeset
1061 playback::rvalue *
kono
parents:
diff changeset
1062 playback::context::
kono
parents:
diff changeset
1063 new_cast (playback::location *loc,
kono
parents:
diff changeset
1064 playback::rvalue *expr,
kono
parents:
diff changeset
1065 playback::type *type_)
kono
parents:
diff changeset
1066 {
kono
parents:
diff changeset
1067
kono
parents:
diff changeset
1068 tree t_cast = build_cast (loc, expr, type_);
kono
parents:
diff changeset
1069 if (loc)
kono
parents:
diff changeset
1070 set_tree_location (t_cast, loc);
kono
parents:
diff changeset
1071 return new rvalue (this, t_cast);
kono
parents:
diff changeset
1072 }
kono
parents:
diff changeset
1073
kono
parents:
diff changeset
1074 /* Construct a playback::lvalue instance (wrapping a tree) for an
kono
parents:
diff changeset
1075 array access. */
kono
parents:
diff changeset
1076
kono
parents:
diff changeset
1077 playback::lvalue *
kono
parents:
diff changeset
1078 playback::context::
kono
parents:
diff changeset
1079 new_array_access (location *loc,
kono
parents:
diff changeset
1080 rvalue *ptr,
kono
parents:
diff changeset
1081 rvalue *index)
kono
parents:
diff changeset
1082 {
kono
parents:
diff changeset
1083 gcc_assert (ptr);
kono
parents:
diff changeset
1084 gcc_assert (index);
kono
parents:
diff changeset
1085
kono
parents:
diff changeset
1086 /* For comparison, see:
kono
parents:
diff changeset
1087 c/c-typeck.c: build_array_ref
kono
parents:
diff changeset
1088 c-family/c-common.c: pointer_int_sum
kono
parents:
diff changeset
1089 */
kono
parents:
diff changeset
1090 tree t_ptr = ptr->as_tree ();
kono
parents:
diff changeset
1091 tree t_index = index->as_tree ();
kono
parents:
diff changeset
1092 tree t_type_ptr = TREE_TYPE (t_ptr);
kono
parents:
diff changeset
1093 tree t_type_star_ptr = TREE_TYPE (t_type_ptr);
kono
parents:
diff changeset
1094
kono
parents:
diff changeset
1095 if (TREE_CODE (t_type_ptr) == ARRAY_TYPE)
kono
parents:
diff changeset
1096 {
kono
parents:
diff changeset
1097 tree t_result = build4 (ARRAY_REF, t_type_star_ptr, t_ptr, t_index,
kono
parents:
diff changeset
1098 NULL_TREE, NULL_TREE);
kono
parents:
diff changeset
1099 if (loc)
kono
parents:
diff changeset
1100 set_tree_location (t_result, loc);
kono
parents:
diff changeset
1101 return new lvalue (this, t_result);
kono
parents:
diff changeset
1102 }
kono
parents:
diff changeset
1103 else
kono
parents:
diff changeset
1104 {
kono
parents:
diff changeset
1105 /* Convert index to an offset in bytes. */
kono
parents:
diff changeset
1106 tree t_sizeof = size_in_bytes (t_type_star_ptr);
kono
parents:
diff changeset
1107 t_index = fold_build1 (CONVERT_EXPR, sizetype, t_index);
kono
parents:
diff changeset
1108 tree t_offset = build2 (MULT_EXPR, sizetype, t_index, t_sizeof);
kono
parents:
diff changeset
1109
kono
parents:
diff changeset
1110 /* Locate (ptr + offset). */
kono
parents:
diff changeset
1111 tree t_address = build2 (POINTER_PLUS_EXPR, t_type_ptr, t_ptr, t_offset);
kono
parents:
diff changeset
1112
kono
parents:
diff changeset
1113 tree t_indirection = build1 (INDIRECT_REF, t_type_star_ptr, t_address);
kono
parents:
diff changeset
1114 if (loc)
kono
parents:
diff changeset
1115 {
kono
parents:
diff changeset
1116 set_tree_location (t_sizeof, loc);
kono
parents:
diff changeset
1117 set_tree_location (t_offset, loc);
kono
parents:
diff changeset
1118 set_tree_location (t_address, loc);
kono
parents:
diff changeset
1119 set_tree_location (t_indirection, loc);
kono
parents:
diff changeset
1120 }
kono
parents:
diff changeset
1121
kono
parents:
diff changeset
1122 return new lvalue (this, t_indirection);
kono
parents:
diff changeset
1123 }
kono
parents:
diff changeset
1124 }
kono
parents:
diff changeset
1125
kono
parents:
diff changeset
1126 /* Construct a tree for a field access. */
kono
parents:
diff changeset
1127
kono
parents:
diff changeset
1128 tree
kono
parents:
diff changeset
1129 playback::context::
kono
parents:
diff changeset
1130 new_field_access (location *loc,
kono
parents:
diff changeset
1131 tree datum,
kono
parents:
diff changeset
1132 field *field)
kono
parents:
diff changeset
1133 {
kono
parents:
diff changeset
1134 gcc_assert (datum);
kono
parents:
diff changeset
1135 gcc_assert (field);
kono
parents:
diff changeset
1136
kono
parents:
diff changeset
1137 /* Compare with c/c-typeck.c:lookup_field, build_indirect_ref, and
kono
parents:
diff changeset
1138 build_component_ref. */
kono
parents:
diff changeset
1139 tree type = TREE_TYPE (datum);
kono
parents:
diff changeset
1140 gcc_assert (type);
kono
parents:
diff changeset
1141 gcc_assert (TREE_CODE (type) != POINTER_TYPE);
kono
parents:
diff changeset
1142
kono
parents:
diff changeset
1143 tree t_field = field->as_tree ();
kono
parents:
diff changeset
1144 tree ref = build3 (COMPONENT_REF, TREE_TYPE (t_field), datum,
kono
parents:
diff changeset
1145 t_field, NULL_TREE);
kono
parents:
diff changeset
1146 if (loc)
kono
parents:
diff changeset
1147 set_tree_location (ref, loc);
kono
parents:
diff changeset
1148 return ref;
kono
parents:
diff changeset
1149 }
kono
parents:
diff changeset
1150
kono
parents:
diff changeset
1151 /* Construct a tree for a dereference. */
kono
parents:
diff changeset
1152
kono
parents:
diff changeset
1153 tree
kono
parents:
diff changeset
1154 playback::context::
kono
parents:
diff changeset
1155 new_dereference (tree ptr,
kono
parents:
diff changeset
1156 location *loc)
kono
parents:
diff changeset
1157 {
kono
parents:
diff changeset
1158 gcc_assert (ptr);
kono
parents:
diff changeset
1159
kono
parents:
diff changeset
1160 tree type = TREE_TYPE (TREE_TYPE(ptr));
kono
parents:
diff changeset
1161 tree datum = build1 (INDIRECT_REF, type, ptr);
kono
parents:
diff changeset
1162 if (loc)
kono
parents:
diff changeset
1163 set_tree_location (datum, loc);
kono
parents:
diff changeset
1164 return datum;
kono
parents:
diff changeset
1165 }
kono
parents:
diff changeset
1166
kono
parents:
diff changeset
1167 /* Construct a playback::type instance (wrapping a tree)
kono
parents:
diff changeset
1168 with the given alignment. */
kono
parents:
diff changeset
1169
kono
parents:
diff changeset
1170 playback::type *
kono
parents:
diff changeset
1171 playback::type::
kono
parents:
diff changeset
1172 get_aligned (size_t alignment_in_bytes) const
kono
parents:
diff changeset
1173 {
kono
parents:
diff changeset
1174 tree t_new_type = build_variant_type_copy (m_inner);
kono
parents:
diff changeset
1175
kono
parents:
diff changeset
1176 SET_TYPE_ALIGN (t_new_type, alignment_in_bytes * BITS_PER_UNIT);
kono
parents:
diff changeset
1177 TYPE_USER_ALIGN (t_new_type) = 1;
kono
parents:
diff changeset
1178
kono
parents:
diff changeset
1179 return new type (t_new_type);
kono
parents:
diff changeset
1180 }
kono
parents:
diff changeset
1181
kono
parents:
diff changeset
1182 /* Construct a playback::type instance (wrapping a tree)
kono
parents:
diff changeset
1183 for the given vector type. */
kono
parents:
diff changeset
1184
kono
parents:
diff changeset
1185 playback::type *
kono
parents:
diff changeset
1186 playback::type::
kono
parents:
diff changeset
1187 get_vector (size_t num_units) const
kono
parents:
diff changeset
1188 {
kono
parents:
diff changeset
1189 tree t_new_type = build_vector_type (m_inner, num_units);
kono
parents:
diff changeset
1190 return new type (t_new_type);
kono
parents:
diff changeset
1191 }
kono
parents:
diff changeset
1192
kono
parents:
diff changeset
1193 /* Construct a playback::lvalue instance (wrapping a tree) for a
kono
parents:
diff changeset
1194 field access. */
kono
parents:
diff changeset
1195
kono
parents:
diff changeset
1196 playback::lvalue *
kono
parents:
diff changeset
1197 playback::lvalue::
kono
parents:
diff changeset
1198 access_field (location *loc,
kono
parents:
diff changeset
1199 field *field)
kono
parents:
diff changeset
1200 {
kono
parents:
diff changeset
1201 tree datum = as_tree ();
kono
parents:
diff changeset
1202 tree ref = get_context ()->new_field_access (loc, datum, field);
kono
parents:
diff changeset
1203 if (!ref)
kono
parents:
diff changeset
1204 return NULL;
kono
parents:
diff changeset
1205 return new lvalue (get_context (), ref);
kono
parents:
diff changeset
1206 }
kono
parents:
diff changeset
1207
kono
parents:
diff changeset
1208 /* Construct a playback::rvalue instance (wrapping a tree) for a
kono
parents:
diff changeset
1209 field access. */
kono
parents:
diff changeset
1210
kono
parents:
diff changeset
1211 playback::rvalue *
kono
parents:
diff changeset
1212 playback::rvalue::
kono
parents:
diff changeset
1213 access_field (location *loc,
kono
parents:
diff changeset
1214 field *field)
kono
parents:
diff changeset
1215 {
kono
parents:
diff changeset
1216 tree datum = as_tree ();
kono
parents:
diff changeset
1217 tree ref = get_context ()->new_field_access (loc, datum, field);
kono
parents:
diff changeset
1218 if (!ref)
kono
parents:
diff changeset
1219 return NULL;
kono
parents:
diff changeset
1220 return new rvalue (get_context (), ref);
kono
parents:
diff changeset
1221 }
kono
parents:
diff changeset
1222
kono
parents:
diff changeset
1223 /* Construct a playback::lvalue instance (wrapping a tree) for a
kono
parents:
diff changeset
1224 dereferenced field access. */
kono
parents:
diff changeset
1225
kono
parents:
diff changeset
1226 playback::lvalue *
kono
parents:
diff changeset
1227 playback::rvalue::
kono
parents:
diff changeset
1228 dereference_field (location *loc,
kono
parents:
diff changeset
1229 field *field)
kono
parents:
diff changeset
1230 {
kono
parents:
diff changeset
1231 tree ptr = as_tree ();
kono
parents:
diff changeset
1232 tree datum = get_context ()->new_dereference (ptr, loc);
kono
parents:
diff changeset
1233 if (!datum)
kono
parents:
diff changeset
1234 return NULL;
kono
parents:
diff changeset
1235 tree ref = get_context ()->new_field_access (loc, datum, field);
kono
parents:
diff changeset
1236 if (!ref)
kono
parents:
diff changeset
1237 return NULL;
kono
parents:
diff changeset
1238 return new lvalue (get_context (), ref);
kono
parents:
diff changeset
1239 }
kono
parents:
diff changeset
1240
kono
parents:
diff changeset
1241 /* Construct a playback::lvalue instance (wrapping a tree) for a
kono
parents:
diff changeset
1242 dereference. */
kono
parents:
diff changeset
1243
kono
parents:
diff changeset
1244 playback::lvalue *
kono
parents:
diff changeset
1245 playback::rvalue::
kono
parents:
diff changeset
1246 dereference (location *loc)
kono
parents:
diff changeset
1247 {
kono
parents:
diff changeset
1248 tree ptr = as_tree ();
kono
parents:
diff changeset
1249 tree datum = get_context ()->new_dereference (ptr, loc);
kono
parents:
diff changeset
1250 return new lvalue (get_context (), datum);
kono
parents:
diff changeset
1251 }
kono
parents:
diff changeset
1252
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1253 /* Mark the lvalue saying that we need to be able to take the
111
kono
parents:
diff changeset
1254 address of it; it should not be allocated in a register.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1255 Compare with e.g. c/c-typeck.c: c_mark_addressable really_atomic_lvalue.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1256 Returns false if a failure occurred (an error will already have been
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1257 added to the active context for this case). */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1258
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1259 bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1260 playback::lvalue::
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1261 mark_addressable (location *loc)
111
kono
parents:
diff changeset
1262 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1263 tree x = as_tree ();;
111
kono
parents:
diff changeset
1264
kono
parents:
diff changeset
1265 while (1)
kono
parents:
diff changeset
1266 switch (TREE_CODE (x))
kono
parents:
diff changeset
1267 {
kono
parents:
diff changeset
1268 case COMPONENT_REF:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1269 if (DECL_JIT_BIT_FIELD (TREE_OPERAND (x, 1)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1270 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1271 gcc_assert (gcc::jit::active_playback_ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1272 gcc::jit::
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1273 active_playback_ctxt->add_error (loc,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1274 "cannot take address of "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1275 "bit-field");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1276 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1277 }
111
kono
parents:
diff changeset
1278 /* fallthrough */
kono
parents:
diff changeset
1279 case ADDR_EXPR:
kono
parents:
diff changeset
1280 case ARRAY_REF:
kono
parents:
diff changeset
1281 case REALPART_EXPR:
kono
parents:
diff changeset
1282 case IMAGPART_EXPR:
kono
parents:
diff changeset
1283 x = TREE_OPERAND (x, 0);
kono
parents:
diff changeset
1284 break;
kono
parents:
diff changeset
1285
kono
parents:
diff changeset
1286 case COMPOUND_LITERAL_EXPR:
kono
parents:
diff changeset
1287 case CONSTRUCTOR:
kono
parents:
diff changeset
1288 TREE_ADDRESSABLE (x) = 1;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1289 return true;
111
kono
parents:
diff changeset
1290
kono
parents:
diff changeset
1291 case VAR_DECL:
kono
parents:
diff changeset
1292 case CONST_DECL:
kono
parents:
diff changeset
1293 case PARM_DECL:
kono
parents:
diff changeset
1294 case RESULT_DECL:
kono
parents:
diff changeset
1295 /* (we don't have a concept of a "register" declaration) */
kono
parents:
diff changeset
1296 /* fallthrough */
kono
parents:
diff changeset
1297 case FUNCTION_DECL:
kono
parents:
diff changeset
1298 TREE_ADDRESSABLE (x) = 1;
kono
parents:
diff changeset
1299 /* fallthrough */
kono
parents:
diff changeset
1300 default:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1301 return true;
111
kono
parents:
diff changeset
1302 }
kono
parents:
diff changeset
1303 }
kono
parents:
diff changeset
1304
kono
parents:
diff changeset
1305 /* Construct a playback::rvalue instance (wrapping a tree) for an
kono
parents:
diff changeset
1306 address-lookup. */
kono
parents:
diff changeset
1307
kono
parents:
diff changeset
1308 playback::rvalue *
kono
parents:
diff changeset
1309 playback::lvalue::
kono
parents:
diff changeset
1310 get_address (location *loc)
kono
parents:
diff changeset
1311 {
kono
parents:
diff changeset
1312 tree t_lvalue = as_tree ();
kono
parents:
diff changeset
1313 tree t_thistype = TREE_TYPE (t_lvalue);
kono
parents:
diff changeset
1314 tree t_ptrtype = build_pointer_type (t_thistype);
kono
parents:
diff changeset
1315 tree ptr = build1 (ADDR_EXPR, t_ptrtype, t_lvalue);
kono
parents:
diff changeset
1316 if (loc)
kono
parents:
diff changeset
1317 get_context ()->set_tree_location (ptr, loc);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1318 if (mark_addressable (loc))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1319 return new rvalue (get_context (), ptr);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1320 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1321 return NULL;
111
kono
parents:
diff changeset
1322 }
kono
parents:
diff changeset
1323
kono
parents:
diff changeset
1324 /* The wrapper subclasses are GC-managed, but can own non-GC memory.
kono
parents:
diff changeset
1325 Provide this finalization hook for calling then they are collected,
kono
parents:
diff changeset
1326 which calls the finalizer vfunc. This allows them to call "release"
kono
parents:
diff changeset
1327 on any vec<> within them. */
kono
parents:
diff changeset
1328
kono
parents:
diff changeset
1329 static void
kono
parents:
diff changeset
1330 wrapper_finalizer (void *ptr)
kono
parents:
diff changeset
1331 {
kono
parents:
diff changeset
1332 playback::wrapper *wrapper = reinterpret_cast <playback::wrapper *> (ptr);
kono
parents:
diff changeset
1333 wrapper->finalizer ();
kono
parents:
diff changeset
1334 }
kono
parents:
diff changeset
1335
kono
parents:
diff changeset
1336 /* gcc::jit::playback::wrapper subclasses are GC-managed:
kono
parents:
diff changeset
1337 allocate them using ggc_internal_cleared_alloc. */
kono
parents:
diff changeset
1338
kono
parents:
diff changeset
1339 void *
kono
parents:
diff changeset
1340 playback::wrapper::
kono
parents:
diff changeset
1341 operator new (size_t sz)
kono
parents:
diff changeset
1342 {
kono
parents:
diff changeset
1343 return ggc_internal_cleared_alloc (sz, wrapper_finalizer, 0, 1);
kono
parents:
diff changeset
1344
kono
parents:
diff changeset
1345 }
kono
parents:
diff changeset
1346
kono
parents:
diff changeset
1347 /* Constructor for gcc:jit::playback::function. */
kono
parents:
diff changeset
1348
kono
parents:
diff changeset
1349 playback::function::
kono
parents:
diff changeset
1350 function (context *ctxt,
kono
parents:
diff changeset
1351 tree fndecl,
kono
parents:
diff changeset
1352 enum gcc_jit_function_kind kind)
kono
parents:
diff changeset
1353 : m_ctxt(ctxt),
kono
parents:
diff changeset
1354 m_inner_fndecl (fndecl),
kono
parents:
diff changeset
1355 m_inner_bind_expr (NULL),
kono
parents:
diff changeset
1356 m_kind (kind)
kono
parents:
diff changeset
1357 {
kono
parents:
diff changeset
1358 if (m_kind != GCC_JIT_FUNCTION_IMPORTED)
kono
parents:
diff changeset
1359 {
kono
parents:
diff changeset
1360 /* Create a BIND_EXPR, and within it, a statement list. */
kono
parents:
diff changeset
1361 m_stmt_list = alloc_stmt_list ();
kono
parents:
diff changeset
1362 m_stmt_iter = tsi_start (m_stmt_list);
kono
parents:
diff changeset
1363 m_inner_block = make_node (BLOCK);
kono
parents:
diff changeset
1364 m_inner_bind_expr =
kono
parents:
diff changeset
1365 build3 (BIND_EXPR, void_type_node, NULL, m_stmt_list, m_inner_block);
kono
parents:
diff changeset
1366 }
kono
parents:
diff changeset
1367 else
kono
parents:
diff changeset
1368 {
kono
parents:
diff changeset
1369 m_inner_block = NULL;
kono
parents:
diff changeset
1370 m_stmt_list = NULL;
kono
parents:
diff changeset
1371 }
kono
parents:
diff changeset
1372 }
kono
parents:
diff changeset
1373
kono
parents:
diff changeset
1374 /* Hand-written GC-marking hook for playback functions. */
kono
parents:
diff changeset
1375
kono
parents:
diff changeset
1376 void
kono
parents:
diff changeset
1377 playback::function::
kono
parents:
diff changeset
1378 gt_ggc_mx ()
kono
parents:
diff changeset
1379 {
kono
parents:
diff changeset
1380 gt_ggc_m_9tree_node (m_inner_fndecl);
kono
parents:
diff changeset
1381 gt_ggc_m_9tree_node (m_inner_bind_expr);
kono
parents:
diff changeset
1382 gt_ggc_m_9tree_node (m_stmt_list);
kono
parents:
diff changeset
1383 gt_ggc_m_9tree_node (m_inner_block);
kono
parents:
diff changeset
1384 }
kono
parents:
diff changeset
1385
kono
parents:
diff changeset
1386 /* Don't leak vec's internal buffer (in non-GC heap) when we are
kono
parents:
diff changeset
1387 GC-ed. */
kono
parents:
diff changeset
1388
kono
parents:
diff changeset
1389 void
kono
parents:
diff changeset
1390 playback::function::finalizer ()
kono
parents:
diff changeset
1391 {
kono
parents:
diff changeset
1392 m_blocks.release ();
kono
parents:
diff changeset
1393 }
kono
parents:
diff changeset
1394
kono
parents:
diff changeset
1395 /* Get the return type of a playback function, in tree form. */
kono
parents:
diff changeset
1396
kono
parents:
diff changeset
1397 tree
kono
parents:
diff changeset
1398 playback::function::
kono
parents:
diff changeset
1399 get_return_type_as_tree () const
kono
parents:
diff changeset
1400 {
kono
parents:
diff changeset
1401 return TREE_TYPE (TREE_TYPE(m_inner_fndecl));
kono
parents:
diff changeset
1402 }
kono
parents:
diff changeset
1403
kono
parents:
diff changeset
1404 /* Construct a new local within this playback::function. */
kono
parents:
diff changeset
1405
kono
parents:
diff changeset
1406 playback::lvalue *
kono
parents:
diff changeset
1407 playback::function::
kono
parents:
diff changeset
1408 new_local (location *loc,
kono
parents:
diff changeset
1409 type *type,
kono
parents:
diff changeset
1410 const char *name)
kono
parents:
diff changeset
1411 {
kono
parents:
diff changeset
1412 gcc_assert (type);
kono
parents:
diff changeset
1413 gcc_assert (name);
kono
parents:
diff changeset
1414 tree inner = build_decl (UNKNOWN_LOCATION, VAR_DECL,
kono
parents:
diff changeset
1415 get_identifier (name),
kono
parents:
diff changeset
1416 type->as_tree ());
kono
parents:
diff changeset
1417 DECL_CONTEXT (inner) = this->m_inner_fndecl;
kono
parents:
diff changeset
1418
kono
parents:
diff changeset
1419 /* Prepend to BIND_EXPR_VARS: */
kono
parents:
diff changeset
1420 DECL_CHAIN (inner) = BIND_EXPR_VARS (m_inner_bind_expr);
kono
parents:
diff changeset
1421 BIND_EXPR_VARS (m_inner_bind_expr) = inner;
kono
parents:
diff changeset
1422
kono
parents:
diff changeset
1423 if (loc)
kono
parents:
diff changeset
1424 set_tree_location (inner, loc);
kono
parents:
diff changeset
1425 return new lvalue (m_ctxt, inner);
kono
parents:
diff changeset
1426 }
kono
parents:
diff changeset
1427
kono
parents:
diff changeset
1428 /* Construct a new block within this playback::function. */
kono
parents:
diff changeset
1429
kono
parents:
diff changeset
1430 playback::block *
kono
parents:
diff changeset
1431 playback::function::
kono
parents:
diff changeset
1432 new_block (const char *name)
kono
parents:
diff changeset
1433 {
kono
parents:
diff changeset
1434 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
kono
parents:
diff changeset
1435
kono
parents:
diff changeset
1436 block *result = new playback::block (this, name);
kono
parents:
diff changeset
1437 m_blocks.safe_push (result);
kono
parents:
diff changeset
1438 return result;
kono
parents:
diff changeset
1439 }
kono
parents:
diff changeset
1440
kono
parents:
diff changeset
1441 /* Construct a playback::rvalue instance wrapping an ADDR_EXPR for
kono
parents:
diff changeset
1442 this playback::function. */
kono
parents:
diff changeset
1443
kono
parents:
diff changeset
1444 playback::rvalue *
kono
parents:
diff changeset
1445 playback::function::get_address (location *loc)
kono
parents:
diff changeset
1446 {
kono
parents:
diff changeset
1447 tree t_fndecl = as_fndecl ();
kono
parents:
diff changeset
1448 tree t_fntype = TREE_TYPE (t_fndecl);
kono
parents:
diff changeset
1449 tree t_fnptr = build1 (ADDR_EXPR, build_pointer_type (t_fntype), t_fndecl);
kono
parents:
diff changeset
1450 if (loc)
kono
parents:
diff changeset
1451 m_ctxt->set_tree_location (t_fnptr, loc);
kono
parents:
diff changeset
1452 return new rvalue (m_ctxt, t_fnptr);
kono
parents:
diff changeset
1453 }
kono
parents:
diff changeset
1454
kono
parents:
diff changeset
1455 /* Build a statement list for the function as a whole out of the
kono
parents:
diff changeset
1456 lists of statements for the individual blocks, building labels
kono
parents:
diff changeset
1457 for each block. */
kono
parents:
diff changeset
1458
kono
parents:
diff changeset
1459 void
kono
parents:
diff changeset
1460 playback::function::
kono
parents:
diff changeset
1461 build_stmt_list ()
kono
parents:
diff changeset
1462 {
kono
parents:
diff changeset
1463 int i;
kono
parents:
diff changeset
1464 block *b;
kono
parents:
diff changeset
1465
kono
parents:
diff changeset
1466 JIT_LOG_SCOPE (m_ctxt->get_logger ());
kono
parents:
diff changeset
1467
kono
parents:
diff changeset
1468 FOR_EACH_VEC_ELT (m_blocks, i, b)
kono
parents:
diff changeset
1469 {
kono
parents:
diff changeset
1470 int j;
kono
parents:
diff changeset
1471 tree stmt;
kono
parents:
diff changeset
1472
kono
parents:
diff changeset
1473 b->m_label_expr = build1 (LABEL_EXPR,
kono
parents:
diff changeset
1474 void_type_node,
kono
parents:
diff changeset
1475 b->as_label_decl ());
kono
parents:
diff changeset
1476 tsi_link_after (&m_stmt_iter, b->m_label_expr, TSI_CONTINUE_LINKING);
kono
parents:
diff changeset
1477
kono
parents:
diff changeset
1478 FOR_EACH_VEC_ELT (b->m_stmts, j, stmt)
kono
parents:
diff changeset
1479 tsi_link_after (&m_stmt_iter, stmt, TSI_CONTINUE_LINKING);
kono
parents:
diff changeset
1480 }
kono
parents:
diff changeset
1481 }
kono
parents:
diff changeset
1482
kono
parents:
diff changeset
1483 /* Finish compiling the given function, potentially running the
kono
parents:
diff changeset
1484 garbage-collector.
kono
parents:
diff changeset
1485 The function will have a statement list by now.
kono
parents:
diff changeset
1486 Amongst other things, this gimplifies the statement list,
kono
parents:
diff changeset
1487 and calls cgraph_node::finalize_function on the function. */
kono
parents:
diff changeset
1488
kono
parents:
diff changeset
1489 void
kono
parents:
diff changeset
1490 playback::function::
kono
parents:
diff changeset
1491 postprocess ()
kono
parents:
diff changeset
1492 {
kono
parents:
diff changeset
1493 JIT_LOG_SCOPE (m_ctxt->get_logger ());
kono
parents:
diff changeset
1494
kono
parents:
diff changeset
1495 if (m_ctxt->get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE))
kono
parents:
diff changeset
1496 debug_tree (m_stmt_list);
kono
parents:
diff changeset
1497
kono
parents:
diff changeset
1498 /* Do we need this to force cgraphunit.c to output the function? */
kono
parents:
diff changeset
1499 if (m_kind == GCC_JIT_FUNCTION_EXPORTED)
kono
parents:
diff changeset
1500 {
kono
parents:
diff changeset
1501 DECL_EXTERNAL (m_inner_fndecl) = 0;
kono
parents:
diff changeset
1502 DECL_PRESERVE_P (m_inner_fndecl) = 1;
kono
parents:
diff changeset
1503 }
kono
parents:
diff changeset
1504
kono
parents:
diff changeset
1505 if (m_kind == GCC_JIT_FUNCTION_INTERNAL
kono
parents:
diff changeset
1506 ||m_kind == GCC_JIT_FUNCTION_ALWAYS_INLINE)
kono
parents:
diff changeset
1507 {
kono
parents:
diff changeset
1508 DECL_EXTERNAL (m_inner_fndecl) = 0;
kono
parents:
diff changeset
1509 TREE_PUBLIC (m_inner_fndecl) = 0;
kono
parents:
diff changeset
1510 }
kono
parents:
diff changeset
1511
kono
parents:
diff changeset
1512 if (m_kind != GCC_JIT_FUNCTION_IMPORTED)
kono
parents:
diff changeset
1513 {
kono
parents:
diff changeset
1514 /* Seem to need this in gimple-low.c: */
kono
parents:
diff changeset
1515 gcc_assert (m_inner_block);
kono
parents:
diff changeset
1516 DECL_INITIAL (m_inner_fndecl) = m_inner_block;
kono
parents:
diff changeset
1517
kono
parents:
diff changeset
1518 /* how to add to function? the following appears to be how to
kono
parents:
diff changeset
1519 set the body of a m_inner_fndecl: */
kono
parents:
diff changeset
1520 DECL_SAVED_TREE(m_inner_fndecl) = m_inner_bind_expr;
kono
parents:
diff changeset
1521
kono
parents:
diff changeset
1522 /* Ensure that locals appear in the debuginfo. */
kono
parents:
diff changeset
1523 BLOCK_VARS (m_inner_block) = BIND_EXPR_VARS (m_inner_bind_expr);
kono
parents:
diff changeset
1524
kono
parents:
diff changeset
1525 //debug_tree (m_inner_fndecl);
kono
parents:
diff changeset
1526
kono
parents:
diff changeset
1527 /* Convert to gimple: */
kono
parents:
diff changeset
1528 //printf("about to gimplify_function_tree\n");
kono
parents:
diff changeset
1529 gimplify_function_tree (m_inner_fndecl);
kono
parents:
diff changeset
1530 //printf("finished gimplify_function_tree\n");
kono
parents:
diff changeset
1531
kono
parents:
diff changeset
1532 current_function_decl = m_inner_fndecl;
kono
parents:
diff changeset
1533 if (m_ctxt->get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE))
kono
parents:
diff changeset
1534 dump_function_to_file (m_inner_fndecl, stderr, TDF_VOPS|TDF_MEMSYMS|TDF_LINENO);
kono
parents:
diff changeset
1535 //debug_tree (m_inner_fndecl);
kono
parents:
diff changeset
1536
kono
parents:
diff changeset
1537 //printf("about to add to cgraph\n");
kono
parents:
diff changeset
1538 /* Add to cgraph: */
kono
parents:
diff changeset
1539 cgraph_node::finalize_function (m_inner_fndecl, false);
kono
parents:
diff changeset
1540 /* This can trigger a collection, so we need to have all of
kono
parents:
diff changeset
1541 the funcs as roots. */
kono
parents:
diff changeset
1542
kono
parents:
diff changeset
1543 current_function_decl = NULL;
kono
parents:
diff changeset
1544 }
kono
parents:
diff changeset
1545 }
kono
parents:
diff changeset
1546
kono
parents:
diff changeset
1547 /* Don't leak vec's internal buffer (in non-GC heap) when we are
kono
parents:
diff changeset
1548 GC-ed. */
kono
parents:
diff changeset
1549
kono
parents:
diff changeset
1550 void
kono
parents:
diff changeset
1551 playback::block::finalizer ()
kono
parents:
diff changeset
1552 {
kono
parents:
diff changeset
1553 m_stmts.release ();
kono
parents:
diff changeset
1554 }
kono
parents:
diff changeset
1555
kono
parents:
diff changeset
1556 /* Add an eval of the rvalue to the function's statement list. */
kono
parents:
diff changeset
1557
kono
parents:
diff changeset
1558 void
kono
parents:
diff changeset
1559 playback::block::
kono
parents:
diff changeset
1560 add_eval (location *loc,
kono
parents:
diff changeset
1561 rvalue *rvalue)
kono
parents:
diff changeset
1562 {
kono
parents:
diff changeset
1563 gcc_assert (rvalue);
kono
parents:
diff changeset
1564
kono
parents:
diff changeset
1565 if (loc)
kono
parents:
diff changeset
1566 set_tree_location (rvalue->as_tree (), loc);
kono
parents:
diff changeset
1567
kono
parents:
diff changeset
1568 add_stmt (rvalue->as_tree ());
kono
parents:
diff changeset
1569 }
kono
parents:
diff changeset
1570
kono
parents:
diff changeset
1571 /* Add an assignment to the function's statement list. */
kono
parents:
diff changeset
1572
kono
parents:
diff changeset
1573 void
kono
parents:
diff changeset
1574 playback::block::
kono
parents:
diff changeset
1575 add_assignment (location *loc,
kono
parents:
diff changeset
1576 lvalue *lvalue,
kono
parents:
diff changeset
1577 rvalue *rvalue)
kono
parents:
diff changeset
1578 {
kono
parents:
diff changeset
1579 gcc_assert (lvalue);
kono
parents:
diff changeset
1580 gcc_assert (rvalue);
kono
parents:
diff changeset
1581
kono
parents:
diff changeset
1582 tree t_lvalue = lvalue->as_tree ();
kono
parents:
diff changeset
1583 tree t_rvalue = rvalue->as_tree ();
kono
parents:
diff changeset
1584 if (TREE_TYPE (t_rvalue) != TREE_TYPE (t_lvalue))
kono
parents:
diff changeset
1585 {
kono
parents:
diff changeset
1586 t_rvalue = build1 (CONVERT_EXPR,
kono
parents:
diff changeset
1587 TREE_TYPE (t_lvalue),
kono
parents:
diff changeset
1588 t_rvalue);
kono
parents:
diff changeset
1589 if (loc)
kono
parents:
diff changeset
1590 set_tree_location (t_rvalue, loc);
kono
parents:
diff changeset
1591 }
kono
parents:
diff changeset
1592
kono
parents:
diff changeset
1593 tree stmt =
kono
parents:
diff changeset
1594 build2 (MODIFY_EXPR, TREE_TYPE (t_lvalue),
kono
parents:
diff changeset
1595 t_lvalue, t_rvalue);
kono
parents:
diff changeset
1596 if (loc)
kono
parents:
diff changeset
1597 set_tree_location (stmt, loc);
kono
parents:
diff changeset
1598 add_stmt (stmt);
kono
parents:
diff changeset
1599 }
kono
parents:
diff changeset
1600
kono
parents:
diff changeset
1601 /* Add a comment to the function's statement list.
kono
parents:
diff changeset
1602 For now this is done by adding a dummy label. */
kono
parents:
diff changeset
1603
kono
parents:
diff changeset
1604 void
kono
parents:
diff changeset
1605 playback::block::
kono
parents:
diff changeset
1606 add_comment (location *loc,
kono
parents:
diff changeset
1607 const char *text)
kono
parents:
diff changeset
1608 {
kono
parents:
diff changeset
1609 /* Wrap the text in C-style comment delimiters. */
kono
parents:
diff changeset
1610 size_t sz =
kono
parents:
diff changeset
1611 (3 /* opening delim */
kono
parents:
diff changeset
1612 + strlen (text)
kono
parents:
diff changeset
1613 + 3 /* closing delim */
kono
parents:
diff changeset
1614 + 1 /* terminator */);
kono
parents:
diff changeset
1615 char *wrapped = (char *)ggc_internal_alloc (sz);
kono
parents:
diff changeset
1616 snprintf (wrapped, sz, "/* %s */", text);
kono
parents:
diff changeset
1617
kono
parents:
diff changeset
1618 /* For now we simply implement this by adding a dummy label with a name
kono
parents:
diff changeset
1619 containing the given text. */
kono
parents:
diff changeset
1620 tree identifier = get_identifier (wrapped);
kono
parents:
diff changeset
1621 tree label_decl = build_decl (UNKNOWN_LOCATION, LABEL_DECL,
kono
parents:
diff changeset
1622 identifier, void_type_node);
kono
parents:
diff changeset
1623 DECL_CONTEXT (label_decl) = m_func->as_fndecl ();
kono
parents:
diff changeset
1624
kono
parents:
diff changeset
1625 tree label_expr = build1 (LABEL_EXPR, void_type_node, label_decl);
kono
parents:
diff changeset
1626 if (loc)
kono
parents:
diff changeset
1627 set_tree_location (label_expr, loc);
kono
parents:
diff changeset
1628 add_stmt (label_expr);
kono
parents:
diff changeset
1629 }
kono
parents:
diff changeset
1630
kono
parents:
diff changeset
1631 /* Add a conditional jump statement to the function's statement list. */
kono
parents:
diff changeset
1632
kono
parents:
diff changeset
1633 void
kono
parents:
diff changeset
1634 playback::block::
kono
parents:
diff changeset
1635 add_conditional (location *loc,
kono
parents:
diff changeset
1636 rvalue *boolval,
kono
parents:
diff changeset
1637 block *on_true,
kono
parents:
diff changeset
1638 block *on_false)
kono
parents:
diff changeset
1639 {
kono
parents:
diff changeset
1640 gcc_assert (boolval);
kono
parents:
diff changeset
1641 gcc_assert (on_true);
kono
parents:
diff changeset
1642 gcc_assert (on_false);
kono
parents:
diff changeset
1643
kono
parents:
diff changeset
1644 /* COND_EXPR wants statement lists for the true/false operands, but we
kono
parents:
diff changeset
1645 want labels.
kono
parents:
diff changeset
1646 Shim it by creating jumps to the labels */
kono
parents:
diff changeset
1647 tree true_jump = build1 (GOTO_EXPR, void_type_node,
kono
parents:
diff changeset
1648 on_true->as_label_decl ());
kono
parents:
diff changeset
1649 if (loc)
kono
parents:
diff changeset
1650 set_tree_location (true_jump, loc);
kono
parents:
diff changeset
1651
kono
parents:
diff changeset
1652 tree false_jump = build1 (GOTO_EXPR, void_type_node,
kono
parents:
diff changeset
1653 on_false->as_label_decl ());
kono
parents:
diff changeset
1654 if (loc)
kono
parents:
diff changeset
1655 set_tree_location (false_jump, loc);
kono
parents:
diff changeset
1656
kono
parents:
diff changeset
1657 tree stmt =
kono
parents:
diff changeset
1658 build3 (COND_EXPR, void_type_node, boolval->as_tree (),
kono
parents:
diff changeset
1659 true_jump, false_jump);
kono
parents:
diff changeset
1660 if (loc)
kono
parents:
diff changeset
1661 set_tree_location (stmt, loc);
kono
parents:
diff changeset
1662 add_stmt (stmt);
kono
parents:
diff changeset
1663 }
kono
parents:
diff changeset
1664
kono
parents:
diff changeset
1665 /* Add an unconditional jump statement to the function's statement list. */
kono
parents:
diff changeset
1666
kono
parents:
diff changeset
1667 void
kono
parents:
diff changeset
1668 playback::block::
kono
parents:
diff changeset
1669 add_jump (location *loc,
kono
parents:
diff changeset
1670 block *target)
kono
parents:
diff changeset
1671 {
kono
parents:
diff changeset
1672 gcc_assert (target);
kono
parents:
diff changeset
1673
kono
parents:
diff changeset
1674 // see c_finish_loop
kono
parents:
diff changeset
1675 //tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
kono
parents:
diff changeset
1676 //add_stmt (top);
kono
parents:
diff changeset
1677
kono
parents:
diff changeset
1678 //tree stmt = build_and_jump (&LABEL_EXPR_LABEL (target->label_));
kono
parents:
diff changeset
1679 TREE_USED (target->as_label_decl ()) = 1;
kono
parents:
diff changeset
1680 tree stmt = build1 (GOTO_EXPR, void_type_node, target->as_label_decl ());
kono
parents:
diff changeset
1681 if (loc)
kono
parents:
diff changeset
1682 set_tree_location (stmt, loc);
kono
parents:
diff changeset
1683 add_stmt (stmt);
kono
parents:
diff changeset
1684
kono
parents:
diff changeset
1685 /*
kono
parents:
diff changeset
1686 from c-typeck.c:
kono
parents:
diff changeset
1687 tree
kono
parents:
diff changeset
1688 c_finish_goto_label (location_t loc, tree label)
kono
parents:
diff changeset
1689 {
kono
parents:
diff changeset
1690 tree decl = lookup_label_for_goto (loc, label);
kono
parents:
diff changeset
1691 if (!decl)
kono
parents:
diff changeset
1692 return NULL_TREE;
kono
parents:
diff changeset
1693 TREE_USED (decl) = 1;
kono
parents:
diff changeset
1694 {
kono
parents:
diff changeset
1695 tree t = build1 (GOTO_EXPR, void_type_node, decl);
kono
parents:
diff changeset
1696 SET_EXPR_LOCATION (t, loc);
kono
parents:
diff changeset
1697 return add_stmt (t);
kono
parents:
diff changeset
1698 }
kono
parents:
diff changeset
1699 }
kono
parents:
diff changeset
1700 */
kono
parents:
diff changeset
1701
kono
parents:
diff changeset
1702 }
kono
parents:
diff changeset
1703
kono
parents:
diff changeset
1704 /* Add a return statement to the function's statement list. */
kono
parents:
diff changeset
1705
kono
parents:
diff changeset
1706 void
kono
parents:
diff changeset
1707 playback::block::
kono
parents:
diff changeset
1708 add_return (location *loc,
kono
parents:
diff changeset
1709 rvalue *rvalue)
kono
parents:
diff changeset
1710 {
kono
parents:
diff changeset
1711 tree modify_retval = NULL;
kono
parents:
diff changeset
1712 tree return_type = m_func->get_return_type_as_tree ();
kono
parents:
diff changeset
1713 if (rvalue)
kono
parents:
diff changeset
1714 {
kono
parents:
diff changeset
1715 tree t_lvalue = DECL_RESULT (m_func->as_fndecl ());
kono
parents:
diff changeset
1716 tree t_rvalue = rvalue->as_tree ();
kono
parents:
diff changeset
1717 if (TREE_TYPE (t_rvalue) != TREE_TYPE (t_lvalue))
kono
parents:
diff changeset
1718 t_rvalue = build1 (CONVERT_EXPR,
kono
parents:
diff changeset
1719 TREE_TYPE (t_lvalue),
kono
parents:
diff changeset
1720 t_rvalue);
kono
parents:
diff changeset
1721 modify_retval = build2 (MODIFY_EXPR, return_type,
kono
parents:
diff changeset
1722 t_lvalue, t_rvalue);
kono
parents:
diff changeset
1723 if (loc)
kono
parents:
diff changeset
1724 set_tree_location (modify_retval, loc);
kono
parents:
diff changeset
1725 }
kono
parents:
diff changeset
1726 tree return_stmt = build1 (RETURN_EXPR, return_type,
kono
parents:
diff changeset
1727 modify_retval);
kono
parents:
diff changeset
1728 if (loc)
kono
parents:
diff changeset
1729 set_tree_location (return_stmt, loc);
kono
parents:
diff changeset
1730
kono
parents:
diff changeset
1731 add_stmt (return_stmt);
kono
parents:
diff changeset
1732 }
kono
parents:
diff changeset
1733
kono
parents:
diff changeset
1734 /* Helper function for playback::block::add_switch.
kono
parents:
diff changeset
1735 Construct a case label for the given range, followed by a goto stmt
kono
parents:
diff changeset
1736 to the given block, appending them to stmt list *ptr_t_switch_body. */
kono
parents:
diff changeset
1737
kono
parents:
diff changeset
1738 static void
kono
parents:
diff changeset
1739 add_case (tree *ptr_t_switch_body,
kono
parents:
diff changeset
1740 tree t_low_value,
kono
parents:
diff changeset
1741 tree t_high_value,
kono
parents:
diff changeset
1742 playback::block *dest_block)
kono
parents:
diff changeset
1743 {
kono
parents:
diff changeset
1744 tree t_label = create_artificial_label (UNKNOWN_LOCATION);
kono
parents:
diff changeset
1745 DECL_CONTEXT (t_label) = dest_block->get_function ()->as_fndecl ();
kono
parents:
diff changeset
1746
kono
parents:
diff changeset
1747 tree t_case_label =
kono
parents:
diff changeset
1748 build_case_label (t_low_value, t_high_value, t_label);
kono
parents:
diff changeset
1749 append_to_statement_list (t_case_label, ptr_t_switch_body);
kono
parents:
diff changeset
1750
kono
parents:
diff changeset
1751 tree t_goto_stmt =
kono
parents:
diff changeset
1752 build1 (GOTO_EXPR, void_type_node, dest_block->as_label_decl ());
kono
parents:
diff changeset
1753 append_to_statement_list (t_goto_stmt, ptr_t_switch_body);
kono
parents:
diff changeset
1754 }
kono
parents:
diff changeset
1755
kono
parents:
diff changeset
1756 /* Add a switch statement to the function's statement list.
kono
parents:
diff changeset
1757
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1758 We create a switch body, and populate it with case labels, each
111
kono
parents:
diff changeset
1759 followed by a goto to the desired block. */
kono
parents:
diff changeset
1760
kono
parents:
diff changeset
1761 void
kono
parents:
diff changeset
1762 playback::block::
kono
parents:
diff changeset
1763 add_switch (location *loc,
kono
parents:
diff changeset
1764 rvalue *expr,
kono
parents:
diff changeset
1765 block *default_block,
kono
parents:
diff changeset
1766 const auto_vec <case_> *cases)
kono
parents:
diff changeset
1767 {
kono
parents:
diff changeset
1768 /* Compare with:
kono
parents:
diff changeset
1769 - c/c-typeck.c: c_start_case
kono
parents:
diff changeset
1770 - c-family/c-common.c:c_add_case_label
kono
parents:
diff changeset
1771 - java/expr.c:expand_java_switch and expand_java_add_case
kono
parents:
diff changeset
1772 We've already rejected overlaps and duplicates in
kono
parents:
diff changeset
1773 libgccjit.c:case_range_validator::validate. */
kono
parents:
diff changeset
1774
kono
parents:
diff changeset
1775 tree t_expr = expr->as_tree ();
kono
parents:
diff changeset
1776 tree t_type = TREE_TYPE (t_expr);
kono
parents:
diff changeset
1777
kono
parents:
diff changeset
1778 tree t_switch_body = alloc_stmt_list ();
kono
parents:
diff changeset
1779
kono
parents:
diff changeset
1780 int i;
kono
parents:
diff changeset
1781 case_ *c;
kono
parents:
diff changeset
1782 FOR_EACH_VEC_ELT (*cases, i, c)
kono
parents:
diff changeset
1783 {
kono
parents:
diff changeset
1784 tree t_low_value = c->m_min_value->as_tree ();
kono
parents:
diff changeset
1785 tree t_high_value = c->m_max_value->as_tree ();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1786 add_case (&t_switch_body, t_low_value, t_high_value, c->m_dest_block);
111
kono
parents:
diff changeset
1787 }
kono
parents:
diff changeset
1788 /* Default label. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1789 add_case (&t_switch_body, NULL_TREE, NULL_TREE, default_block);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1790
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1791 tree switch_stmt = build2 (SWITCH_EXPR, t_type, t_expr, t_switch_body);
111
kono
parents:
diff changeset
1792 if (loc)
kono
parents:
diff changeset
1793 set_tree_location (switch_stmt, loc);
kono
parents:
diff changeset
1794 add_stmt (switch_stmt);
kono
parents:
diff changeset
1795 }
kono
parents:
diff changeset
1796
kono
parents:
diff changeset
1797 /* Constructor for gcc::jit::playback::block. */
kono
parents:
diff changeset
1798
kono
parents:
diff changeset
1799 playback::block::
kono
parents:
diff changeset
1800 block (function *func,
kono
parents:
diff changeset
1801 const char *name)
kono
parents:
diff changeset
1802 : m_func (func),
kono
parents:
diff changeset
1803 m_stmts ()
kono
parents:
diff changeset
1804 {
kono
parents:
diff changeset
1805 tree identifier;
kono
parents:
diff changeset
1806
kono
parents:
diff changeset
1807 gcc_assert (func);
kono
parents:
diff changeset
1808 // name can be NULL
kono
parents:
diff changeset
1809 if (name)
kono
parents:
diff changeset
1810 identifier = get_identifier (name);
kono
parents:
diff changeset
1811 else
kono
parents:
diff changeset
1812 identifier = NULL;
kono
parents:
diff changeset
1813 m_label_decl = build_decl (UNKNOWN_LOCATION, LABEL_DECL,
kono
parents:
diff changeset
1814 identifier, void_type_node);
kono
parents:
diff changeset
1815 DECL_CONTEXT (m_label_decl) = func->as_fndecl ();
kono
parents:
diff changeset
1816 m_label_expr = NULL;
kono
parents:
diff changeset
1817 }
kono
parents:
diff changeset
1818
kono
parents:
diff changeset
1819 /* Compile a playback::context:
kono
parents:
diff changeset
1820
kono
parents:
diff changeset
1821 - Use the context's options to cconstruct command-line options, and
kono
parents:
diff changeset
1822 call into the rest of GCC (toplev::main).
kono
parents:
diff changeset
1823 - Assuming it succeeds, we have a .s file.
kono
parents:
diff changeset
1824 - We then run the "postprocess" vfunc:
kono
parents:
diff changeset
1825
kono
parents:
diff changeset
1826 (A) In-memory compile ("gcc_jit_context_compile")
kono
parents:
diff changeset
1827
kono
parents:
diff changeset
1828 For an in-memory compile we have the playback::compile_to_memory
kono
parents:
diff changeset
1829 subclass; "postprocess" will convert the .s file to a .so DSO,
kono
parents:
diff changeset
1830 and load it in memory (via dlopen), wrapping the result up as
kono
parents:
diff changeset
1831 a jit::result and returning it.
kono
parents:
diff changeset
1832
kono
parents:
diff changeset
1833 (B) Compile to file ("gcc_jit_context_compile_to_file")
kono
parents:
diff changeset
1834
kono
parents:
diff changeset
1835 When compiling to a file, we have the playback::compile_to_file
kono
parents:
diff changeset
1836 subclass; "postprocess" will either copy the .s file to the
kono
parents:
diff changeset
1837 destination (for GCC_JIT_OUTPUT_KIND_ASSEMBLER), or invoke
kono
parents:
diff changeset
1838 the driver to convert it as necessary, copying the result. */
kono
parents:
diff changeset
1839
kono
parents:
diff changeset
1840 void
kono
parents:
diff changeset
1841 playback::context::
kono
parents:
diff changeset
1842 compile ()
kono
parents:
diff changeset
1843 {
kono
parents:
diff changeset
1844 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
1845
kono
parents:
diff changeset
1846 const char *ctxt_progname;
kono
parents:
diff changeset
1847
kono
parents:
diff changeset
1848 int keep_intermediates =
kono
parents:
diff changeset
1849 get_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES);
kono
parents:
diff changeset
1850
kono
parents:
diff changeset
1851 m_tempdir = new tempdir (get_logger (), keep_intermediates);
kono
parents:
diff changeset
1852 if (!m_tempdir->create ())
kono
parents:
diff changeset
1853 return;
kono
parents:
diff changeset
1854
kono
parents:
diff changeset
1855 /* Call into the rest of gcc.
kono
parents:
diff changeset
1856 For now, we have to assemble command-line options to pass into
kono
parents:
diff changeset
1857 toplev::main, so that they can be parsed. */
kono
parents:
diff changeset
1858
kono
parents:
diff changeset
1859 /* Pass in user-provided program name as argv0, if any, so that it
kono
parents:
diff changeset
1860 makes it into GCC's "progname" global, used in various diagnostics. */
kono
parents:
diff changeset
1861 ctxt_progname = get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
kono
parents:
diff changeset
1862
kono
parents:
diff changeset
1863 if (!ctxt_progname)
kono
parents:
diff changeset
1864 ctxt_progname = "libgccjit.so";
kono
parents:
diff changeset
1865
kono
parents:
diff changeset
1866 auto_vec <recording::requested_dump> requested_dumps;
kono
parents:
diff changeset
1867 m_recording_ctxt->get_all_requested_dumps (&requested_dumps);
kono
parents:
diff changeset
1868
kono
parents:
diff changeset
1869 /* Acquire the JIT mutex and set "this" as the active playback ctxt. */
kono
parents:
diff changeset
1870 acquire_mutex ();
kono
parents:
diff changeset
1871
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1872 auto_string_vec fake_args;
111
kono
parents:
diff changeset
1873 make_fake_args (&fake_args, ctxt_progname, &requested_dumps);
kono
parents:
diff changeset
1874 if (errors_occurred ())
kono
parents:
diff changeset
1875 {
kono
parents:
diff changeset
1876 release_mutex ();
kono
parents:
diff changeset
1877 return;
kono
parents:
diff changeset
1878 }
kono
parents:
diff changeset
1879
kono
parents:
diff changeset
1880 /* This runs the compiler. */
kono
parents:
diff changeset
1881 toplev toplev (get_timer (), /* external_timer */
kono
parents:
diff changeset
1882 false); /* init_signals */
kono
parents:
diff changeset
1883 enter_scope ("toplev::main");
kono
parents:
diff changeset
1884 if (get_logger ())
kono
parents:
diff changeset
1885 for (unsigned i = 0; i < fake_args.length (); i++)
kono
parents:
diff changeset
1886 get_logger ()->log ("argv[%i]: %s", i, fake_args[i]);
kono
parents:
diff changeset
1887 toplev.main (fake_args.length (),
kono
parents:
diff changeset
1888 const_cast <char **> (fake_args.address ()));
kono
parents:
diff changeset
1889 exit_scope ("toplev::main");
kono
parents:
diff changeset
1890
kono
parents:
diff changeset
1891 /* Extracting dumps makes use of the gcc::dump_manager, hence we
kono
parents:
diff changeset
1892 need to do it between toplev::main (which creates the dump manager)
kono
parents:
diff changeset
1893 and toplev::finalize (which deletes it). */
kono
parents:
diff changeset
1894 extract_any_requested_dumps (&requested_dumps);
kono
parents:
diff changeset
1895
kono
parents:
diff changeset
1896 /* Clean up the compiler. */
kono
parents:
diff changeset
1897 enter_scope ("toplev::finalize");
kono
parents:
diff changeset
1898 toplev.finalize ();
kono
parents:
diff changeset
1899 exit_scope ("toplev::finalize");
kono
parents:
diff changeset
1900
kono
parents:
diff changeset
1901 /* Ideally we would release the jit mutex here, but we can't yet since
kono
parents:
diff changeset
1902 followup activities use timevars, which are global state. */
kono
parents:
diff changeset
1903
kono
parents:
diff changeset
1904 if (errors_occurred ())
kono
parents:
diff changeset
1905 {
kono
parents:
diff changeset
1906 release_mutex ();
kono
parents:
diff changeset
1907 return;
kono
parents:
diff changeset
1908 }
kono
parents:
diff changeset
1909
kono
parents:
diff changeset
1910 if (get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE))
kono
parents:
diff changeset
1911 dump_generated_code ();
kono
parents:
diff changeset
1912
kono
parents:
diff changeset
1913 /* We now have a .s file.
kono
parents:
diff changeset
1914
kono
parents:
diff changeset
1915 Run any postprocessing steps. This will either convert the .s file to
kono
parents:
diff changeset
1916 a .so DSO, and load it in memory (playback::compile_to_memory), or
kono
parents:
diff changeset
1917 convert the .s file to the requested output format, and copy it to a
kono
parents:
diff changeset
1918 given file (playback::compile_to_file). */
kono
parents:
diff changeset
1919 postprocess (ctxt_progname);
kono
parents:
diff changeset
1920
kono
parents:
diff changeset
1921 release_mutex ();
kono
parents:
diff changeset
1922 }
kono
parents:
diff changeset
1923
kono
parents:
diff changeset
1924 /* Implementation of class gcc::jit::playback::compile_to_memory,
kono
parents:
diff changeset
1925 a subclass of gcc::jit::playback::context. */
kono
parents:
diff changeset
1926
kono
parents:
diff changeset
1927 /* playback::compile_to_memory's trivial constructor. */
kono
parents:
diff changeset
1928
kono
parents:
diff changeset
1929 playback::compile_to_memory::compile_to_memory (recording::context *ctxt) :
kono
parents:
diff changeset
1930 playback::context (ctxt),
kono
parents:
diff changeset
1931 m_result (NULL)
kono
parents:
diff changeset
1932 {
kono
parents:
diff changeset
1933 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
1934 }
kono
parents:
diff changeset
1935
kono
parents:
diff changeset
1936 /* Implementation of the playback::context::process vfunc for compiling
kono
parents:
diff changeset
1937 to memory.
kono
parents:
diff changeset
1938
kono
parents:
diff changeset
1939 Convert the .s file to a .so DSO, and load it in memory (via dlopen),
kono
parents:
diff changeset
1940 wrapping the result up as a jit::result and returning it. */
kono
parents:
diff changeset
1941
kono
parents:
diff changeset
1942 void
kono
parents:
diff changeset
1943 playback::compile_to_memory::postprocess (const char *ctxt_progname)
kono
parents:
diff changeset
1944 {
kono
parents:
diff changeset
1945 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
1946 convert_to_dso (ctxt_progname);
kono
parents:
diff changeset
1947 if (errors_occurred ())
kono
parents:
diff changeset
1948 return;
kono
parents:
diff changeset
1949 m_result = dlopen_built_dso ();
kono
parents:
diff changeset
1950 }
kono
parents:
diff changeset
1951
kono
parents:
diff changeset
1952 /* Implementation of class gcc::jit::playback::compile_to_file,
kono
parents:
diff changeset
1953 a subclass of gcc::jit::playback::context. */
kono
parents:
diff changeset
1954
kono
parents:
diff changeset
1955 /* playback::compile_to_file's trivial constructor. */
kono
parents:
diff changeset
1956
kono
parents:
diff changeset
1957 playback::compile_to_file::compile_to_file (recording::context *ctxt,
kono
parents:
diff changeset
1958 enum gcc_jit_output_kind output_kind,
kono
parents:
diff changeset
1959 const char *output_path) :
kono
parents:
diff changeset
1960 playback::context (ctxt),
kono
parents:
diff changeset
1961 m_output_kind (output_kind),
kono
parents:
diff changeset
1962 m_output_path (output_path)
kono
parents:
diff changeset
1963 {
kono
parents:
diff changeset
1964 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
1965 }
kono
parents:
diff changeset
1966
kono
parents:
diff changeset
1967 /* Implementation of the playback::context::process vfunc for compiling
kono
parents:
diff changeset
1968 to a file.
kono
parents:
diff changeset
1969
kono
parents:
diff changeset
1970 Either copy the .s file to the given destination (for
kono
parents:
diff changeset
1971 GCC_JIT_OUTPUT_KIND_ASSEMBLER), or invoke the driver to convert it
kono
parents:
diff changeset
1972 as necessary, copying the result. */
kono
parents:
diff changeset
1973
kono
parents:
diff changeset
1974 void
kono
parents:
diff changeset
1975 playback::compile_to_file::postprocess (const char *ctxt_progname)
kono
parents:
diff changeset
1976 {
kono
parents:
diff changeset
1977 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
1978
kono
parents:
diff changeset
1979 /* The driver takes different actions based on the filename, so
kono
parents:
diff changeset
1980 we provide a filename with an appropriate suffix for the
kono
parents:
diff changeset
1981 output kind, and then copy it up to the user-provided path,
kono
parents:
diff changeset
1982 rather than directly compiling it to the requested output path. */
kono
parents:
diff changeset
1983
kono
parents:
diff changeset
1984 switch (m_output_kind)
kono
parents:
diff changeset
1985 {
kono
parents:
diff changeset
1986 default:
kono
parents:
diff changeset
1987 gcc_unreachable ();
kono
parents:
diff changeset
1988
kono
parents:
diff changeset
1989 case GCC_JIT_OUTPUT_KIND_ASSEMBLER:
kono
parents:
diff changeset
1990 copy_file (get_tempdir ()->get_path_s_file (),
kono
parents:
diff changeset
1991 m_output_path);
kono
parents:
diff changeset
1992 /* The .s file is automatically unlinked by tempdir::~tempdir. */
kono
parents:
diff changeset
1993 break;
kono
parents:
diff changeset
1994
kono
parents:
diff changeset
1995 case GCC_JIT_OUTPUT_KIND_OBJECT_FILE:
kono
parents:
diff changeset
1996 {
kono
parents:
diff changeset
1997 char *tmp_o_path = ::concat (get_tempdir ()->get_path (),
kono
parents:
diff changeset
1998 "/fake.o",
kono
parents:
diff changeset
1999 NULL);
kono
parents:
diff changeset
2000 invoke_driver (ctxt_progname,
kono
parents:
diff changeset
2001 get_tempdir ()->get_path_s_file (),
kono
parents:
diff changeset
2002 tmp_o_path,
kono
parents:
diff changeset
2003 TV_ASSEMBLE,
kono
parents:
diff changeset
2004 false, /* bool shared, */
kono
parents:
diff changeset
2005 false);/* bool run_linker */
kono
parents:
diff changeset
2006 if (!errors_occurred ())
kono
parents:
diff changeset
2007 {
kono
parents:
diff changeset
2008 copy_file (tmp_o_path,
kono
parents:
diff changeset
2009 m_output_path);
kono
parents:
diff changeset
2010 get_tempdir ()->add_temp_file (tmp_o_path);
kono
parents:
diff changeset
2011 }
kono
parents:
diff changeset
2012 else
kono
parents:
diff changeset
2013 free (tmp_o_path);
kono
parents:
diff changeset
2014 }
kono
parents:
diff changeset
2015 break;
kono
parents:
diff changeset
2016
kono
parents:
diff changeset
2017 case GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY:
kono
parents:
diff changeset
2018 invoke_driver (ctxt_progname,
kono
parents:
diff changeset
2019 get_tempdir ()->get_path_s_file (),
kono
parents:
diff changeset
2020 get_tempdir ()->get_path_so_file (),
kono
parents:
diff changeset
2021 TV_ASSEMBLE,
kono
parents:
diff changeset
2022 true, /* bool shared, */
kono
parents:
diff changeset
2023 true);/* bool run_linker */
kono
parents:
diff changeset
2024 if (!errors_occurred ())
kono
parents:
diff changeset
2025 copy_file (get_tempdir ()->get_path_so_file (),
kono
parents:
diff changeset
2026 m_output_path);
kono
parents:
diff changeset
2027 /* The .so file is automatically unlinked by tempdir::~tempdir. */
kono
parents:
diff changeset
2028 break;
kono
parents:
diff changeset
2029
kono
parents:
diff changeset
2030 case GCC_JIT_OUTPUT_KIND_EXECUTABLE:
kono
parents:
diff changeset
2031 {
kono
parents:
diff changeset
2032 char *tmp_exe_path = ::concat (get_tempdir ()->get_path (),
kono
parents:
diff changeset
2033 "/fake.exe",
kono
parents:
diff changeset
2034 NULL);
kono
parents:
diff changeset
2035 invoke_driver (ctxt_progname,
kono
parents:
diff changeset
2036 get_tempdir ()->get_path_s_file (),
kono
parents:
diff changeset
2037 tmp_exe_path,
kono
parents:
diff changeset
2038 TV_ASSEMBLE,
kono
parents:
diff changeset
2039 false, /* bool shared, */
kono
parents:
diff changeset
2040 true);/* bool run_linker */
kono
parents:
diff changeset
2041 if (!errors_occurred ())
kono
parents:
diff changeset
2042 {
kono
parents:
diff changeset
2043 copy_file (tmp_exe_path,
kono
parents:
diff changeset
2044 m_output_path);
kono
parents:
diff changeset
2045 get_tempdir ()->add_temp_file (tmp_exe_path);
kono
parents:
diff changeset
2046 }
kono
parents:
diff changeset
2047 else
kono
parents:
diff changeset
2048 free (tmp_exe_path);
kono
parents:
diff changeset
2049 }
kono
parents:
diff changeset
2050 break;
kono
parents:
diff changeset
2051
kono
parents:
diff changeset
2052 }
kono
parents:
diff changeset
2053
kono
parents:
diff changeset
2054 }
kono
parents:
diff changeset
2055
kono
parents:
diff changeset
2056 /* Copy SRC_PATH to DST_PATH, preserving permission bits (in particular,
kono
parents:
diff changeset
2057 the "executable" bits).
kono
parents:
diff changeset
2058
kono
parents:
diff changeset
2059 Any errors that occur are reported on the context and hence count as
kono
parents:
diff changeset
2060 a failure of the compile.
kono
parents:
diff changeset
2061
kono
parents:
diff changeset
2062 We can't in general hardlink or use "rename" from the tempdir since
kono
parents:
diff changeset
2063 it might be on a different filesystem to the destination. For example,
kono
parents:
diff changeset
2064 I get EXDEV: "Invalid cross-device link". */
kono
parents:
diff changeset
2065
kono
parents:
diff changeset
2066 void
kono
parents:
diff changeset
2067 playback::compile_to_file::copy_file (const char *src_path,
kono
parents:
diff changeset
2068 const char *dst_path)
kono
parents:
diff changeset
2069 {
kono
parents:
diff changeset
2070 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2071 if (get_logger ())
kono
parents:
diff changeset
2072 {
kono
parents:
diff changeset
2073 get_logger ()->log ("src_path: %s", src_path);
kono
parents:
diff changeset
2074 get_logger ()->log ("dst_path: %s", dst_path);
kono
parents:
diff changeset
2075 }
kono
parents:
diff changeset
2076
kono
parents:
diff changeset
2077 FILE *f_in = NULL;
kono
parents:
diff changeset
2078 FILE *f_out = NULL;
kono
parents:
diff changeset
2079 size_t total_sz_in = 0;
kono
parents:
diff changeset
2080 size_t total_sz_out = 0;
kono
parents:
diff changeset
2081 char buf[4096];
kono
parents:
diff changeset
2082 size_t sz_in;
kono
parents:
diff changeset
2083 struct stat stat_buf;
kono
parents:
diff changeset
2084
kono
parents:
diff changeset
2085 f_in = fopen (src_path, "rb");
kono
parents:
diff changeset
2086 if (!f_in)
kono
parents:
diff changeset
2087 {
kono
parents:
diff changeset
2088 add_error (NULL,
kono
parents:
diff changeset
2089 "unable to open %s for reading: %s",
kono
parents:
diff changeset
2090 src_path,
kono
parents:
diff changeset
2091 xstrerror (errno));
kono
parents:
diff changeset
2092 return;
kono
parents:
diff changeset
2093 }
kono
parents:
diff changeset
2094
kono
parents:
diff changeset
2095 /* Use stat on the filedescriptor to get the mode,
kono
parents:
diff changeset
2096 so that we can copy it over (in particular, the
kono
parents:
diff changeset
2097 "executable" bits). */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2098 if (fstat (fileno (f_in), &stat_buf) == -1)
111
kono
parents:
diff changeset
2099 {
kono
parents:
diff changeset
2100 add_error (NULL,
kono
parents:
diff changeset
2101 "unable to fstat %s: %s",
kono
parents:
diff changeset
2102 src_path,
kono
parents:
diff changeset
2103 xstrerror (errno));
kono
parents:
diff changeset
2104 fclose (f_in);
kono
parents:
diff changeset
2105 return;
kono
parents:
diff changeset
2106 }
kono
parents:
diff changeset
2107
kono
parents:
diff changeset
2108 f_out = fopen (dst_path, "wb");
kono
parents:
diff changeset
2109 if (!f_out)
kono
parents:
diff changeset
2110 {
kono
parents:
diff changeset
2111 add_error (NULL,
kono
parents:
diff changeset
2112 "unable to open %s for writing: %s",
kono
parents:
diff changeset
2113 dst_path,
kono
parents:
diff changeset
2114 xstrerror (errno));
kono
parents:
diff changeset
2115 fclose (f_in);
kono
parents:
diff changeset
2116 return;
kono
parents:
diff changeset
2117 }
kono
parents:
diff changeset
2118
kono
parents:
diff changeset
2119 while ( (sz_in = fread (buf, 1, sizeof (buf), f_in)) )
kono
parents:
diff changeset
2120 {
kono
parents:
diff changeset
2121 total_sz_in += sz_in;
kono
parents:
diff changeset
2122 size_t sz_out_remaining = sz_in;
kono
parents:
diff changeset
2123 size_t sz_out_so_far = 0;
kono
parents:
diff changeset
2124 while (sz_out_remaining)
kono
parents:
diff changeset
2125 {
kono
parents:
diff changeset
2126 size_t sz_out = fwrite (buf + sz_out_so_far,
kono
parents:
diff changeset
2127 1,
kono
parents:
diff changeset
2128 sz_out_remaining,
kono
parents:
diff changeset
2129 f_out);
kono
parents:
diff changeset
2130 gcc_assert (sz_out <= sz_out_remaining);
kono
parents:
diff changeset
2131 if (!sz_out)
kono
parents:
diff changeset
2132 {
kono
parents:
diff changeset
2133 add_error (NULL,
kono
parents:
diff changeset
2134 "error writing to %s: %s",
kono
parents:
diff changeset
2135 dst_path,
kono
parents:
diff changeset
2136 xstrerror (errno));
kono
parents:
diff changeset
2137 fclose (f_in);
kono
parents:
diff changeset
2138 fclose (f_out);
kono
parents:
diff changeset
2139 return;
kono
parents:
diff changeset
2140 }
kono
parents:
diff changeset
2141 total_sz_out += sz_out;
kono
parents:
diff changeset
2142 sz_out_so_far += sz_out;
kono
parents:
diff changeset
2143 sz_out_remaining -= sz_out;
kono
parents:
diff changeset
2144 }
kono
parents:
diff changeset
2145 gcc_assert (sz_out_so_far == sz_in);
kono
parents:
diff changeset
2146 }
kono
parents:
diff changeset
2147
kono
parents:
diff changeset
2148 if (!feof (f_in))
kono
parents:
diff changeset
2149 add_error (NULL,
kono
parents:
diff changeset
2150 "error reading from %s: %s",
kono
parents:
diff changeset
2151 src_path,
kono
parents:
diff changeset
2152 xstrerror (errno));
kono
parents:
diff changeset
2153
kono
parents:
diff changeset
2154 fclose (f_in);
kono
parents:
diff changeset
2155
kono
parents:
diff changeset
2156 gcc_assert (total_sz_in == total_sz_out);
kono
parents:
diff changeset
2157 if (get_logger ())
kono
parents:
diff changeset
2158 get_logger ()->log ("total bytes copied: %ld", total_sz_out);
kono
parents:
diff changeset
2159
kono
parents:
diff changeset
2160 /* Set the permissions of the copy to those of the original file,
kono
parents:
diff changeset
2161 in particular the "executable" bits. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2162 if (fchmod (fileno (f_out), stat_buf.st_mode) == -1)
111
kono
parents:
diff changeset
2163 add_error (NULL,
kono
parents:
diff changeset
2164 "error setting mode of %s: %s",
kono
parents:
diff changeset
2165 dst_path,
kono
parents:
diff changeset
2166 xstrerror (errno));
kono
parents:
diff changeset
2167
kono
parents:
diff changeset
2168 fclose (f_out);
kono
parents:
diff changeset
2169 }
kono
parents:
diff changeset
2170
kono
parents:
diff changeset
2171 /* Helper functions for gcc::jit::playback::context::compile. */
kono
parents:
diff changeset
2172
kono
parents:
diff changeset
2173 /* This mutex guards gcc::jit::recording::context::compile, so that only
kono
parents:
diff changeset
2174 one thread can be accessing the bulk of GCC's state at once. */
kono
parents:
diff changeset
2175
kono
parents:
diff changeset
2176 static pthread_mutex_t jit_mutex = PTHREAD_MUTEX_INITIALIZER;
kono
parents:
diff changeset
2177
kono
parents:
diff changeset
2178 /* Acquire jit_mutex and set "this" as the active playback ctxt. */
kono
parents:
diff changeset
2179
kono
parents:
diff changeset
2180 void
kono
parents:
diff changeset
2181 playback::context::acquire_mutex ()
kono
parents:
diff changeset
2182 {
kono
parents:
diff changeset
2183 auto_timevar tv (get_timer (), TV_JIT_ACQUIRING_MUTEX);
kono
parents:
diff changeset
2184
kono
parents:
diff changeset
2185 /* Acquire the big GCC mutex. */
kono
parents:
diff changeset
2186 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2187 pthread_mutex_lock (&jit_mutex);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2188 gcc_assert (active_playback_ctxt == NULL);
111
kono
parents:
diff changeset
2189 active_playback_ctxt = this;
kono
parents:
diff changeset
2190 }
kono
parents:
diff changeset
2191
kono
parents:
diff changeset
2192 /* Release jit_mutex and clear the active playback ctxt. */
kono
parents:
diff changeset
2193
kono
parents:
diff changeset
2194 void
kono
parents:
diff changeset
2195 playback::context::release_mutex ()
kono
parents:
diff changeset
2196 {
kono
parents:
diff changeset
2197 /* Release the big GCC mutex. */
kono
parents:
diff changeset
2198 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2199 gcc_assert (active_playback_ctxt == this);
kono
parents:
diff changeset
2200 active_playback_ctxt = NULL;
kono
parents:
diff changeset
2201 pthread_mutex_unlock (&jit_mutex);
kono
parents:
diff changeset
2202 }
kono
parents:
diff changeset
2203
kono
parents:
diff changeset
2204 /* Callback used by gcc::jit::playback::context::make_fake_args when
kono
parents:
diff changeset
2205 invoking driver_get_configure_time_options.
kono
parents:
diff changeset
2206 Populate a vec <char * > with the configure-time options. */
kono
parents:
diff changeset
2207
kono
parents:
diff changeset
2208 static void
kono
parents:
diff changeset
2209 append_arg_from_driver (const char *option, void *user_data)
kono
parents:
diff changeset
2210 {
kono
parents:
diff changeset
2211 gcc_assert (option);
kono
parents:
diff changeset
2212 gcc_assert (user_data);
kono
parents:
diff changeset
2213 vec <char *> *argvec = static_cast <vec <char *> *> (user_data);
kono
parents:
diff changeset
2214 argvec->safe_push (concat ("-", option, NULL));
kono
parents:
diff changeset
2215 }
kono
parents:
diff changeset
2216
kono
parents:
diff changeset
2217 /* Build a fake argv for toplev::main from the options set
kono
parents:
diff changeset
2218 by the user on the context . */
kono
parents:
diff changeset
2219
kono
parents:
diff changeset
2220 void
kono
parents:
diff changeset
2221 playback::context::
kono
parents:
diff changeset
2222 make_fake_args (vec <char *> *argvec,
kono
parents:
diff changeset
2223 const char *ctxt_progname,
kono
parents:
diff changeset
2224 vec <recording::requested_dump> *requested_dumps)
kono
parents:
diff changeset
2225 {
kono
parents:
diff changeset
2226 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2227
kono
parents:
diff changeset
2228 #define ADD_ARG(arg) argvec->safe_push (xstrdup (arg))
kono
parents:
diff changeset
2229 #define ADD_ARG_TAKE_OWNERSHIP(arg) argvec->safe_push (arg)
kono
parents:
diff changeset
2230
kono
parents:
diff changeset
2231 ADD_ARG (ctxt_progname);
kono
parents:
diff changeset
2232 ADD_ARG (get_path_c_file ());
kono
parents:
diff changeset
2233 ADD_ARG ("-fPIC");
kono
parents:
diff changeset
2234
kono
parents:
diff changeset
2235 /* Handle int options: */
kono
parents:
diff changeset
2236 switch (get_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL))
kono
parents:
diff changeset
2237 {
kono
parents:
diff changeset
2238 default:
kono
parents:
diff changeset
2239 add_error (NULL,
kono
parents:
diff changeset
2240 "unrecognized optimization level: %i",
kono
parents:
diff changeset
2241 get_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL));
kono
parents:
diff changeset
2242 return;
kono
parents:
diff changeset
2243
kono
parents:
diff changeset
2244 case 0:
kono
parents:
diff changeset
2245 ADD_ARG ("-O0");
kono
parents:
diff changeset
2246 break;
kono
parents:
diff changeset
2247
kono
parents:
diff changeset
2248 case 1:
kono
parents:
diff changeset
2249 ADD_ARG ("-O1");
kono
parents:
diff changeset
2250 break;
kono
parents:
diff changeset
2251
kono
parents:
diff changeset
2252 case 2:
kono
parents:
diff changeset
2253 ADD_ARG ("-O2");
kono
parents:
diff changeset
2254 break;
kono
parents:
diff changeset
2255
kono
parents:
diff changeset
2256 case 3:
kono
parents:
diff changeset
2257 ADD_ARG ("-O3");
kono
parents:
diff changeset
2258 break;
kono
parents:
diff changeset
2259 }
kono
parents:
diff changeset
2260 /* What about -Os? */
kono
parents:
diff changeset
2261
kono
parents:
diff changeset
2262 /* Handle bool options: */
kono
parents:
diff changeset
2263 if (get_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO))
kono
parents:
diff changeset
2264 ADD_ARG ("-g");
kono
parents:
diff changeset
2265
kono
parents:
diff changeset
2266 /* Suppress timing (and other) info. */
kono
parents:
diff changeset
2267 if (!get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_SUMMARY))
kono
parents:
diff changeset
2268 {
kono
parents:
diff changeset
2269 ADD_ARG ("-quiet");
kono
parents:
diff changeset
2270 quiet_flag = 1;
kono
parents:
diff changeset
2271 }
kono
parents:
diff changeset
2272
kono
parents:
diff changeset
2273 /* Aggressively garbage-collect, to shake out bugs: */
kono
parents:
diff changeset
2274 if (get_bool_option (GCC_JIT_BOOL_OPTION_SELFCHECK_GC))
kono
parents:
diff changeset
2275 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2276 ADD_ARG ("--param=ggc-min-expand=0");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2277 ADD_ARG ("--param=ggc-min-heapsize=0");
111
kono
parents:
diff changeset
2278 }
kono
parents:
diff changeset
2279
kono
parents:
diff changeset
2280 if (get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING))
kono
parents:
diff changeset
2281 {
kono
parents:
diff changeset
2282 ADD_ARG ("-fdump-tree-all");
kono
parents:
diff changeset
2283 ADD_ARG ("-fdump-rtl-all");
kono
parents:
diff changeset
2284 ADD_ARG ("-fdump-ipa-all");
kono
parents:
diff changeset
2285 }
kono
parents:
diff changeset
2286
kono
parents:
diff changeset
2287 /* Add "-fdump-" options for any calls to
kono
parents:
diff changeset
2288 gcc_jit_context_enable_dump. */
kono
parents:
diff changeset
2289 {
kono
parents:
diff changeset
2290 int i;
kono
parents:
diff changeset
2291 recording::requested_dump *d;
kono
parents:
diff changeset
2292 FOR_EACH_VEC_ELT (*requested_dumps, i, d)
kono
parents:
diff changeset
2293 {
kono
parents:
diff changeset
2294 char *arg = concat ("-fdump-", d->m_dumpname, NULL);
kono
parents:
diff changeset
2295 ADD_ARG_TAKE_OWNERSHIP (arg);
kono
parents:
diff changeset
2296 }
kono
parents:
diff changeset
2297 }
kono
parents:
diff changeset
2298
kono
parents:
diff changeset
2299 /* PR jit/64810: Add any target-specific default options
kono
parents:
diff changeset
2300 from OPTION_DEFAULT_SPECS, normally provided by the driver
kono
parents:
diff changeset
2301 in the non-jit case.
kono
parents:
diff changeset
2302
kono
parents:
diff changeset
2303 The target-specific code can define OPTION_DEFAULT_SPECS:
kono
parents:
diff changeset
2304 default command options in the form of spec macros for the
kono
parents:
diff changeset
2305 driver to expand ().
kono
parents:
diff changeset
2306
kono
parents:
diff changeset
2307 For cc1 etc, the driver processes OPTION_DEFAULT_SPECS and,
kono
parents:
diff changeset
2308 if not overriden, injects the defaults as extra arguments to
kono
parents:
diff changeset
2309 cc1 etc.
kono
parents:
diff changeset
2310 For the jit case, we need to add these arguments here. The
kono
parents:
diff changeset
2311 input format (using the specs language) means that we have to run
kono
parents:
diff changeset
2312 part of the driver code here (driver_get_configure_time_options).
kono
parents:
diff changeset
2313
kono
parents:
diff changeset
2314 To avoid running the spec-expansion code every time, we just do
kono
parents:
diff changeset
2315 it the first time (via a function-static flag), saving the result
kono
parents:
diff changeset
2316 into a function-static vec.
kono
parents:
diff changeset
2317 This flag and vec are global state (i.e. per-process).
kono
parents:
diff changeset
2318 They are guarded by the jit mutex. */
kono
parents:
diff changeset
2319 {
kono
parents:
diff changeset
2320 static bool have_configure_time_options = false;
kono
parents:
diff changeset
2321 static vec <char *> configure_time_options;
kono
parents:
diff changeset
2322
kono
parents:
diff changeset
2323 if (have_configure_time_options)
kono
parents:
diff changeset
2324 log ("reusing cached configure-time options");
kono
parents:
diff changeset
2325 else
kono
parents:
diff changeset
2326 {
kono
parents:
diff changeset
2327 have_configure_time_options = true;
kono
parents:
diff changeset
2328 log ("getting configure-time options from driver");
kono
parents:
diff changeset
2329 driver_get_configure_time_options (append_arg_from_driver,
kono
parents:
diff changeset
2330 &configure_time_options);
kono
parents:
diff changeset
2331 }
kono
parents:
diff changeset
2332
kono
parents:
diff changeset
2333 int i;
kono
parents:
diff changeset
2334 char *opt;
kono
parents:
diff changeset
2335
kono
parents:
diff changeset
2336 if (get_logger ())
kono
parents:
diff changeset
2337 FOR_EACH_VEC_ELT (configure_time_options, i, opt)
kono
parents:
diff changeset
2338 log ("configure_time_options[%i]: %s", i, opt);
kono
parents:
diff changeset
2339
kono
parents:
diff changeset
2340 /* configure_time_options should now contain the expanded options
kono
parents:
diff changeset
2341 from OPTION_DEFAULT_SPECS (if any). */
kono
parents:
diff changeset
2342 FOR_EACH_VEC_ELT (configure_time_options, i, opt)
kono
parents:
diff changeset
2343 {
kono
parents:
diff changeset
2344 gcc_assert (opt);
kono
parents:
diff changeset
2345 gcc_assert (opt[0] == '-');
kono
parents:
diff changeset
2346 ADD_ARG (opt);
kono
parents:
diff changeset
2347 }
kono
parents:
diff changeset
2348 }
kono
parents:
diff changeset
2349
kono
parents:
diff changeset
2350 if (get_timer ())
kono
parents:
diff changeset
2351 ADD_ARG ("-ftime-report");
kono
parents:
diff changeset
2352
kono
parents:
diff changeset
2353 /* Add any user-provided extra options, starting with any from
kono
parents:
diff changeset
2354 parent contexts. */
kono
parents:
diff changeset
2355 m_recording_ctxt->append_command_line_options (argvec);
kono
parents:
diff changeset
2356
kono
parents:
diff changeset
2357 #undef ADD_ARG
kono
parents:
diff changeset
2358 #undef ADD_ARG_TAKE_OWNERSHIP
kono
parents:
diff changeset
2359 }
kono
parents:
diff changeset
2360
kono
parents:
diff changeset
2361 /* The second half of the implementation of gcc_jit_context_enable_dump.
kono
parents:
diff changeset
2362 Iterate through the requested dumps, reading the underlying files
kono
parents:
diff changeset
2363 into heap-allocated buffers, writing pointers to the buffers into
kono
parents:
diff changeset
2364 the char ** pointers provided by client code.
kono
parents:
diff changeset
2365 Client code is responsible for calling free on the results. */
kono
parents:
diff changeset
2366
kono
parents:
diff changeset
2367 void
kono
parents:
diff changeset
2368 playback::context::
kono
parents:
diff changeset
2369 extract_any_requested_dumps (vec <recording::requested_dump> *requested_dumps)
kono
parents:
diff changeset
2370 {
kono
parents:
diff changeset
2371 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2372
kono
parents:
diff changeset
2373 int i;
kono
parents:
diff changeset
2374 recording::requested_dump *d;
kono
parents:
diff changeset
2375 FOR_EACH_VEC_ELT (*requested_dumps, i, d)
kono
parents:
diff changeset
2376 {
kono
parents:
diff changeset
2377 dump_file_info *dfi;
kono
parents:
diff changeset
2378 char *filename;
kono
parents:
diff changeset
2379 char *content;
kono
parents:
diff changeset
2380
kono
parents:
diff changeset
2381 dfi = g->get_dumps ()->get_dump_file_info_by_switch (d->m_dumpname);
kono
parents:
diff changeset
2382 if (!dfi)
kono
parents:
diff changeset
2383 {
kono
parents:
diff changeset
2384 add_error (NULL, "unrecognized dump: %s", d->m_dumpname);
kono
parents:
diff changeset
2385 continue;
kono
parents:
diff changeset
2386 }
kono
parents:
diff changeset
2387
kono
parents:
diff changeset
2388 filename = g->get_dumps ()->get_dump_file_name (dfi);
kono
parents:
diff changeset
2389 content = read_dump_file (filename);
kono
parents:
diff changeset
2390 *(d->m_out_ptr) = content;
kono
parents:
diff changeset
2391 m_tempdir->add_temp_file (filename);
kono
parents:
diff changeset
2392 }
kono
parents:
diff changeset
2393 }
kono
parents:
diff changeset
2394
kono
parents:
diff changeset
2395 /* Helper function for playback::context::extract_any_requested_dumps
kono
parents:
diff changeset
2396 (itself for use in implementation of gcc_jit_context_enable_dump).
kono
parents:
diff changeset
2397
kono
parents:
diff changeset
2398 Attempt to read the complete file at the given path, returning the
kono
parents:
diff changeset
2399 bytes found there as a buffer.
kono
parents:
diff changeset
2400 The caller is responsible for calling free on the result.
kono
parents:
diff changeset
2401 Errors will be reported on the context, and lead to NULL being
kono
parents:
diff changeset
2402 returned; an out-of-memory error will terminate the process. */
kono
parents:
diff changeset
2403
kono
parents:
diff changeset
2404 char *
kono
parents:
diff changeset
2405 playback::context::read_dump_file (const char *path)
kono
parents:
diff changeset
2406 {
kono
parents:
diff changeset
2407 char *result = NULL;
kono
parents:
diff changeset
2408 size_t total_sz = 0;
kono
parents:
diff changeset
2409 char buf[4096];
kono
parents:
diff changeset
2410 size_t sz;
kono
parents:
diff changeset
2411 FILE *f_in;
kono
parents:
diff changeset
2412
kono
parents:
diff changeset
2413 f_in = fopen (path, "r");
kono
parents:
diff changeset
2414 if (!f_in)
kono
parents:
diff changeset
2415 {
kono
parents:
diff changeset
2416 add_error (NULL, "unable to open %s for reading", path);
kono
parents:
diff changeset
2417 return NULL;
kono
parents:
diff changeset
2418 }
kono
parents:
diff changeset
2419
kono
parents:
diff changeset
2420 while ( (sz = fread (buf, 1, sizeof (buf), f_in)) )
kono
parents:
diff changeset
2421 {
kono
parents:
diff changeset
2422 size_t old_total_sz = total_sz;
kono
parents:
diff changeset
2423 total_sz += sz;
kono
parents:
diff changeset
2424 result = reinterpret_cast <char *> (xrealloc (result, total_sz + 1));
kono
parents:
diff changeset
2425 memcpy (result + old_total_sz, buf, sz);
kono
parents:
diff changeset
2426 }
kono
parents:
diff changeset
2427
kono
parents:
diff changeset
2428 if (!feof (f_in))
kono
parents:
diff changeset
2429 {
kono
parents:
diff changeset
2430 add_error (NULL, "error reading from %s", path);
kono
parents:
diff changeset
2431 free (result);
kono
parents:
diff changeset
2432 fclose (f_in);
kono
parents:
diff changeset
2433 return NULL;
kono
parents:
diff changeset
2434 }
kono
parents:
diff changeset
2435
kono
parents:
diff changeset
2436 fclose (f_in);
kono
parents:
diff changeset
2437
kono
parents:
diff changeset
2438 if (result)
kono
parents:
diff changeset
2439 {
kono
parents:
diff changeset
2440 result[total_sz] = '\0';
kono
parents:
diff changeset
2441 return result;
kono
parents:
diff changeset
2442 }
kono
parents:
diff changeset
2443 else
kono
parents:
diff changeset
2444 return xstrdup ("");
kono
parents:
diff changeset
2445 }
kono
parents:
diff changeset
2446
kono
parents:
diff changeset
2447 /* Part of playback::context::compile ().
kono
parents:
diff changeset
2448
kono
parents:
diff changeset
2449 We have a .s file; we want a .so file.
kono
parents:
diff changeset
2450 We could reuse parts of gcc/gcc.c to do this.
kono
parents:
diff changeset
2451 For now, just use the driver binary from the install, as
kono
parents:
diff changeset
2452 named in gcc-driver-name.h
kono
parents:
diff changeset
2453 e.g. "x86_64-unknown-linux-gnu-gcc-5.0.0". */
kono
parents:
diff changeset
2454
kono
parents:
diff changeset
2455 void
kono
parents:
diff changeset
2456 playback::context::
kono
parents:
diff changeset
2457 convert_to_dso (const char *ctxt_progname)
kono
parents:
diff changeset
2458 {
kono
parents:
diff changeset
2459 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2460
kono
parents:
diff changeset
2461 invoke_driver (ctxt_progname,
kono
parents:
diff changeset
2462 m_tempdir->get_path_s_file (),
kono
parents:
diff changeset
2463 m_tempdir->get_path_so_file (),
kono
parents:
diff changeset
2464 TV_ASSEMBLE,
kono
parents:
diff changeset
2465 true, /* bool shared, */
kono
parents:
diff changeset
2466 true);/* bool run_linker */
kono
parents:
diff changeset
2467 }
kono
parents:
diff changeset
2468
kono
parents:
diff changeset
2469 static const char * const gcc_driver_name = GCC_DRIVER_NAME;
kono
parents:
diff changeset
2470
kono
parents:
diff changeset
2471 void
kono
parents:
diff changeset
2472 playback::context::
kono
parents:
diff changeset
2473 invoke_driver (const char *ctxt_progname,
kono
parents:
diff changeset
2474 const char *input_file,
kono
parents:
diff changeset
2475 const char *output_file,
kono
parents:
diff changeset
2476 timevar_id_t tv_id,
kono
parents:
diff changeset
2477 bool shared,
kono
parents:
diff changeset
2478 bool run_linker)
kono
parents:
diff changeset
2479 {
kono
parents:
diff changeset
2480 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2481
kono
parents:
diff changeset
2482 bool embedded_driver
kono
parents:
diff changeset
2483 = !get_inner_bool_option (INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER);
kono
parents:
diff changeset
2484
kono
parents:
diff changeset
2485 /* Currently this lumps together both assembling and linking into
kono
parents:
diff changeset
2486 TV_ASSEMBLE. */
kono
parents:
diff changeset
2487 auto_timevar assemble_timevar (get_timer (), tv_id);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2488 auto_string_vec argvec;
111
kono
parents:
diff changeset
2489 #define ADD_ARG(arg) argvec.safe_push (xstrdup (arg))
kono
parents:
diff changeset
2490
kono
parents:
diff changeset
2491 ADD_ARG (gcc_driver_name);
kono
parents:
diff changeset
2492
kono
parents:
diff changeset
2493 add_multilib_driver_arguments (&argvec);
kono
parents:
diff changeset
2494
kono
parents:
diff changeset
2495 if (shared)
kono
parents:
diff changeset
2496 ADD_ARG ("-shared");
kono
parents:
diff changeset
2497
kono
parents:
diff changeset
2498 if (!run_linker)
kono
parents:
diff changeset
2499 ADD_ARG ("-c");
kono
parents:
diff changeset
2500
kono
parents:
diff changeset
2501 ADD_ARG (input_file);
kono
parents:
diff changeset
2502 ADD_ARG ("-o");
kono
parents:
diff changeset
2503 ADD_ARG (output_file);
kono
parents:
diff changeset
2504
kono
parents:
diff changeset
2505 /* Don't use the linker plugin.
kono
parents:
diff changeset
2506 If running with just a "make" and not a "make install", then we'd
kono
parents:
diff changeset
2507 run into
kono
parents:
diff changeset
2508 "fatal error: -fuse-linker-plugin, but liblto_plugin.so not found"
kono
parents:
diff changeset
2509 libto_plugin is a .la at build time, with it becoming installed with
kono
parents:
diff changeset
2510 ".so" suffix: i.e. it doesn't exist with a .so suffix until install
kono
parents:
diff changeset
2511 time. */
kono
parents:
diff changeset
2512 ADD_ARG ("-fno-use-linker-plugin");
kono
parents:
diff changeset
2513
kono
parents:
diff changeset
2514 #if defined (DARWIN_X86) || defined (DARWIN_PPC)
kono
parents:
diff changeset
2515 /* OS X's linker defaults to treating undefined symbols as errors.
kono
parents:
diff changeset
2516 If the context has any imported functions or globals they will be
kono
parents:
diff changeset
2517 undefined until the .so is dynamically-linked into the process.
kono
parents:
diff changeset
2518 Ensure that the driver passes in "-undefined dynamic_lookup" to the
kono
parents:
diff changeset
2519 linker. */
kono
parents:
diff changeset
2520 ADD_ARG ("-Wl,-undefined,dynamic_lookup");
kono
parents:
diff changeset
2521 #endif
kono
parents:
diff changeset
2522
kono
parents:
diff changeset
2523 if (0)
kono
parents:
diff changeset
2524 ADD_ARG ("-v");
kono
parents:
diff changeset
2525
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2526 /* Add any user-provided driver extra options. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2527
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2528 m_recording_ctxt->append_driver_options (&argvec);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2529
111
kono
parents:
diff changeset
2530 #undef ADD_ARG
kono
parents:
diff changeset
2531
kono
parents:
diff changeset
2532 /* pex_one's error-handling requires pname to be non-NULL. */
kono
parents:
diff changeset
2533 gcc_assert (ctxt_progname);
kono
parents:
diff changeset
2534
kono
parents:
diff changeset
2535 if (get_logger ())
kono
parents:
diff changeset
2536 for (unsigned i = 0; i < argvec.length (); i++)
kono
parents:
diff changeset
2537 get_logger ()->log ("argv[%i]: %s", i, argvec[i]);
kono
parents:
diff changeset
2538
kono
parents:
diff changeset
2539 if (embedded_driver)
kono
parents:
diff changeset
2540 invoke_embedded_driver (&argvec);
kono
parents:
diff changeset
2541 else
kono
parents:
diff changeset
2542 invoke_external_driver (ctxt_progname, &argvec);
kono
parents:
diff changeset
2543 }
kono
parents:
diff changeset
2544
kono
parents:
diff changeset
2545 void
kono
parents:
diff changeset
2546 playback::context::
kono
parents:
diff changeset
2547 invoke_embedded_driver (const vec <char *> *argvec)
kono
parents:
diff changeset
2548 {
kono
parents:
diff changeset
2549 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2550 driver d (true, /* can_finalize */
kono
parents:
diff changeset
2551 false); /* debug */
kono
parents:
diff changeset
2552 int result = d.main (argvec->length (),
kono
parents:
diff changeset
2553 const_cast <char **> (argvec->address ()));
kono
parents:
diff changeset
2554 d.finalize ();
kono
parents:
diff changeset
2555 if (result)
kono
parents:
diff changeset
2556 add_error (NULL, "error invoking gcc driver");
kono
parents:
diff changeset
2557 }
kono
parents:
diff changeset
2558
kono
parents:
diff changeset
2559 void
kono
parents:
diff changeset
2560 playback::context::
kono
parents:
diff changeset
2561 invoke_external_driver (const char *ctxt_progname,
kono
parents:
diff changeset
2562 vec <char *> *argvec)
kono
parents:
diff changeset
2563 {
kono
parents:
diff changeset
2564 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2565 const char *errmsg;
kono
parents:
diff changeset
2566 int exit_status = 0;
kono
parents:
diff changeset
2567 int err = 0;
kono
parents:
diff changeset
2568
kono
parents:
diff changeset
2569 /* pex argv arrays are NULL-terminated. */
kono
parents:
diff changeset
2570 argvec->safe_push (NULL);
kono
parents:
diff changeset
2571
kono
parents:
diff changeset
2572 errmsg = pex_one (PEX_SEARCH, /* int flags, */
kono
parents:
diff changeset
2573 gcc_driver_name,
kono
parents:
diff changeset
2574 const_cast <char *const *> (argvec->address ()),
kono
parents:
diff changeset
2575 ctxt_progname, /* const char *pname */
kono
parents:
diff changeset
2576 NULL, /* const char *outname */
kono
parents:
diff changeset
2577 NULL, /* const char *errname */
kono
parents:
diff changeset
2578 &exit_status, /* int *status */
kono
parents:
diff changeset
2579 &err); /* int *err*/
kono
parents:
diff changeset
2580 if (errmsg)
kono
parents:
diff changeset
2581 {
kono
parents:
diff changeset
2582 add_error (NULL, "error invoking gcc driver: %s", errmsg);
kono
parents:
diff changeset
2583 return;
kono
parents:
diff changeset
2584 }
kono
parents:
diff changeset
2585
kono
parents:
diff changeset
2586 /* pex_one can return a NULL errmsg when the executable wasn't
kono
parents:
diff changeset
2587 found (or doesn't exist), so trap these cases also. */
kono
parents:
diff changeset
2588 if (exit_status || err)
kono
parents:
diff changeset
2589 {
kono
parents:
diff changeset
2590 add_error (NULL,
kono
parents:
diff changeset
2591 "error invoking gcc driver: exit_status: %i err: %i",
kono
parents:
diff changeset
2592 exit_status, err);
kono
parents:
diff changeset
2593 add_error (NULL,
kono
parents:
diff changeset
2594 "whilst attempting to run a driver named: %s",
kono
parents:
diff changeset
2595 gcc_driver_name);
kono
parents:
diff changeset
2596 add_error (NULL,
kono
parents:
diff changeset
2597 "PATH was: %s",
kono
parents:
diff changeset
2598 getenv ("PATH"));
kono
parents:
diff changeset
2599 return;
kono
parents:
diff changeset
2600 }
kono
parents:
diff changeset
2601 }
kono
parents:
diff changeset
2602
kono
parents:
diff changeset
2603 /* Extract the target-specific MULTILIB_DEFAULTS to
kono
parents:
diff changeset
2604 multilib_defaults_raw for use by
kono
parents:
diff changeset
2605 playback::context::add_multilib_driver_arguments (). */
kono
parents:
diff changeset
2606
kono
parents:
diff changeset
2607 #ifndef MULTILIB_DEFAULTS
kono
parents:
diff changeset
2608 #define MULTILIB_DEFAULTS { "" }
kono
parents:
diff changeset
2609 #endif
kono
parents:
diff changeset
2610
kono
parents:
diff changeset
2611 static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
kono
parents:
diff changeset
2612
kono
parents:
diff changeset
2613 /* Helper function for playback::context::invoke_driver ().
kono
parents:
diff changeset
2614
kono
parents:
diff changeset
2615 32-bit and 64-bit multilib peer builds of libgccjit.so may share
kono
parents:
diff changeset
2616 a driver binary. We need to pass in options to the shared driver
kono
parents:
diff changeset
2617 to get the appropriate assembler/linker options for this multilib
kono
parents:
diff changeset
2618 peer. */
kono
parents:
diff changeset
2619
kono
parents:
diff changeset
2620 void
kono
parents:
diff changeset
2621 playback::context::
kono
parents:
diff changeset
2622 add_multilib_driver_arguments (vec <char *> *argvec)
kono
parents:
diff changeset
2623 {
kono
parents:
diff changeset
2624 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2625
kono
parents:
diff changeset
2626 /* Add copies of the arguments in multilib_defaults_raw to argvec,
kono
parents:
diff changeset
2627 prepending each with a "-". */
kono
parents:
diff changeset
2628 for (size_t i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
kono
parents:
diff changeset
2629 if (multilib_defaults_raw[i][0])
kono
parents:
diff changeset
2630 argvec->safe_push (concat ("-", multilib_defaults_raw[i], NULL));
kono
parents:
diff changeset
2631 }
kono
parents:
diff changeset
2632
kono
parents:
diff changeset
2633 /* Dynamically-link the built DSO file into this process, using dlopen.
kono
parents:
diff changeset
2634 Wrap it up within a jit::result *, and return that.
kono
parents:
diff changeset
2635 Return NULL if any errors occur, reporting them on this context. */
kono
parents:
diff changeset
2636
kono
parents:
diff changeset
2637 result *
kono
parents:
diff changeset
2638 playback::context::
kono
parents:
diff changeset
2639 dlopen_built_dso ()
kono
parents:
diff changeset
2640 {
kono
parents:
diff changeset
2641 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2642 auto_timevar load_timevar (get_timer (), TV_LOAD);
kono
parents:
diff changeset
2643 void *handle = NULL;
kono
parents:
diff changeset
2644 const char *error = NULL;
kono
parents:
diff changeset
2645 result *result_obj = NULL;
kono
parents:
diff changeset
2646
kono
parents:
diff changeset
2647 /* Clear any existing error. */
kono
parents:
diff changeset
2648 dlerror ();
kono
parents:
diff changeset
2649
kono
parents:
diff changeset
2650 handle = dlopen (m_tempdir->get_path_so_file (),
kono
parents:
diff changeset
2651 RTLD_NOW | RTLD_LOCAL);
kono
parents:
diff changeset
2652 if ((error = dlerror()) != NULL) {
kono
parents:
diff changeset
2653 add_error (NULL, "%s", error);
kono
parents:
diff changeset
2654 }
kono
parents:
diff changeset
2655 if (handle)
kono
parents:
diff changeset
2656 {
kono
parents:
diff changeset
2657 /* We've successfully dlopened the result; create a
kono
parents:
diff changeset
2658 jit::result object to wrap it.
kono
parents:
diff changeset
2659
kono
parents:
diff changeset
2660 We're done with the tempdir for now, but if the user
kono
parents:
diff changeset
2661 has requested debugging, the user's debugger might not
kono
parents:
diff changeset
2662 be capable of dealing with the .so file being unlinked
kono
parents:
diff changeset
2663 immediately, so keep it around until after the result
kono
parents:
diff changeset
2664 is released. We do this by handing over ownership of
kono
parents:
diff changeset
2665 the jit::tempdir to the result. See PR jit/64206. */
kono
parents:
diff changeset
2666 tempdir *handover_tempdir;
kono
parents:
diff changeset
2667 if (get_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO))
kono
parents:
diff changeset
2668 {
kono
parents:
diff changeset
2669 handover_tempdir = m_tempdir;
kono
parents:
diff changeset
2670 m_tempdir = NULL;
kono
parents:
diff changeset
2671 /* The tempdir will eventually be cleaned up in the
kono
parents:
diff changeset
2672 jit::result's dtor. */
kono
parents:
diff changeset
2673 log ("GCC_JIT_BOOL_OPTION_DEBUGINFO was set:"
kono
parents:
diff changeset
2674 " handing over tempdir to jit::result");
kono
parents:
diff changeset
2675 }
kono
parents:
diff changeset
2676 else
kono
parents:
diff changeset
2677 {
kono
parents:
diff changeset
2678 handover_tempdir = NULL;
kono
parents:
diff changeset
2679 /* ... and retain ownership of m_tempdir so we clean it
kono
parents:
diff changeset
2680 up it the playback::context's dtor. */
kono
parents:
diff changeset
2681 log ("GCC_JIT_BOOL_OPTION_DEBUGINFO was not set:"
kono
parents:
diff changeset
2682 " retaining ownership of tempdir");
kono
parents:
diff changeset
2683 }
kono
parents:
diff changeset
2684
kono
parents:
diff changeset
2685 result_obj = new result (get_logger (), handle, handover_tempdir);
kono
parents:
diff changeset
2686 }
kono
parents:
diff changeset
2687 else
kono
parents:
diff changeset
2688 result_obj = NULL;
kono
parents:
diff changeset
2689
kono
parents:
diff changeset
2690 return result_obj;
kono
parents:
diff changeset
2691 }
kono
parents:
diff changeset
2692
kono
parents:
diff changeset
2693 /* Top-level hook for playing back a recording context.
kono
parents:
diff changeset
2694
kono
parents:
diff changeset
2695 This plays back m_recording_ctxt, and, if no errors
kono
parents:
diff changeset
2696 occurred builds statement lists for and then postprocesses
kono
parents:
diff changeset
2697 every function in the result. */
kono
parents:
diff changeset
2698
kono
parents:
diff changeset
2699 void
kono
parents:
diff changeset
2700 playback::context::
kono
parents:
diff changeset
2701 replay ()
kono
parents:
diff changeset
2702 {
kono
parents:
diff changeset
2703 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2704 /* Adapted from c-common.c:c_common_nodes_and_builtins. */
kono
parents:
diff changeset
2705 tree array_domain_type = build_index_type (size_int (200));
kono
parents:
diff changeset
2706 m_char_array_type_node
kono
parents:
diff changeset
2707 = build_array_type (char_type_node, array_domain_type);
kono
parents:
diff changeset
2708
kono
parents:
diff changeset
2709 m_const_char_ptr
kono
parents:
diff changeset
2710 = build_pointer_type (build_qualified_type (char_type_node,
kono
parents:
diff changeset
2711 TYPE_QUAL_CONST));
kono
parents:
diff changeset
2712
kono
parents:
diff changeset
2713 /* Replay the recorded events: */
kono
parents:
diff changeset
2714 timevar_push (TV_JIT_REPLAY);
kono
parents:
diff changeset
2715
kono
parents:
diff changeset
2716 m_recording_ctxt->replay_into (this);
kono
parents:
diff changeset
2717
kono
parents:
diff changeset
2718 /* Clean away the temporary references from recording objects
kono
parents:
diff changeset
2719 to playback objects. We have to do this now since the
kono
parents:
diff changeset
2720 latter are GC-allocated, but the former don't mark these
kono
parents:
diff changeset
2721 refs. Hence we must stop using them before the GC can run. */
kono
parents:
diff changeset
2722 m_recording_ctxt->disassociate_from_playback ();
kono
parents:
diff changeset
2723
kono
parents:
diff changeset
2724 /* The builtins_manager, if any, is associated with the recording::context
kono
parents:
diff changeset
2725 and might be reused for future compiles on other playback::contexts,
kono
parents:
diff changeset
2726 but its m_attributes array is not GTY-labeled and hence will become
kono
parents:
diff changeset
2727 nonsense if the GC runs. Purge this state. */
kono
parents:
diff changeset
2728 builtins_manager *bm = get_builtins_manager ();
kono
parents:
diff changeset
2729 if (bm)
kono
parents:
diff changeset
2730 bm->finish_playback ();
kono
parents:
diff changeset
2731
kono
parents:
diff changeset
2732 timevar_pop (TV_JIT_REPLAY);
kono
parents:
diff changeset
2733
kono
parents:
diff changeset
2734 if (!errors_occurred ())
kono
parents:
diff changeset
2735 {
kono
parents:
diff changeset
2736 int i;
kono
parents:
diff changeset
2737 function *func;
kono
parents:
diff changeset
2738
kono
parents:
diff changeset
2739 /* No GC can happen yet; process the cached source locations. */
kono
parents:
diff changeset
2740 handle_locations ();
kono
parents:
diff changeset
2741
kono
parents:
diff changeset
2742 /* We've now created tree nodes for the stmts in the various blocks
kono
parents:
diff changeset
2743 in each function, but we haven't built each function's single stmt
kono
parents:
diff changeset
2744 list yet. Do so now. */
kono
parents:
diff changeset
2745 FOR_EACH_VEC_ELT (m_functions, i, func)
kono
parents:
diff changeset
2746 func->build_stmt_list ();
kono
parents:
diff changeset
2747
kono
parents:
diff changeset
2748 /* No GC can have happened yet. */
kono
parents:
diff changeset
2749
kono
parents:
diff changeset
2750 /* Postprocess the functions. This could trigger GC. */
kono
parents:
diff changeset
2751 FOR_EACH_VEC_ELT (m_functions, i, func)
kono
parents:
diff changeset
2752 {
kono
parents:
diff changeset
2753 gcc_assert (func);
kono
parents:
diff changeset
2754 func->postprocess ();
kono
parents:
diff changeset
2755 }
kono
parents:
diff changeset
2756 }
kono
parents:
diff changeset
2757 }
kono
parents:
diff changeset
2758
kono
parents:
diff changeset
2759 /* Dump the generated .s file to stderr. */
kono
parents:
diff changeset
2760
kono
parents:
diff changeset
2761 void
kono
parents:
diff changeset
2762 playback::context::
kono
parents:
diff changeset
2763 dump_generated_code ()
kono
parents:
diff changeset
2764 {
kono
parents:
diff changeset
2765 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2766 char buf[4096];
kono
parents:
diff changeset
2767 size_t sz;
kono
parents:
diff changeset
2768 FILE *f_in = fopen (get_path_s_file (), "r");
kono
parents:
diff changeset
2769 if (!f_in)
kono
parents:
diff changeset
2770 return;
kono
parents:
diff changeset
2771
kono
parents:
diff changeset
2772 while ( (sz = fread (buf, 1, sizeof (buf), f_in)) )
kono
parents:
diff changeset
2773 fwrite (buf, 1, sz, stderr);
kono
parents:
diff changeset
2774
kono
parents:
diff changeset
2775 fclose (f_in);
kono
parents:
diff changeset
2776 }
kono
parents:
diff changeset
2777
kono
parents:
diff changeset
2778 /* Get the supposed path of the notional "fake.c" file within the
kono
parents:
diff changeset
2779 tempdir. This file doesn't exist, but the rest of the compiler
kono
parents:
diff changeset
2780 needs a name. */
kono
parents:
diff changeset
2781
kono
parents:
diff changeset
2782 const char *
kono
parents:
diff changeset
2783 playback::context::
kono
parents:
diff changeset
2784 get_path_c_file () const
kono
parents:
diff changeset
2785 {
kono
parents:
diff changeset
2786 return m_tempdir->get_path_c_file ();
kono
parents:
diff changeset
2787 }
kono
parents:
diff changeset
2788
kono
parents:
diff changeset
2789 /* Get the path of the assembler output file "fake.s" file within the
kono
parents:
diff changeset
2790 tempdir. */
kono
parents:
diff changeset
2791
kono
parents:
diff changeset
2792 const char *
kono
parents:
diff changeset
2793 playback::context::
kono
parents:
diff changeset
2794 get_path_s_file () const
kono
parents:
diff changeset
2795 {
kono
parents:
diff changeset
2796 return m_tempdir->get_path_s_file ();
kono
parents:
diff changeset
2797 }
kono
parents:
diff changeset
2798
kono
parents:
diff changeset
2799 /* Get the path of the DSO object file "fake.so" file within the
kono
parents:
diff changeset
2800 tempdir. */
kono
parents:
diff changeset
2801
kono
parents:
diff changeset
2802 const char *
kono
parents:
diff changeset
2803 playback::context::
kono
parents:
diff changeset
2804 get_path_so_file () const
kono
parents:
diff changeset
2805 {
kono
parents:
diff changeset
2806 return m_tempdir->get_path_so_file ();
kono
parents:
diff changeset
2807 }
kono
parents:
diff changeset
2808
kono
parents:
diff changeset
2809 /* qsort comparator for comparing pairs of playback::source_line *,
kono
parents:
diff changeset
2810 ordering them by line number. */
kono
parents:
diff changeset
2811
kono
parents:
diff changeset
2812 static int
kono
parents:
diff changeset
2813 line_comparator (const void *lhs, const void *rhs)
kono
parents:
diff changeset
2814 {
kono
parents:
diff changeset
2815 const playback::source_line *line_lhs = \
kono
parents:
diff changeset
2816 *static_cast<const playback::source_line * const*> (lhs);
kono
parents:
diff changeset
2817 const playback::source_line *line_rhs = \
kono
parents:
diff changeset
2818 *static_cast<const playback::source_line * const*> (rhs);
kono
parents:
diff changeset
2819 return line_lhs->get_line_num () - line_rhs->get_line_num ();
kono
parents:
diff changeset
2820 }
kono
parents:
diff changeset
2821
kono
parents:
diff changeset
2822 /* qsort comparator for comparing pairs of playback::location *,
kono
parents:
diff changeset
2823 ordering them by column number. */
kono
parents:
diff changeset
2824
kono
parents:
diff changeset
2825 static int
kono
parents:
diff changeset
2826 location_comparator (const void *lhs, const void *rhs)
kono
parents:
diff changeset
2827 {
kono
parents:
diff changeset
2828 const playback::location *loc_lhs = \
kono
parents:
diff changeset
2829 *static_cast<const playback::location * const *> (lhs);
kono
parents:
diff changeset
2830 const playback::location *loc_rhs = \
kono
parents:
diff changeset
2831 *static_cast<const playback::location * const *> (rhs);
kono
parents:
diff changeset
2832 return loc_lhs->get_column_num () - loc_rhs->get_column_num ();
kono
parents:
diff changeset
2833 }
kono
parents:
diff changeset
2834
kono
parents:
diff changeset
2835 /* Our API allows locations to be created in arbitrary orders, but the
kono
parents:
diff changeset
2836 linemap API requires locations to be created in ascending order
kono
parents:
diff changeset
2837 as if we were tokenizing files.
kono
parents:
diff changeset
2838
kono
parents:
diff changeset
2839 This hook sorts all of the locations that have been created, and
kono
parents:
diff changeset
2840 calls into the linemap API, creating linemap entries in sorted order
kono
parents:
diff changeset
2841 for our locations. */
kono
parents:
diff changeset
2842
kono
parents:
diff changeset
2843 void
kono
parents:
diff changeset
2844 playback::context::
kono
parents:
diff changeset
2845 handle_locations ()
kono
parents:
diff changeset
2846 {
kono
parents:
diff changeset
2847 /* Create the source code locations, following the ordering rules
kono
parents:
diff changeset
2848 imposed by the linemap API.
kono
parents:
diff changeset
2849
kono
parents:
diff changeset
2850 line_table is a global. */
kono
parents:
diff changeset
2851 JIT_LOG_SCOPE (get_logger ());
kono
parents:
diff changeset
2852 int i;
kono
parents:
diff changeset
2853 source_file *file;
kono
parents:
diff changeset
2854
kono
parents:
diff changeset
2855 FOR_EACH_VEC_ELT (m_source_files, i, file)
kono
parents:
diff changeset
2856 {
kono
parents:
diff changeset
2857 linemap_add (line_table, LC_ENTER, false, file->get_filename (), 0);
kono
parents:
diff changeset
2858
kono
parents:
diff changeset
2859 /* Sort lines by ascending line numbers. */
kono
parents:
diff changeset
2860 file->m_source_lines.qsort (&line_comparator);
kono
parents:
diff changeset
2861
kono
parents:
diff changeset
2862 int j;
kono
parents:
diff changeset
2863 source_line *line;
kono
parents:
diff changeset
2864 FOR_EACH_VEC_ELT (file->m_source_lines, j, line)
kono
parents:
diff changeset
2865 {
kono
parents:
diff changeset
2866 int k;
kono
parents:
diff changeset
2867 location *loc;
kono
parents:
diff changeset
2868
kono
parents:
diff changeset
2869 /* Sort locations in line by ascending column numbers. */
kono
parents:
diff changeset
2870 line->m_locations.qsort (&location_comparator);
kono
parents:
diff changeset
2871
kono
parents:
diff changeset
2872 /* Determine maximum column within this line. */
kono
parents:
diff changeset
2873 gcc_assert (line->m_locations.length () > 0);
kono
parents:
diff changeset
2874 location *final_column =
kono
parents:
diff changeset
2875 line->m_locations[line->m_locations.length () - 1];
kono
parents:
diff changeset
2876 int max_col = final_column->get_column_num ();
kono
parents:
diff changeset
2877
kono
parents:
diff changeset
2878 linemap_line_start (line_table, line->get_line_num (), max_col);
kono
parents:
diff changeset
2879 FOR_EACH_VEC_ELT (line->m_locations, k, loc)
kono
parents:
diff changeset
2880 {
kono
parents:
diff changeset
2881 loc->m_srcloc = \
kono
parents:
diff changeset
2882 linemap_position_for_column (line_table, loc->get_column_num ());
kono
parents:
diff changeset
2883 }
kono
parents:
diff changeset
2884 }
kono
parents:
diff changeset
2885
kono
parents:
diff changeset
2886 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
kono
parents:
diff changeset
2887 }
kono
parents:
diff changeset
2888
kono
parents:
diff changeset
2889 /* line_table should now be populated; every playback::location should
kono
parents:
diff changeset
2890 now have an m_srcloc. */
kono
parents:
diff changeset
2891
kono
parents:
diff changeset
2892 /* Now assign them to tree nodes as appropriate. */
kono
parents:
diff changeset
2893 std::pair<tree, location *> *cached_location;
kono
parents:
diff changeset
2894
kono
parents:
diff changeset
2895 FOR_EACH_VEC_ELT (m_cached_locations, i, cached_location)
kono
parents:
diff changeset
2896 {
kono
parents:
diff changeset
2897 tree t = cached_location->first;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2898 location_t srcloc = cached_location->second->m_srcloc;
111
kono
parents:
diff changeset
2899
kono
parents:
diff changeset
2900 /* This covers expressions: */
kono
parents:
diff changeset
2901 if (CAN_HAVE_LOCATION_P (t))
kono
parents:
diff changeset
2902 SET_EXPR_LOCATION (t, srcloc);
kono
parents:
diff changeset
2903 else if (CODE_CONTAINS_STRUCT(TREE_CODE(t), TS_DECL_MINIMAL))
kono
parents:
diff changeset
2904 DECL_SOURCE_LOCATION (t) = srcloc;
kono
parents:
diff changeset
2905 else
kono
parents:
diff changeset
2906 {
kono
parents:
diff changeset
2907 /* Don't know how to set location on this node. */
kono
parents:
diff changeset
2908 }
kono
parents:
diff changeset
2909 }
kono
parents:
diff changeset
2910 }
kono
parents:
diff changeset
2911
kono
parents:
diff changeset
2912 /* We handle errors on a playback::context by adding them to the
kono
parents:
diff changeset
2913 corresponding recording::context. */
kono
parents:
diff changeset
2914
kono
parents:
diff changeset
2915 void
kono
parents:
diff changeset
2916 playback::context::
kono
parents:
diff changeset
2917 add_error (location *loc, const char *fmt, ...)
kono
parents:
diff changeset
2918 {
kono
parents:
diff changeset
2919 va_list ap;
kono
parents:
diff changeset
2920 va_start (ap, fmt);
kono
parents:
diff changeset
2921 m_recording_ctxt->add_error_va (loc ? loc->get_recording_loc () : NULL,
kono
parents:
diff changeset
2922 fmt, ap);
kono
parents:
diff changeset
2923 va_end (ap);
kono
parents:
diff changeset
2924 }
kono
parents:
diff changeset
2925
kono
parents:
diff changeset
2926 /* We handle errors on a playback::context by adding them to the
kono
parents:
diff changeset
2927 corresponding recording::context. */
kono
parents:
diff changeset
2928
kono
parents:
diff changeset
2929 void
kono
parents:
diff changeset
2930 playback::context::
kono
parents:
diff changeset
2931 add_error_va (location *loc, const char *fmt, va_list ap)
kono
parents:
diff changeset
2932 {
kono
parents:
diff changeset
2933 m_recording_ctxt->add_error_va (loc ? loc->get_recording_loc () : NULL,
kono
parents:
diff changeset
2934 fmt, ap);
kono
parents:
diff changeset
2935 }
kono
parents:
diff changeset
2936
kono
parents:
diff changeset
2937 /* Report a diagnostic up to the jit context as an error,
kono
parents:
diff changeset
2938 so that the compilation is treated as a failure.
kono
parents:
diff changeset
2939 For now, any kind of diagnostic is treated as an error by the jit
kono
parents:
diff changeset
2940 API. */
kono
parents:
diff changeset
2941
kono
parents:
diff changeset
2942 void
kono
parents:
diff changeset
2943 playback::context::
kono
parents:
diff changeset
2944 add_diagnostic (struct diagnostic_context *diag_context,
kono
parents:
diff changeset
2945 struct diagnostic_info *diagnostic)
kono
parents:
diff changeset
2946 {
kono
parents:
diff changeset
2947 /* At this point the text has been formatted into the pretty-printer's
kono
parents:
diff changeset
2948 output buffer. */
kono
parents:
diff changeset
2949 pretty_printer *pp = diag_context->printer;
kono
parents:
diff changeset
2950 const char *text = pp_formatted_text (pp);
kono
parents:
diff changeset
2951
kono
parents:
diff changeset
2952 /* Get location information (if any) from the diagnostic.
kono
parents:
diff changeset
2953 The recording::context::add_error[_va] methods require a
kono
parents:
diff changeset
2954 recording::location. We can't lookup the playback::location
kono
parents:
diff changeset
2955 from the file/line/column since any playback location instances
kono
parents:
diff changeset
2956 may have been garbage-collected away by now, so instead we create
kono
parents:
diff changeset
2957 another recording::location directly. */
kono
parents:
diff changeset
2958 location_t gcc_loc = diagnostic_location (diagnostic);
kono
parents:
diff changeset
2959 recording::location *rec_loc = NULL;
kono
parents:
diff changeset
2960 if (gcc_loc)
kono
parents:
diff changeset
2961 {
kono
parents:
diff changeset
2962 expanded_location exploc = expand_location (gcc_loc);
kono
parents:
diff changeset
2963 if (exploc.file)
kono
parents:
diff changeset
2964 rec_loc = m_recording_ctxt->new_location (exploc.file,
kono
parents:
diff changeset
2965 exploc.line,
kono
parents:
diff changeset
2966 exploc.column,
kono
parents:
diff changeset
2967 false);
kono
parents:
diff changeset
2968 }
kono
parents:
diff changeset
2969
kono
parents:
diff changeset
2970 m_recording_ctxt->add_error (rec_loc, "%s", text);
kono
parents:
diff changeset
2971 pp_clear_output_area (pp);
kono
parents:
diff changeset
2972 }
kono
parents:
diff changeset
2973
kono
parents:
diff changeset
2974 /* Dealing with the linemap API. */
kono
parents:
diff changeset
2975
kono
parents:
diff changeset
2976 /* Construct a playback::location for a recording::location, if it
kono
parents:
diff changeset
2977 doesn't exist already. */
kono
parents:
diff changeset
2978
kono
parents:
diff changeset
2979 playback::location *
kono
parents:
diff changeset
2980 playback::context::
kono
parents:
diff changeset
2981 new_location (recording::location *rloc,
kono
parents:
diff changeset
2982 const char *filename,
kono
parents:
diff changeset
2983 int line,
kono
parents:
diff changeset
2984 int column)
kono
parents:
diff changeset
2985 {
kono
parents:
diff changeset
2986 /* Get the source_file for filename, creating if necessary. */
kono
parents:
diff changeset
2987 source_file *src_file = get_source_file (filename);
kono
parents:
diff changeset
2988 /* Likewise for the line within the file. */
kono
parents:
diff changeset
2989 source_line *src_line = src_file->get_source_line (line);
kono
parents:
diff changeset
2990 /* Likewise for the column within the line. */
kono
parents:
diff changeset
2991 location *loc = src_line->get_location (rloc, column);
kono
parents:
diff changeset
2992 return loc;
kono
parents:
diff changeset
2993 }
kono
parents:
diff changeset
2994
kono
parents:
diff changeset
2995 /* Deferred setting of the location for a given tree, by adding the
kono
parents:
diff changeset
2996 (tree, playback::location) pair to a list of deferred associations.
kono
parents:
diff changeset
2997 We will actually set the location on the tree later on once
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2998 the location_t for the playback::location exists. */
111
kono
parents:
diff changeset
2999
kono
parents:
diff changeset
3000 void
kono
parents:
diff changeset
3001 playback::context::
kono
parents:
diff changeset
3002 set_tree_location (tree t, location *loc)
kono
parents:
diff changeset
3003 {
kono
parents:
diff changeset
3004 gcc_assert (loc);
kono
parents:
diff changeset
3005 m_cached_locations.safe_push (std::make_pair (t, loc));
kono
parents:
diff changeset
3006 }
kono
parents:
diff changeset
3007
kono
parents:
diff changeset
3008
kono
parents:
diff changeset
3009 /* Construct a playback::source_file for the given source
kono
parents:
diff changeset
3010 filename, if it doesn't exist already. */
kono
parents:
diff changeset
3011
kono
parents:
diff changeset
3012 playback::source_file *
kono
parents:
diff changeset
3013 playback::context::
kono
parents:
diff changeset
3014 get_source_file (const char *filename)
kono
parents:
diff changeset
3015 {
kono
parents:
diff changeset
3016 /* Locate the file.
kono
parents:
diff changeset
3017 For simplicitly, this is currently a linear search.
kono
parents:
diff changeset
3018 Replace with a hash if this shows up in the profile. */
kono
parents:
diff changeset
3019 int i;
kono
parents:
diff changeset
3020 source_file *file;
kono
parents:
diff changeset
3021 tree ident_filename = get_identifier (filename);
kono
parents:
diff changeset
3022
kono
parents:
diff changeset
3023 FOR_EACH_VEC_ELT (m_source_files, i, file)
kono
parents:
diff changeset
3024 if (file->filename_as_tree () == ident_filename)
kono
parents:
diff changeset
3025 return file;
kono
parents:
diff changeset
3026
kono
parents:
diff changeset
3027 /* Not found. */
kono
parents:
diff changeset
3028 file = new source_file (ident_filename);
kono
parents:
diff changeset
3029 m_source_files.safe_push (file);
kono
parents:
diff changeset
3030 return file;
kono
parents:
diff changeset
3031 }
kono
parents:
diff changeset
3032
kono
parents:
diff changeset
3033 /* Constructor for gcc::jit::playback::source_file. */
kono
parents:
diff changeset
3034
kono
parents:
diff changeset
3035 playback::source_file::source_file (tree filename) :
kono
parents:
diff changeset
3036 m_source_lines (),
kono
parents:
diff changeset
3037 m_filename (filename)
kono
parents:
diff changeset
3038 {
kono
parents:
diff changeset
3039 }
kono
parents:
diff changeset
3040
kono
parents:
diff changeset
3041 /* Don't leak vec's internal buffer (in non-GC heap) when we are
kono
parents:
diff changeset
3042 GC-ed. */
kono
parents:
diff changeset
3043
kono
parents:
diff changeset
3044 void
kono
parents:
diff changeset
3045 playback::source_file::finalizer ()
kono
parents:
diff changeset
3046 {
kono
parents:
diff changeset
3047 m_source_lines.release ();
kono
parents:
diff changeset
3048 }
kono
parents:
diff changeset
3049
kono
parents:
diff changeset
3050 /* Construct a playback::source_line for the given line
kono
parents:
diff changeset
3051 within this source file, if one doesn't exist already. */
kono
parents:
diff changeset
3052
kono
parents:
diff changeset
3053 playback::source_line *
kono
parents:
diff changeset
3054 playback::source_file::
kono
parents:
diff changeset
3055 get_source_line (int line_num)
kono
parents:
diff changeset
3056 {
kono
parents:
diff changeset
3057 /* Locate the line.
kono
parents:
diff changeset
3058 For simplicitly, this is currently a linear search.
kono
parents:
diff changeset
3059 Replace with a hash if this shows up in the profile. */
kono
parents:
diff changeset
3060 int i;
kono
parents:
diff changeset
3061 source_line *line;
kono
parents:
diff changeset
3062
kono
parents:
diff changeset
3063 FOR_EACH_VEC_ELT (m_source_lines, i, line)
kono
parents:
diff changeset
3064 if (line->get_line_num () == line_num)
kono
parents:
diff changeset
3065 return line;
kono
parents:
diff changeset
3066
kono
parents:
diff changeset
3067 /* Not found. */
kono
parents:
diff changeset
3068 line = new source_line (this, line_num);
kono
parents:
diff changeset
3069 m_source_lines.safe_push (line);
kono
parents:
diff changeset
3070 return line;
kono
parents:
diff changeset
3071 }
kono
parents:
diff changeset
3072
kono
parents:
diff changeset
3073 /* Constructor for gcc::jit::playback::source_line. */
kono
parents:
diff changeset
3074
kono
parents:
diff changeset
3075 playback::source_line::source_line (source_file *file, int line_num) :
kono
parents:
diff changeset
3076 m_locations (),
kono
parents:
diff changeset
3077 m_source_file (file),
kono
parents:
diff changeset
3078 m_line_num (line_num)
kono
parents:
diff changeset
3079 {
kono
parents:
diff changeset
3080 }
kono
parents:
diff changeset
3081
kono
parents:
diff changeset
3082 /* Don't leak vec's internal buffer (in non-GC heap) when we are
kono
parents:
diff changeset
3083 GC-ed. */
kono
parents:
diff changeset
3084
kono
parents:
diff changeset
3085 void
kono
parents:
diff changeset
3086 playback::source_line::finalizer ()
kono
parents:
diff changeset
3087 {
kono
parents:
diff changeset
3088 m_locations.release ();
kono
parents:
diff changeset
3089 }
kono
parents:
diff changeset
3090
kono
parents:
diff changeset
3091 /* Construct a playback::location for the given column
kono
parents:
diff changeset
3092 within this line of a specific source file, if one doesn't exist
kono
parents:
diff changeset
3093 already. */
kono
parents:
diff changeset
3094
kono
parents:
diff changeset
3095 playback::location *
kono
parents:
diff changeset
3096 playback::source_line::
kono
parents:
diff changeset
3097 get_location (recording::location *rloc, int column_num)
kono
parents:
diff changeset
3098 {
kono
parents:
diff changeset
3099 int i;
kono
parents:
diff changeset
3100 location *loc;
kono
parents:
diff changeset
3101
kono
parents:
diff changeset
3102 /* Another linear search that probably should be a hash table. */
kono
parents:
diff changeset
3103 FOR_EACH_VEC_ELT (m_locations, i, loc)
kono
parents:
diff changeset
3104 if (loc->get_column_num () == column_num)
kono
parents:
diff changeset
3105 return loc;
kono
parents:
diff changeset
3106
kono
parents:
diff changeset
3107 /* Not found. */
kono
parents:
diff changeset
3108 loc = new location (rloc, this, column_num);
kono
parents:
diff changeset
3109 m_locations.safe_push (loc);
kono
parents:
diff changeset
3110 return loc;
kono
parents:
diff changeset
3111 }
kono
parents:
diff changeset
3112
kono
parents:
diff changeset
3113 /* Constructor for gcc::jit::playback::location. */
kono
parents:
diff changeset
3114
kono
parents:
diff changeset
3115 playback::location::location (recording::location *loc,
kono
parents:
diff changeset
3116 source_line *line,
kono
parents:
diff changeset
3117 int column_num) :
kono
parents:
diff changeset
3118 m_srcloc (UNKNOWN_LOCATION),
kono
parents:
diff changeset
3119 m_recording_loc (loc),
kono
parents:
diff changeset
3120 m_line (line),
kono
parents:
diff changeset
3121 m_column_num(column_num)
kono
parents:
diff changeset
3122 {
kono
parents:
diff changeset
3123 }
kono
parents:
diff changeset
3124
kono
parents:
diff changeset
3125 /* The active gcc::jit::playback::context instance. This is a singleton,
kono
parents:
diff changeset
3126 guarded by jit_mutex. */
kono
parents:
diff changeset
3127
kono
parents:
diff changeset
3128 playback::context *active_playback_ctxt;
kono
parents:
diff changeset
3129
kono
parents:
diff changeset
3130 } // namespace gcc::jit
kono
parents:
diff changeset
3131
kono
parents:
diff changeset
3132 } // namespace gcc