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