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