annotate gcc/jit/jit-playback.c @ 111:04ced10e8804

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